- 의사 결정 나무 (Decision Tree)
- 의사 결정 나무는 의사결정 규칙(Decision rule)을 나무구조로 도표화하여 관심대상이 되는 집단을 몇 개의 소집단으로 분류(Classification)하거나 예측(Prediction)을 수행하는 분석 방법이다.
- 최고의 장점은 해석력이다. 앞으로 나올 고도화된 모델들은 블랙박스 모델로 해석이 어렵다. 하지만 이 의사 결정 트리는 각각의 결정 규칙이 명확하게 이해되기 때문에 모델의 작동 방식을 이해하고 설명하기 쉽다.
- 의사 결정 나무의 노드 분할 방법 (불순도 측정)
- Gini index와 Entropy 두가지 방법이 있다.
- Gini index
- P_k : 범위 A내에서 클래스 K에 속하는 관측치의 비율
- 지니 지수는 0~0.5 사이의 값을 가지며 0일때 순도가 높다.
- 다음 예시는 목표변수: 신용상태, 설명변수: 급여형태, 나이, 직업 이라고 할때, 신용상태에 대해 지니지수를 구하는 예시이다.
- ΔG : 지니지수의 감소량 Information Gain으로 분할하기전과 후의 감소량을 나타낸다. (Information gain 용어를 기억해 두길 바란다!)
- 다른 설명 변수들에 대해서도 Information Gain을 구한 후 가장 큰 값을 갖는 설명변수를 사용하여 분리하는 방식이다.
- Entropy
- r_i : 전체 관측치중에서 i번째 직사각형내에 존재하는 관측치의 비율
- 엔트로피 값은 0 <= Entropy <= log_2(m) 사이에 분포, 0일때 가장 순수
- ΔE : Entropy 감소량으로 다른 설명변수들에 대해서도 ΔE를 구한 후, 가장 큰 값을 갖는 설명변수를 사용하여 분리한다.
- Decision Tree Pruning (가지치기)
- 무한히 Partitioning(Split)을 하게되면 100% 순도(Purity), 0% 불순도(Impurity)가 된다.
- => Overfitting 발생
- Full Tree: 모든 끝 마디에서의 순도가 100%인 상태 , 즉 Full Tree 가되면 Overfitting이 된다.
- Prunning(가지치기)
- 방법 :
- Full Tree가 되는것을 방지하기위해 의사결정나무의 최대 Depth나 노드의 최소 개수를 미리 지정해 더 이상의 분할이 일어나지 않게 한다.
- 가지치기를 중단할 점을 찾기 위해 검증데이터의 오류가 증가하기 시작하는 지점을 찾는다.
- 최소 오류나무: 검증 데이터에서 가장 낮은 오분류율을 갖는 나무
- 최적의 가지치기된 나무 : 간결성/간명성 측면에서 우수
- 코드 예제
[Decision Tree를 활용한 Rule Extraction]
- Max_Depth는 5 초과를 넘지 않아야함, 5를 초과하게 되면 Rule Extraction Plotting의 가독성이 매우 떨어짐
- 정확도와 설명력은 Trade-off가 존재하기 때문에 자기만의 기준으로 적절한 선을 선택하면 됨
- Rule Extraction 할때 GINI INDEX 뿐만 아니라 Sample 개수도 중요한 척도가 됨 GINI INDEX가 아주 낮지만(불순도가 낮음, 좋음) Sample의 개수가 너무 적으면 의미가 없음(Overfitting이라고 생각됨)
import pandas as pd
from sklearn.model_selection import train_test_split
from sklearn.tree import DecisionTreeClassifier
from sklearn.metrics import confusion_matrix, f1_score
# Data Loading (수술 時 사망 데이터)
data = pd.read_csv("https://raw.githubusercontent.com/GonieAhn/Data-Science-online-course-from-gonie/main/Data%20Store/example_data.csv")
# X & Y Split
Y = data['censor']
X = data.drop(columns=['censor'])
idx = list(range(X.shape[0]))
train_idx, valid_idx = train_test_split(idx, test_size=0.3, random_state=2023)
# model Train
model = DecisionTreeClassifier(max_depth=4, criterion='gini')
model.fit(X.iloc[train_idx], Y.iloc[train_idx])
# 결과 확인
# Train Acc
y_pre_train = model.predict(X.iloc[train_idx])
cm_train = confusion_matrix(Y.iloc[train_idx], y_pre_train)
print("Train Confusion Matrix")
print(cm_train)
print("Train Acc: {}".format((cm_train[0,0] + cm_train[1,1])/cm_train.sum()))
print("Train F1-Score: {}".format(f1_score(Y.iloc[train_idx], y_pre_train)))
print("-----------------------------------------------------------------------")
# Test Acc
y_pre_test = model.predict(X.iloc[valid_idx])
cm_test = confusion_matrix(Y.iloc[valid_idx], y_pre_test)
print("Test Confusion Matrix")
print(cm_test)
print("Test Acc: {}".format((cm_test[0,0] + cm_test[1,1]) / cm_test.sum()))
print("Test F1-Score: {}".format(f1_score(Y.iloc[valid_idx], y_pre_test)))
import matplotlib.pyplot as plt
from sklearn import tree
# Creating the tree plot
tree.plot_tree(model, filled=True, feature_names=X.columns, class_names = ['Dead', 'indicator'])
plt.rcParams['figure.figsize'] = [30,10]
'ML' 카테고리의 다른 글
[Boosting] Light GBM (0) | 2024.07.24 |
---|---|
랜덤 포레스트(Random Forest) (0) | 2024.06.18 |
[머신러닝] 앙상블(Ensemble) (1) | 2024.06.01 |
로지스틱 회귀 (Logistic Regression) (0) | 2024.06.01 |