결정트리란

결정트리는 선형 회귀와 로지스틱 회귀처럼 특성을 가중치와 곱하는 대신
특성에 대한 질문에 따라 데이터를 나눕니다.
예를 들어
결정 트리가 온도 특성을 가지고 데이터를 두 그룹으로 나눌 수 있다고 칠 때
온도가 20도 이상인 그룹과 20도 이하인 그룹이 있으면, 각 그룹을 계절 기반으로 나눌 수 있습니다
겨울에 경우에는 그렇지 않은 경우(70 이하)이지만
더 정확한 데이터 분별을 위해 데이터를 네 개의 그룹(봄, 여름, 가을, 겨울)으로 나눈다면 어떨까요?
이렇게 알고리즘이 일정 수준의 정확도에 도달할 때까지 데이터를 새로운 그룹으로 나누는 과정이 계속됩니다
결정 트리는 훈련 세트에 있는 각 샘플을 정확한 타깃에 매핑할 때까지 수천 개의 그룹을 만들 수 있습니다.
훈련 세트에 대해서 100% 정확도를 달성한다는 의미입니다 (그러나 새로운 데이터는 절대 불가능합니다 ㅠ)
즉 과적합이 되기 매우 쉽습니다. - (이 때문에 XGBoost를 사용할 때 빛을 발합니다)
결정트리 구조

루트 노드 (Root Node) : 트리의 시작 지점으로, 모든 데이터가 시작되는 곳입니다.
분기 (Branches) : 루트 노드에서 시작하여 각 노드마다 하위 노드로 나뉩니다.
각 분기는 하나의 특성 (데이터의 속성)과 그 특성의 값을 기반으로 데이터를 분할합니다.
내부 노드 (Internal Node) : 루트 노드를 제외한 모든 노드, 데이터를 분류하기 위한 특성과 값을 가지고 있습니다.
리프 노드 (Leaf Node) : 더 이상 분할되지 않고 최종적으로 데이터가 할당되는 노드입니다.
결정 노드 (Decision node) : 데이터를 분할하기 위한 특성과 분할 기준을 나타냅니다.
지니 불순도 (gini impurity)
지니 불순도는 결정트리가 어떻게 그룹을 나눌지 결정하는데 사용합니다.
특정 집합에서 한 항목을 뽑아 무작위로 라벨 추정시 틀릴 확률을 측정합니다
결정트리의 목표는 불순도 값이 가장 낮은 그룹을 찾는 것입니다
지니 불순도가 0.5이면 클래스 간의 샘플 개수가 동일한 경우입니다.
지니 불순도가 0이면 하나의 클래스로만 이루어진 노드겠죠

pi는 전체 샘플 중에서 해당 클래스 샘플의 비율이고 c는 클래스 총 개수입니다.
아래 사진을 예시로 설명하자면

각 항아리는 10개의 구슬이 있고 클래스는 2개(빨강, 파랑)가 있습니다.
각 항아리의 지니 불순도를 구해보면
항아리 1 불순도 = 1 - (1)**2 - (0)**2 = 0
항아리 2 불순도 = 1 - (0.5)**2 - (0.5)**2 = 0.5
항아리 3 불순도 = 1 - (0)**2 - (1)**2 = 0
이러한 불순도를 가지고 있는 것을 알 수 있습니다.
불순도가 크든, 작든 클래스를 나눠야하는 결정트리의 지니 불순도 최대값은 0.5 입니다.
엔트로피 지수 (Entropy Index)
엔트로피는 결정트리가 어떻게 그룹을 나눌지 결정하는데 사용되는 두번째 방법입니다.
확률 분포의 무질서도 또는 정보의 분포를 측정합니다
지니 불순도와 마찬가지로 수치가 낮을수록 클래스를 일관성있게 분류할 수 있습니다.

결정트리 파라미터
from sklearn.tree import DecisionTreeClassifier
tree = DecisionTreeClassifier(
criterion="gini", # 분할 기준: 지니 불순도 (기본값 gini)
max_depth=3, # 최대 트리 깊이 (기본값 None)
min_samples_split=2, # 노드 분할을 위한 최소 샘플 수 (기본값 2)
min_samples_leaf=1, # 리프 노드의 최소 샘플 수 (기본값 1)
max_features=None, # 노드 분할에 사용할 최대 특성 수 (None은 전체 특성 사용)
splitter="best", # 노드 분할 전략: "best" 또는 "random"
min_impurity_decrease=0.0, # 분할 기준 불순도 감소 최소값
class_weight=None, # 클래스 가중치
presort=False, # 데이터 미리 정렬 여부 (사용하지 않음)
ccp_alpha=0.0 # 최소 비용 복잡성 가지치기 매개변수
)
파라미터 | 설명 |
criterion | 결정트리가 데이터를 분류할 때 사용하는 방법을 정합니다 |
max_depth | 결정트리의 최대 깊이를 제한합니다 |
min_samples_split | 노드를 분할하기 위해 필요한 최소 샘플 수를 지정합니다 이 값보다 작은 샘플 수를 가진 노드는 더 이상 분할되지 않습니다 |
min_samples_leaf | 리프 노드가 가져야 하는 최소 샘플 수를 지정합니다 |
max_features | 각 노드에서 분할을 수행할 때 고려할 최대 특성 수를 제한합니다 auto로 설정하면 sqrt(전체 특성 수)로 설정됩니다. |
splitter | 노드를 어떻게 분할할지 선택하는 전략을 지정합니다 best는 가장 좋은 분할을 선택하고 random은 무작위로 분할을 수행합니다 |
min_impurity_decrease | 노드를 분할하기 위한 최소한의 불순도 감수를 지정합니다. 불순도 감소가 이 값보다 작은 분할은 수행되지 않습니다 |
class_weight | 불균형한 클래스 분포를 다룰 때 각 클래스에 대한 가중치를 지정합니다. balanced로 설정하면 자동으로 클래스에 반비례하는 가중치가 설정됩니다. |
presort | 데이터를 미리 정렬하여 노드 분할 속도를 높일지 여부를 결정합니다. True로 설정하면 분할 속도를 높이지만, 큰 데이터셋에서는 성능 저하가 생길 수 있습니다 |
ccp_alpha | 비용 복잡성 가지치기(Cost complexity Pruning)를 조하여 과적합을 해결합니다 |
결정트리 시각화
결정트리를 시각화하기 위해서는 사이킷런 제공 함수인 export_graphviz를 사용해야 합니다
그리고 그 결과를 Graphviz 라이브러리를 이용해 시각화 해야 합니다.
from sklearn.tree import DecisionTreeClassifier # 결정 트리
from sklearn.tree import export_graphviz
import graphviz
tree = DecisionTreeClassifier()
tree.fit(X, y)
dot_data = export_graphviz(tree, out_file=None,
feature_names=iris.feature_names,
class_names=iris.target_names,
filled=True, rounded=True,
special_characters=True)
# Graphviz로 시각화
graph = graphviz.Source(dot_data)
graph.render("pdf name")
export_graphviz 함수에 모델을 넣고
out_file : 출력 파일의 경로를 지정합니다. None으로 해 놨기에 변수에 저장했습니다.
feature_names : 특성의 이름들을 제공합니다. (iris dataset으로 예를들었습니다)
class_names : 클래스(타겟)의 이름들을 제공합니다
filled : 노드의 색상을 클래스별로 구분하여 채웁니다
rounded : 노드 상자를 둥글게 표시합니다
special_characters : 특수 문자를 처리합니다
위 파라미터를 설정 한 뒤
graphviz 라이브러리의 Source 함수로 시각화를 처리합니다.
마지막으로 render 함수로 그래프 파일을 저장합니다. ( 저장된 파일은 pdf 형태로 저장됩니다)
'인공지능 > 머신러닝' 카테고리의 다른 글
[머신러닝] 앙상블 - 에이다부스트 (AdaBoost) (0) | 2023.09.27 |
---|---|
[머신러닝] 앙상블 학습 (Ensemble Learning) (2) | 2023.08.29 |
[머신러닝] 전처리 (pre-processing) (1) | 2023.04.11 |
[머신러닝] 회귀(Regression) 선 그래프 (1) | 2023.04.08 |
[머신러닝] K - 최근접 이웃 회귀 (K-NN Regression) 01 (0) | 2023.04.08 |