- 저자
- 오렐리앙 제롱
- 출판
- 한빛미디어
- 출판일
- 2020.05.04
결정 트리 Decision Tree
결정 트리(Decision Tree)는 분류와 회귀 작업 그리고 다중출력 작업도 가능한 다재다능한 머신러닝 알고리즘으로 매우 복잡한 데이터셋도 학습할 수 있다.
=> 그만큼 과대적합 우려가 있다
결정 트리는 최근 가장 강력한 머신러닝 알고리즘 중 하나인 랜덤 포레스트의 기본 구성요소이기도 하다.
1. 결정 트리 학습과 시각화
아래의 코드는 붓꽃 데이터셋에 DecisionTreeClassifier
를 훈련시키는 코드이다.
from sklearn.datasets import load_iris
from sklearn.tree import DecisionTreeClassifier
iris = load_iris()
X = iris.data[:, 2:] # 꽃잎 길이와 너비
y = iris.target
tree_clf = DecisionTreeClassifier(max_depth=2, random_state=42)
tree_clf.fit(X, y)
이를 시각화하면 아래와 같다.
2. 예측하기
위의 트리가 어떻게 예측을 만드는지 살펴보자.
새로 발견한 붓꽃의 품종을 분류한다고 가정했을 때, 루트 노드(root node, 깊이가 0인 맨 꼭대기의 노드)에서 시작한다. 이 노드의 꽃잎의 길이가 2.45cm보다 짧다면 루트 노드에서 왼쪽의 자식 노드(child node, 깊이 1, 왼쪽 노드)로 이동한다. 이 노드가 리프 노트(leaf node, 자식 노드를 가지지 않는 노드)이므로 추가적인 검사를 하지 않는다. 그냥 노드에 있는 예측 클래스를 보고 결정 트리가 새로 발견한 꽃의 품종을 Iris-Setosa(class=setosa
)라 예측한다.
다른 꽃은 꽃잎의 길이가 2.45cm보다 길다. 이번에는 루트 노드의 오른쪽 자식 노드로 이동하며, 리프 노드가 아니기에 추가로 "꽃잎의 너비가 1.75cm보다 작은지" 검사한다. 만약 작다면 이 꽃은 아마도 Iris-Versicolor(깊이 2, 왼쪽)일 것이고 그렇지 않다면 Iris-Virginica(깊이2, 오른쪽) 일 것이다.
이러한 결정트리의 여러 장점 중 하나는 데이터 전처리가 거의 필요하지 않다는 점이다. 특성의 스케일을 맞추거나 평균을 원점에 맞추는 작업이 필요하지 않다.
노드의 sample 속성은 훈련 샘플의 개수로, 100개의 훈련 샘플의 꽃잎 길이가 2.45cm보다 길다는 뜻이다(깊이 1, 오른쪽). 노드의 value 속성은 노드에서 각 클래스에 속한 샘플의 개수로 맨 오른쪽 아래 노드는 Iris-Setosa가 0개이고, Iris-Versicolor가 1개, Iris-Virginica가 45개 있다. 마지막으로 gini 속성은 불순도(impurity)를 측정한다. 한 노드의 모든 샘플이 같은 클래스에 속해 있다면 이 노드를 순수(gini=0)하다고 한다. gini를 계산하는 방법은 아래의 식을 따른다.
사이킷런은 이진 트리만 만드는 CART 알고리즘을 사용한다. 따라서 리프 노드 외의 모든 노드는 자식 노드를 두 개씩 가지며, ID3 같은 알고리즘은 둘 이상의 자식 노드를 가진 결정 트리를 만들 수 있다.
from matplotlib.colors import ListedColormap
def plot_decision_boundary(clf, X, y, axes=[0, 7.5, 0, 3], iris=True, legend=False, plot_training=True):
x1s = np.linspace(axes[0], axes[1], 100)
x2s = np.linspace(axes[2], axes[3], 100)
x1, x2 = np.meshgrid(x1s, x2s)
X_new = np.c_[x1.ravel(), x2.ravel()]
y_pred = clf.predict(X_new).reshape(x1.shape)
custom_cmap = ListedColormap(['#fafab0','#9898ff','#a0faa0'])
plt.contourf(x1, x2, y_pred, alpha=0.3, cmap=custom_cmap)
if not iris:
custom_cmap2 = ListedColormap(['#7d7d58','#4c4c7f','#507d50'])
plt.contour(x1, x2, y_pred, cmap=custom_cmap2, alpha=0.8)
if plot_training:
plt.plot(X[:, 0][y==0], X[:, 1][y==0], "yo", label="Iris setosa")
plt.plot(X[:, 0][y==1], X[:, 1][y==1], "bs", label="Iris versicolor")
plt.plot(X[:, 0][y==2], X[:, 1][y==2], "g^", label="Iris virginica")
plt.axis(axes)
if iris:
plt.xlabel("Petal length", fontsize=14)
plt.ylabel("Petal width", fontsize=14)
else:
plt.xlabel(r"$x_1$", fontsize=18)
plt.ylabel(r"$x_2$", fontsize=18, rotation=0)
if legend:
plt.legend(loc="lower right", fontsize=14)
plt.figure(figsize=(8, 4))
plot_decision_boundary(tree_clf, X, y)
plt.plot([2.45, 2.45], [0, 3], "k-", linewidth=2)
plt.plot([2.45, 7.5], [1.75, 1.75], "k--", linewidth=2)
plt.plot([4.95, 4.95], [0, 1.75], "k:", linewidth=2)
plt.plot([4.85, 4.85], [1.75, 3], "k:", linewidth=2)
plt.text(1.40, 1.0, "Depth=0", fontsize=15)
plt.text(3.2, 1.80, "Depth=1", fontsize=13)
plt.text(4.05, 0.5, "(Depth=2)", fontsize=11)
save_fig("decision_tree_decision_boundaries_plot")
plt.show()
위의 그림은 결정 트리의 결정 경계를 보여준다. 굵은 수직선이 루트 노트의 결정경계이다. 왼쪽은 Iris-Setosa만 있는 순수 노드이기에 더이상 나눌 수 없으나 오른쪽은 순수노드가 아니므로 꽃잎 너비 1.75를 기준으로 나누어진다(파선). max_depth를 2로 설정했기 때문에 더이상 분할하지 않으나, 3으로 설정하면 두 점선으로 새롭게 경계가 추가된다.
모델 해석: 화이트박스와 블랙박스
결정 트리는 직관적이고 결정 방식을 이해하기 쉽다. 이런 모델을 화이트박스(white box) 모델이라고 한다. 반대로 랜덤포레스트나 신경망은 블랙박스(black box)모델이다. 이 알고리즘들은 성능이 뛰어나고 예측을 만드는 연산 과정을 쉽게 할 수 있으나, 왜 그런 예측을 만드는지는 설명하기 어렵다. 예를 들어 사람이 신경망이 어떤 사람이 사진에 있다고 판단했을 때 무엇이 이런 예측을 낳게 했는지 파악하기 어렵다. 모델이 그 사람의 눈을 인식한 걸까? 아니면 입? 코? 신발? 그 사람이 앉아 있는 소파? 반면에 결정 트리는 필요하다면 수동으로 직접 따라해볼 수도 있는 간단하고 명확한 분류 방법을 사용한다.
'AI > ML' 카테고리의 다른 글
정규분포와 Feature Scaling (1) | 2022.11.10 |
---|---|
[유튜브 강의록] 04-1: Ensemble Learning - Overview (0) | 2022.11.06 |
지도 학습, 비지도 학습, 강화 학습 [작성중] (0) | 2022.10.27 |
2021 캐글 통계로 보는 머신러닝 (0) | 2022.10.27 |
머신러닝 시작! (0) | 2022.10.27 |
댓글