의사결정나무란
결정 트리란 데이터에 있는 규칙을 학습을 통해 자동으로 찾아내 Tree기반의 "분류 규칙"을 만들고, 이 규칙을 통해 최대한 균일도가 높은(과적합 고려) 결정 클래스를 만드는 분류기법이다.
하나의 규칙을 만들 때마다 특정 기준에 따라 "예/아니오"로 답할 수 있는 질문을 이어나가면서 학습한다. 이 때 규칙을 만들 떄마다 노드를 만들고, 가지를 치면서 내려간다. 이 결과는 규칙이 명확해 해석을 쉽게 할 수 있다.
또한 선형성과 정규성 등의 가정이 필요하지 않아 전처리 과정에 모델의 성능이 큰 영향을 받지 않는다. 하지만 과적합의 가능성이 있어 일반화 성능이 우수하지 않다.
구조
- 규칙 노드 (Decision Node) : 규칙 조건을 표시한 노드
- 리프 노드 (Leaf Node) : 결정된 클래스 값을 표시한 노드
규칙
1. 분류분석 (종속변수 : 이산형)
- 카이제곱 통계량 p값 : p값이 가장 작은 예측변수와 그 때의 최적분리에 의해서 자식마디를 형성
- 지니지수 : 지니지수를 감소시키는 예측변수와 그 때의 최적분리에 의해 자식마디를 형성
위 예시에서 분기 후 지니지수의 감소량(정보 획득량)은 0.47 - 0.34 = 0.13
P는 k범주에 속하는 클래스의 비율, m는 범주의 개수
- 엔트로피지수 : 엔트로피지수가 가장 작은 예측변수와 이 떄의 최적분리에 의해 자식마디를 형성
위 예시에서 분기 후 엔트로피지수의 감소량(정보 획득량)은 0.95 - 0.75 = 0.20
2. 회귀분석 (종속변수 : 연속형)
- 분산분석에서 F통계량 : p값이 가장 작은 예측변수와 그 때의 최적분리에 의해서 자식마디를 형성
- 분산의 감소량 : 분산의 감소량을 최대화하는 기준의 최적분리에 의해서 자식마디를 형성
복잡도 제어
학습 시 트리의 크기를 의사결정나무 모델의 복잡도로 볼 수 있다. 모든 데이터가 각각 분할되도록 가지를 치도록 하는 모델이라면 학습 데이터에 대해 높은 예측력을 가지겠지만 과적합 문제가 발생할 수 있다. 이러한 문제를 방지하기 위해 가지치기를 이용해 트리의 성장을 제한하는데, sklearn에서 지원하는 방식은 사전가지치기(Pre-pruning)이다. 하이퍼파라미터를 조정해 트리의 최대 깊이나 리프의 최대 개수를 제한하거나, 노드가 분할하기 위한 포인트의 최소 개수를 정한다.
from sklearn.datasets import load_breast_cancer
import pandas as pd
from sklearn.model_selection import train_test_split
from sklearn.tree import DecisionTreeClassifier
cancer = load_breast_cancer()
x = pd.DataFrame(cancer.data, columns = cancer.feature_names)
y = cancer.target
X_train, X_test, y_train, y_test = train_test_split(x, y, stratify=y, train_size = 0.7, random_state = 42)
print(X_train.shape, X_test.shape)
clf = DecisionTreeClassifier(max_depth = 5)
clf.fit(X_train, y_train)
from sklearn.metrics import confusion_matrix, accuracy_score, roc_auc_score
from sklearn.metrics import precision_score, recall_score, f1_score, plot_roc_curve
pred = clf.predict(X_test)
test_cm = confusion_matrix(y_test, pred)
test_acc = accuracy_score(y_test, pred)
test_pre = precision_score(y_test, pred)
test_re = recall_score(y_test, pred)
test_f1 = f1_score(y_test, pred)
print(test_cm)
print('\n')
print(f'정확도 : {round(test_acc*100, 2)}%')
print(f'정밀도 : {round(test_pre*100, 2)}%')
print(f'재현율 : {round(test_re*100, 2)}%')
print(f'F1 score : {round(test_f1*100, 2)}%')
from sklearn.metrics import classification_report
import matplotlib.pyplot as plt
report = classification_report(y_test, pred)
print(report)
print('ROC_AUC_SCORE : ', ra_score)
plot_roc_curve(clf, X_test, y_test)
plt.show()
ra_score = roc_auc_score(y_test, clf.predict_proba(X_test)[:, 1])
# 변수 중요도 확인
importances = clf.feature_importances_
cols = pd.DataFrame(X_train.columns)
feature_importances = pd.concat([cols, pd.DataFrame(importances)], axis = 1)
feature_importances.columns = ['feature_nm', 'importances']
print(feature_importances.sort_values('importances', ascending=False))
import numpy as np
feature_names = X_train.columns
target_names = np.array(['0', '1'])
import pydot
import pydotplus
import graphviz
from sklearn.tree import export_graphviz
dt_dot_data = export_graphviz(clf, feature_names = feature_names,
class_names = target_names,
filled=True, rounded=True,
special_characters = True)
dt_graph = pydotplus.graph_from_dot_data(dt_dot_data)
from IPython.display import Image
Image(dt_graph.create_png())
'ADP로ML정리' 카테고리의 다른 글
6. 앙상블 모델 (0) | 2024.02.22 |
---|---|
4-2. 회귀 모델 - 분류를 위한 회귀 모델 (1) | 2024.02.19 |
4-1. 회귀 모델 - 규제가 있는 선형 회귀 (1) | 2024.02.19 |
3. 머신러닝 평가지표 (0) | 2024.02.15 |
2-6. 데이터 전처리 - 데이터 불균형 문제 해결 (1) | 2024.02.15 |