데이터를 분할하는 기준을 결정하는데 사용되는 방법론
트리의 각 단계에서 최적의 분할을 찾기 위해 사용되며
이를 통해 트리의 깊이와 복잡성을 관리할 수 있음
좋은 결정 기준은 트리를 더욱 간결하고 효율적으로 만들며
과적합을 방지하고 일반화 성능을 향상시킴!
분류 과정에서 사용되는 결정 기준
• 정보 이득
• 지니 불순도
• 회귀 과정에서 사용되는 결정 기준
• MSE 최소화
Tree에서 가장 중요한 것은 분할을 잘하는 정도이다.
그렇기에 분할 결정 기준이 매우 중요!
어떤 상황이나 현상이 품고 있는 불확실성을 의미하며, 포함하는 정보의 양과 반비례 한다는 의미
엔트로피가 크다 → 불확실성이 크다 → 정보량이 적다
반대로, 엔트로피가 작으면 → 불확실성이 작고, 알고 있는 정보가 많다!
예를 들어, 두 사람이 가위 바위 보를 하는 상황에서
엔트로피는 수치적으로 구할 수 있으며 아래와 같음

상황은 특정한 정도의 엔트로피를 갖고 있음을 알 수 있다.

노드에 포함되는 데이터의 순도에 따라 엔트로피가 계산될 수 있음
정보 이득 (information gain)이란,
• 부모 노드와 자식 노드들의 엔트로피를 계산해
• 엔트로피가 낮아지는 방향으로 결정 경계를 선정하는 것을 의미함
즉, 정보 이득을 최대화 하는 방향으로!
[나이가 30살 이상이다!] 라는 분류를 해야 이후에 더 큰 정보를 얻을 수 있음.
식은 아래와 같다.

A ~ C 각 노드의 엔트로피 계산


엔트로피가 작아지는 방향으로 노드를 만드는 결정 경계를 생성해야 함!
데이터 집합의 순도를 측정하는 또 다른 방법
데이터 안에 존재하는 클래스 분포의 불균형을 평가하는 방법

p! : 데이터 집합 안에 존재하는 i 번째 클래스가 나타나는 확률
0 이상 1 미만의 값을 갖는다.
• 0 : 모든 데이터가 하나의 클래스에 속함. 제일 순도가 높은 상태
• 1에 가까운 값 : 모든 클래스의 데이터가 고루 섞인 상태로 불순도가 제일 높음
A ~ C 각 노드의 지니 불순도



위와 같은 데이터 형태를 분류 실습을 진행할 예정이다.
# 정보 이득을 사용하는 결정 트리 분류기 생성
dt_entropy = DecisionTreeClassifier(criterion='entropy',
max_depth=3, #노드 층 수를 의미
min_samples_split=3) # 분기 진행 시작 조건인 노드 내 샘플 수
dt_entropy.fit(X, y)
# 지니 불순도를 사용하는 결정 트리 분류기 생성
dt_gini = DecisionTreeClassifier(criterion='gini',
max_depth=3,
min_samples_split=3) # 분기 진행 시작 조건인 노드 내 샘플 수
dt_gini.fit(X, y) # 피팅
max_depth=3 : 노드 층 수를 의미 / 3개의 층을 만들 것이라는 의미.
이후 sklearn의 plot_tree 를 사용하면 나눠진 모습을 그려볼 수 있다.
# 두 모델의 훈련된 구조를 확인
from sklearn.tree import plot_tree
# 정보 이득을 사용한 결정 트리
plt.figure(figsize=(24, 12))
plot_tree(dt_entropy, filled=True,
feature_names=['Feature 1', 'Feature 2'],
class_names=['Class 0', 'Class 1', 'Class 2'])
plt.title("Decision Tree using Entropy")
plt.show()

# 지니 불순도를 사용한 결정 트리
plt.figure(figsize=(24, 12))
plot_tree(dt_gini, filled=True,
feature_names=['Feature 1', 'Feature 2'],
class_names=['Class 0', 'Class 1', 'Class 2'])
plt.title("Decision Tree using Gini")
plt.show()

어떤식으로 데이터를 분류했는지 시각화를 진행해 보자면 아래와 같이 나올 수 있다.
# 결정 경계 그려보기
import numpy as np
# 데이터와 결정 경계를 시각화하는 함수
def plot_decision_boundaries(X, y, model, title):
# 마커와 색상 설정
markers = ('s', 'x', 'o')
colors = ('red', 'blue', 'green')
cmap = plt.cm.RdYlBu
# 결정 경계 그리기
x1_min, x1_max = X[:, 0].min() - 1, X[:, 0].max() + 1
x2_min, x2_max = X[:, 1].min() - 1, X[:, 1].max() + 1
xx1, xx2 = np.meshgrid(np.arange(x1_min, x1_max, 0.01),
np.arange(x2_min, x2_max, 0.01))
Z = model.predict(np.array([xx1.ravel(), xx2.ravel()]).T)
Z = Z.reshape(xx1.shape)
plt.contourf(xx1, xx2, Z, alpha=0.4, cmap=cmap)
# 데이터셋의 샘플 플로팅
for idx, cl in enumerate(np.unique(y)):
plt.scatter(x=X[y == cl, 0], y=X[y == cl, 1],
alpha=0.8, c=colors[idx],
marker=markers[idx], label=f'Class {cl}')
plt.xlabel('Feature 1')
plt.ylabel('Feature 2')
plt.legend(loc='upper left')
plt.title(title)
# 첫 번째 특성과 두 번째 특성을 이용한 데이터셋 시각화
plt.figure(figsize=(24, 12))
plt.subplot(1, 2, 1)
plot_decision_boundaries(X, y, dt_entropy, "Decision Tree (Entropy)")
plt.subplot(1, 2, 2)
plot_decision_boundaries(X, y, dt_gini, "Decision Tree (Gini)")
plt.show()

트리문제는 직관적으로 어떻게 나눴는지 확인할 수 있는 모습이다.