1. 필수 라이브러리 불러오기
데이터 처리, 수치 계산 및 모델링에 필요한 주요 라이브러리를 임포트합니다.
import pandas as pd
import openpyxl # pandas가 Excel 파일을 읽을 때 필요한 의존성
import numpy as np
pandas는 데이터 구조 및 분석 도구를 제공하여 데이터프레임 조작에 사용됩니다.openpyxl은pandas가 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_depth를best_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.pyplot과sklearn.tree의plot_tree함수를 임포트합니다.- 큰 크기의 그림(32x32 인치)을 생성하여 복잡한 트리 구조도 선명하게 볼 수 있도록 합니다.
plot_tree함수를 사용하여final_dt_model의 구조를 그립니다.filled=True는 각 노드의 클래스 비율에 따라 색상을 채우고,rounded=True는 노드 상자를 둥글게 만듭니다.feature_names와class_names를 지정하여 트리 노드에 특징 이름과 클래스 이름을 표시합니다.- 최종적으로
plt.show()를 호출하여 생성된 의사결정 트리를 화면에 출력합니다.