파이썬을 활용한 의사결정 트리 분류기 구현

1. 필수 라이브러리 불러오기

데이터 처리, 수치 계산 및 모델링에 필요한 주요 라이브러리를 임포트합니다.

import pandas as pd
import openpyxl # pandas가 Excel 파일을 읽을 때 필요한 의존성
import numpy as np
  • pandas는 데이터 구조 및 분석 도구를 제공하여 데이터프레임 조작에 사용됩니다.
  • openpyxlpandas가 Excel 파일 형식을 처리하는 데 도움을 줍니다.
  • numpy는 고성능 수치 계산을 위한 배열 객체와 도구를 제공합니다.

2. 혼동 행렬 시각화 함수 정의

모델의 성능을 직관적으로 이해할 수 있도록 혼동 행렬(Confusion Matrix)을 그리는 함수를 구현합니다.

def plot_confusion_matrix(actual_labels, predicted_labels):
    from sklearn.metrics import confusion_matrix
    import matplotlib.pyplot as plt

    # 혼동 행렬 계산
    cm = confusion_matrix(actual_labels, predicted_labels)
    
    # 혼동 행렬 시각화
    plt.figure(figsize=(6, 5))
    plt.matshow(cm, cmap=plt.cm.Blues, fignum=1) # fignum을 지정하여 새로운 figure에 그림
    plt.colorbar()

    # 각 셀에 숫자 값 추가
    for x_idx in range(len(cm)):
        for y_idx in range(len(cm)):
            plt.annotate(str(cm[x_idx, y_idx]), xy=(y_idx, x_idx),
                         horizontalalignment='center', verticalalignment='center',
                         color='black' if cm[x_idx, y_idx] < cm.max()/2 else 'white') # 텍스트 색상 조절
    
    plt.ylabel('실제 레이블')
    plt.xlabel('예측 레이블')
    plt.title('혼동 행렬')
    return plt
  • 이 함수는 실제 레이블(actual_labels)과 모델의 예측 레이블(predicted_labels)을 입력으로 받습니다.
  • sklearn.metrics.confusion_matrix를 사용하여 혼동 행렬을 생성합니다.
  • matplotlib을 활용하여 혼동 행렬을 시각화하며, 값에 따라 파란색 계열의 색상을 적용합니다.
  • 각 셀에는 해당 수치를 명확하게 표시하고, 축 레이블과 제목을 추가하여 가독성을 높입니다.
  • 최종적으로 생성된 matplotlib.pyplot 객체를 반환합니다.

3. 데이터 로드 및 분리

모델 학습에 필요한 고객 이탈 데이터를 불러오고, 특징(feature)과 목표 변수(target)로 나눕니다.

# Excel 파일에서 데이터 읽기
churn_data = pd.read_excel("./data/통신사_고객_이탈_데이터.xlsx")

# 마지막 열을 제외한 모든 열을 특징으로 설정
features = churn_data.iloc[:, :-1]
# 마지막 열을 목표 변수로 설정
labels = churn_data.iloc[:, -1]
  • pd.read_excel 함수를 사용하여 지정된 경로의 Excel 파일을 데이터프레임으로 불러옵니다.
  • features 변수에는 데이터프레임의 첫 번째 열부터 마지막에서 두 번째 열까지의 데이터를 할당합니다. 이는 모델 학습에 사용될 입력 특성입니다.
  • labels 변수에는 데이터프레임의 마지막 열만 할당합니다. 이는 모델이 예측해야 할 목표 변수(예: 고객 이탈 여부)입니다.

4. 훈련 및 테스트 데이터셋 분할

모델의 일반화 성능을 평가하기 위해 데이터를 훈련 세트와 테스트 세트로 나눕니다.

from sklearn.model_selection import train_test_split

# 데이터를 훈련 세트(80%)와 테스트 세트(20%)로 분할
X_train, X_test, y_train, y_test = \
    train_test_split(features, labels, test_size=0.2, random_state=42)
  • sklearn.model_selection 모듈의 train_test_split 함수를 임포트합니다.
  • 전체 데이터를 훈련 세트(X_train, y_train)와 테스트 세트(X_test, y_test)로 나눕니다.
  • test_size=0.2는 전체 데이터의 20%를 테스트 세트로 사용함을 의미합니다.
  • random_state=42는 데이터를 분할할 때 무작위성을 제어하여, 코드 재실행 시에도 동일한 분할 결과를 보장합니다.

5. 의사결정 트리 모델 하이퍼파라미터 튜닝

최적의 모델 성능을 위해 의사결정 트리의 주요 하이퍼파라미터인 max_depth를 튜닝합니다.

from sklearn import tree
from sklearn.model_selection import cross_val_score
import time

evaluation_scores = []
depth_options = [7, 8, 9, 10, 12, 14, 15, 16, 17, 18, 19, 20]

print("Max_depth별 교차 검증 점수 (recall) 측정:")
for depth in depth_options:
    start_time_iter = time.time()
    # Gini 불순도와 현재 max_depth로 의사결정 트리 분류기 초기화
    dt_classifier = tree.DecisionTreeClassifier(criterion='gini', max_depth=depth, random_state=123)
    
    # 10겹 교차 검증 수행 (평가 지표: 재현율)
    scores_cv = cross_val_score(dt_classifier, X_train, y_train, cv=10, scoring='recall')
    
    end_time_iter = time.time()
    avg_score = np.mean(scores_cv)
    evaluation_scores.append(avg_score)
    
    print(f"  Max_depth {depth}: 평균 재현율 = {avg_score:.4f}, 소요 시간 = {end_time_iter - start_time_iter:.2f}초")

# 가장 높은 평균 재현율을 보인 max_depth 선택
best_max_depth = depth_options[np.argmax(evaluation_scores)]
print(f"\n최적의 max_depth는 {best_max_depth}입니다.")
  • sklearn.tree에서 DecisionTreeClassifier를, sklearn.model_selection에서 cross_val_score를 임포트합니다.
  • depth_options 리스트에 정의된 각 max_depth 값에 대해 반복합니다.
  • 각 반복에서 criterion='gini'를 사용하여 의사결정 트리 모델을 생성하고, random_state를 고정하여 재현성을 확보합니다.
  • 훈련 세트(X_train, y_train)에 대해 10겹 교차 검증(cv=10)을 수행하며, 모델 평가 지표로는 '재현율'(scoring='recall')을 사용합니다.
  • max_depth에 대한 평균 재현율과 소요 시간을 출력하고, 이 값을 evaluation_scores 리스트에 저장합니다.
  • 마지막으로 np.argmax(evaluation_scores)를 통해 가장 높은 평균 재현율을 기록한 max_depthbest_max_depth로 선정합니다.

6. 최적의 의사결정 트리 모델 훈련

하이퍼파라미터 튜닝을 통해 얻은 최적의 max_depth를 사용하여 최종 의사결정 트리 모델을 훈련시킵니다.

# 최적의 max_depth와 추가 매개변수를 사용하여 의사결정 트리 모델 초기화
final_dt_model = tree.DecisionTreeClassifier(
    criterion='gini', 
    max_depth=best_max_depth, 
    max_leaf_nodes=85, # 리프 노드의 최대 개수를 고정
    random_state=123
)

# 훈련 데이터셋으로 모델 학습
final_dt_model.fit(X_train, y_train)
print(f"최종 의사결정 트리 모델 학습 완료 (max_depth={best_max_depth}, max_leaf_nodes=85)")
  • DecisionTreeClassifier를 생성할 때, 앞서 찾은 best_max_depth 값을 적용하고, 추가적으로 max_leaf_nodes=85를 설정하여 트리의 복잡성을 제어합니다.
  • random_state=123을 사용하여 모델의 재현성을 유지합니다.
  • final_dt_model.fit(X_train, y_train)을 호출하여 훈련 데이터로 모델을 학습시킵니다.

7. 모델 성능 평가

훈련된 의사결정 트리 모델의 성능을 훈련 세트와 테스트 세트 모두에서 평가합니다.

from sklearn import metrics

print("--- 훈련 세트 평가 결과 ---")
train_predictions = final_dt_model.predict(X_train)
# 훈련 세트에 대한 분류 보고서 출력
print(metrics.classification_report(y_train, train_predictions))
# 혼동 행렬 시각화 (주석 처리됨)
# plot_confusion_matrix(y_train, train_predictions).show()

print("\n--- 테스트 세트 평가 결과 ---")
test_predictions = final_dt_model.predict(X_test)
# 테스트 세트에 대한 분류 보고서 출력
print(metrics.classification_report(y_test, test_predictions))
# 혼동 행렬 시각화 (주석 처리됨)
# plot_confusion_matrix(y_test, test_predictions).show()
  • sklearn.metrics 모듈을 사용하여 모델 평가를 위한 도구들을 활용합니다.
  • 먼저 훈련된 모델을 사용하여 훈련 세트(X_train)에 대한 예측(train_predictions)을 수행합니다.
  • metrics.classification_report를 통해 정밀도, 재현율, F1-점수 등 훈련 세트에 대한 상세 분류 보고서를 출력합니다.
  • 그 다음, 테스트 세트(X_test)에 대한 예측(test_predictions)을 수행하고, 동일하게 테스트 세트 성능 보고서를 출력합니다.
  • 주석 처리된 plot_confusion_matrix 함수를 활성화하면 각 세트에 대한 혼동 행렬을 시각적으로 확인할 수 있습니다.

8. 의사결정 트리 시각화

훈련된 의사결정 트리의 구조를 그래픽으로 표현하여 의사결정 과정을 이해합니다.

import matplotlib.pyplot as plt
from sklearn.tree import plot_tree

# 32x32 인치 크기의 그림 객체 생성
fig, ax = plt.subplots(figsize=(32, 32))

# 의사결정 트리 시각화
plot_tree(final_dt_model, 
          filled=True,             # 노드에 색상 채우기
          rounded=True,            # 노드 모서리를 둥글게 처리
          feature_names=features.columns.tolist(), # 특징 이름 추가
          class_names=[str(c) for c in final_dt_model.classes_], # 클래스 이름 추가
          ax=ax,                   # 현재 figure의 axes에 그리기
          fontsize=10)             # 글꼴 크기 설정
plt.title("훈련된 의사결정 트리 구조", fontsize=16)
plt.show()
  • matplotlib.pyplotsklearn.treeplot_tree 함수를 임포트합니다.
  • 큰 크기의 그림(32x32 인치)을 생성하여 복잡한 트리 구조도 선명하게 볼 수 있도록 합니다.
  • plot_tree 함수를 사용하여 final_dt_model의 구조를 그립니다.
  • filled=True는 각 노드의 클래스 비율에 따라 색상을 채우고, rounded=True는 노드 상자를 둥글게 만듭니다.
  • feature_namesclass_names를 지정하여 트리 노드에 특징 이름과 클래스 이름을 표시합니다.
  • 최종적으로 plt.show()를 호출하여 생성된 의사결정 트리를 화면에 출력합니다.

태그: scikit-learn DecisionTree ClassificationModel HyperparameterTuning ModelEvaluation

8월 6일 15:14에 게시됨