Table of Contents

ML

Decision tree -> pre-pruning, post-pruning

꼬꼬마코더 2024. 5. 29. 12:37
728x90

결정 트리 모델에서 가지치기(pruning)는 모델이 훈련 데이터에 과적합되는 것을 방지하기 위해 트리의 크기를 줄이는 과정입니다. 가지치기는 전정 가지치기(pre-pruning)와 후정 가지치기(post-pruning)로 나눌 수 있습니다.

  • 전정 가지치기 (Pre-pruning): 트리를 성장시키는 동안 불필요한 분할을 방지하는 방법입니다. 이는 트리의 깊이, 최소 샘플 수 등을 제한하여 구현할 수 있습니다.
  • 후정 가지치기 (Post-pruning): 트리를 다 성장시킨 후에 가지를 치는 방법입니다. 이는 노드에서 분할을 제거하고, 트리의 일부를 잘라내어 구현할 수 있습니다.

여기서는 사이킷런(Scikit-learn) 라이브러리를 사용하여 전정 가지치기와 후정 가지치기를 구현하는 방법을 보여드리겠습니다.

전정 가지치기 (Pre-pruning)

전정 가지치기는 결정 트리를 생성할 때 파라미터를 설정하여 트리의 최대 깊이(max_depth), 노드의 최소 샘플 수(min_samples_split, min_samples_leaf) 등을 제한합니다.

from sklearn.datasets import load_iris
from sklearn.tree import DecisionTreeClassifier
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score

# 데이터 로드 및 분할
iris = load_iris()
X_train, X_test, y_train, y_test = train_test_split(iris.data, iris.target, test_size=0.3, random_state=42)

# 결정 트리 모델 생성 (전정 가지치기)
clf = DecisionTreeClassifier(max_depth=3, min_samples_split=4, min_samples_leaf=2, random_state=42)
clf.fit(X_train, y_train)

# 예측 및 평가
y_pred = clf.predict(X_test)
print("Accuracy with pre-pruning:", accuracy_score(y_test, y_pred))

후정 가지치기 (Post-pruning)

후정 가지치기는 트리를 완전히 성장시킨 후에 가지를 치는 방법입니다. 사이킷런에서 직접 후정 가지치기를 수행하는 기능은 제공하지 않지만, 비용 복잡성 프루닝(Cost Complexity Pruning)이라는 방법을 사용할 수 있습니다. 이는 ccp_alpha 매개변수를 조정하여 수행합니다.

from sklearn.datasets import load_iris
from sklearn.tree import DecisionTreeClassifier
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score
import matplotlib.pyplot as plt
import numpy as np

# 데이터 로드 및 분할
iris = load_iris()
X_train, X_test, y_train, y_test = train_test_split(iris.data, iris.target, test_size=0.3, random_state=42)

# 결정 트리 모델 생성 (후정 가지치기)
clf = DecisionTreeClassifier(random_state=42)
path = clf.cost_complexity_pruning_path(X_train, y_train)
ccp_alphas = path.ccp_alphas

# 다양한 ccp_alpha 값에 대해 트리 모델 훈련
clfs = []
for ccp_alpha in ccp_alphas:
    clf = DecisionTreeClassifier(random_state=42, ccp_alpha=ccp_alpha)
    clf.fit(X_train, y_train)
    clfs.append(clf)

# 각 트리의 정확도 평가
train_scores = [accuracy_score(y_train, clf.predict(X_train)) for clf in clfs]
test_scores = [accuracy_score(y_test, clf.predict(X_test)) for clf in clfs]

# 정확도 시각화
plt.figure(figsize=(10, 6))
plt.plot(ccp_alphas, train_scores, marker='o', label='train', drawstyle="steps-post")
plt.plot(ccp_alphas, test_scores, marker='o', label='test', drawstyle="steps-post")
plt.xlabel("ccp_alpha")
plt.ylabel("accuracy")
plt.legend()
plt.title("Accuracy vs ccp_alpha for training and testing sets")
plt.show()

# 최적의 ccp_alpha 값 선택 후 모델 생성
optimal_ccp_alpha = ccp_alphas[np.argmax(test_scores)]
optimal_clf = DecisionTreeClassifier(random_state=42, ccp_alpha=optimal_ccp_alpha)
optimal_clf.fit(X_train, y_train)

# 최적 모델 평가
y_pred = optimal_clf.predict(X_test)
print("Accuracy with post-pruning:", accuracy_score(y_test, y_pred))

요약

  • 전정 가지치기는 트리를 성장시키는 동안 최대 깊이, 최소 샘플 수 등을 제한하여 불필요한 분할을 방지합니다.
  • 후정 가지치기는 트리를 완전히 성장시킨 후, 비용 복잡성 프루닝을 사용하여 가지를 치는 방법입니다.

위의 코드는 두 가지 가지치기 방법을 구현한 예제로, 사이킷런 라이브러리를 사용하여 쉽게 적용할 수 있습니다. 이를 통해 모델의 복잡성을 줄이고 과적합을 방지할 수 있습니다.