의사결정나무(Decision Tree)란 이름 그대로 의사 결정을 하는 데 나무(tree)를 사용한다는 뜻입니다.
의사결정나무는 예측 또는 분류 문제를 해결함에 있어서 어떤 변수가 가장 중요한 영향을 주는지 확인할 수 있고, 나아가 각 변수별로 어떤 척도에 따라 예측 또는 분류했는지 상세한 기준을 알 수 있다는 장점이 있습니다.
트리를 구성하는 방법은 엔트로피(Entropy)와 지니계수(Gini Index)를 사용하는 방법이 있는데, 이 중 엔트로피를 사용하는 방법을 알아봅시다.
먼저 엔트로피란 불순도(impurity) 정도를 측정하며, 낮을수록 좋습니다.
여기서 불순도란 노드에 서로 다른 데이터가 얼마나 섞여 있는지를 의미합니다.
또한 불순도가 낮을수록 데이터가 섞여 있지 않다는 것을 의미합니다.
엔트로피의 식은 아래와 같습니다.
식에서 p(i|d)는 노드 d가 주어질 때 i클래스에 속할 확률입니다.
이진 분류일 경우 k=2가 됩니다.
위 엔트로피는 다음과 같이 정리할 수 있습니다.
여기서 T는 노드 속 전체 데이터 수, P는 positive 데이터 수, N은 Negative 데이터 수를 의미합니다.
다음과 같은 데이터로 날씨에 대한 각 노드 엔트로피와 성능, 그리고 의사결정나무를 계산해 봅시다.
날씨 | 바람 | 온도 | 습도 | 배드민턴 |
맑음 | 강함 | 낮음 | 보통 | 아니오 |
흐림 | 강함 | 높음 | 보통 | 아니오 |
맑음 | 약함 | 높음 | 보통 | 네 |
비 | 약함 | 보통 | 높음 | 네 |
맑음 | 약함 | 보통 | 낮음 | 네 |
흐림 | 약함 | 낮음 | 높음 | 아니오 |
흐림 | 약함 | 보통 | 높음 | 아니오 |
맑음 | 강함 | 높음 | 낮음 | 아니오 |
날씨에 대한 각 노드별 엔트로피는 다음과 같습니다.
날씨에 대한 테스트 전체의 성능을 평가하기 위한 공식은 아래와 같습니다.
Rj는 전체 데이터 개수 중 해당 노드의 데이터 개수 비율을 의미합니다.
날씨 테스트에서 테스트 전체 데이터 수는 8개이고 맑음 노드는 4개, 흐림 노드는 3개, 비 노드는 1개의 데이터로 구성되어 있습니다.
따라서 Q(날씨 테스트)는 다음과 같습니다.
이와 같이 진행하면 각 피처에 대한 성능은 다음과 같습니다.
테스트 | 성능 |
날씨 | 0.5 |
바람 | 0.6 |
온도 | 0.7 |
습도 | 0.95 |
또한 의사결정나무는 다음과 같습니다.
하지만 맑음 노드의 경우 배드민턴 플레이 여부를 정확히 분류하지 못하므로 해당 데이터를 분류하기 위한 추가적인 테스트가 필요합니다.
추가적인 테스트는 날씨=맑음일 경우만 고려합니다.
바람, 온도, 습도에 대하여 배드민턴 플레이 여부를 정확히 분류할 수 있을때까지 위와 같은 테스트를 계속 진행합니다.
의사결정나무를 정리하면 다음과 같습니다.
1. 날씨, 바람, 온도, 습도에 대한 각 노드의 엔트로피와 각 피처의 성능을 계산하고 그 중 가장 낮은 성능 값을 가지는 피처(날씨)를 기준으로 나무를 구성한다.
2. 구성된 나무가 목표 변수(Y)를 정확히 분류할 수 있는지 확인하고, 그렇지 않다면(날씨=맑음 과 같은 경우) 다음으로 낮은 성능 값을 가지는 피처(바람)를 테스트한다.
실습은 sklearn DecisionTreeClassifier를 이용하여 와인 데이터를 분류해 보겠습니다.
from sklearn import datasets
from sklearn.preprocessing import StandardScaler
from sklearn.model_selection import train_test_split
from sklearn import tree
from sklearn.metrics import f1_score
from sklearn.metrics import confusion_matrix
from sklearn.metrics import classification_report
# 데이터 불러오기
raw_wine = datasets.load_wine()
# 피쳐, 타겟 데이터 지정
X = raw_wine.data
y = raw_wine.target
# 트레이닝/테스트 데이터 분할
X_tn, X_te, y_tn, y_te=train_test_split(X,y,random_state=0)
# 데이터 표준화
std_scale = StandardScaler()
std_scale.fit(X_tn)
X_tn_std = std_scale.transform(X_tn)
X_te_std = std_scale.transform(X_te)
# 의사결정나무 학습
clf_tree = tree.DecisionTreeClassifier(random_state=0)
clf_tree.fit(X_tn_std, y_tn)
# 예측
pred_tree = clf_tree.predict(X_te_std)
print(pred_tree)
# f1 score
from sklearn.metrics import f1_score
f1 = f1_score(y_te, pred_tree, average='macro')
print(f1)
# confusion matrix 확인
conf_matrix = confusion_matrix(y_te, pred_tree)
print(conf_matrix)
# 분류 레포트 확인
class_report = classification_report(y_te, pred_tree)
print(class_report)
'AI > Machine Learning' 카테고리의 다른 글
[Machine Learning] 보팅 (Voting) (0) | 2023.05.31 |
---|---|
[Machine Learning] 서포트 벡터 머신 (Support Vector Machine, SVM) (1) | 2023.05.31 |
[Machine Learning] 나이브 베이즈 (Naive Bayes) (0) | 2023.05.24 |
[Machine Learning] 로지스틱 회귀 (Logistic Regression) (1) | 2022.09.29 |
[Machine Learning] 라쏘, 릿지, 엘라스틱넷 (Ridge, Lasso, ElasticNet) (0) | 2022.09.28 |