본문으로 건너뛰기

091 모델 비교와 분석

키워드: compare_models, 모델 비교

개요

여러 모델을 체계적으로 비교하고 분석하는 것은 최적의 모델을 선택하는 핵심 과정입니다. PyCaret의 compare_models()와 다양한 분석 도구를 활용한 심층 비교 방법을 알아봅니다.

실습 환경

  • Python 버전: 3.11 권장
  • 필요 패키지: pycaret[full]>=3.0

compare_models 기본

from pycaret.classification import *
from pycaret.datasets import get_data

# 091 데이터 로드
data = get_data('diabetes')

# 091 환경 설정
clf = setup(data, target='Class variable', session_id=42, verbose=False)

# 091 모든 모델 비교
best = compare_models()

# 091 결과 테이블 확인
results = pull()
print(results)

비교 옵션

from pycaret.classification import *

clf = setup(data, target='Class variable', session_id=42, verbose=False)

# 091 상위 N개 모델 반환
top3 = compare_models(n_select=3)

# 091 특정 메트릭 기준 정렬
best_f1 = compare_models(sort='F1')
best_auc = compare_models(sort='AUC')

# 091 특정 모델만 비교
selected = compare_models(include=['rf', 'xgboost', 'lightgbm', 'catboost'])

# 091 특정 모델 제외
without_svm = compare_models(exclude=['svm', 'knn'])

# 091 교차 검증 폴드 수
best_cv10 = compare_models(fold=10)

비교 결과 분석

from pycaret.classification import *
import pandas as pd

clf = setup(data, target='Class variable', session_id=42, verbose=False)

# 091 모델 비교
best = compare_models()

# 091 결과 테이블
results = pull()

# 091 메트릭별 분석
print("=== 메트릭별 최고 모델 ===")
for col in ['Accuracy', 'AUC', 'Recall', 'Prec.', 'F1']:
if col in results.columns:
best_model = results[col].idxmax()
best_value = results[col].max()
print(f"{col}: {best_model} ({best_value:.4f})")

# 091 모델별 순위
results['Rank'] = results['Accuracy'].rank(ascending=False)
print("\n=== 정확도 순위 ===")
print(results[['Accuracy', 'Rank']].sort_values('Rank'))

다중 메트릭 비교

from pycaret.classification import *
import pandas as pd
import matplotlib.pyplot as plt

clf = setup(data, target='Class variable', session_id=42, verbose=False)

# 091 상위 5개 모델
top5 = compare_models(n_select=5)
results = pull()

# 091 레이더 차트용 데이터
metrics = ['Accuracy', 'AUC', 'Recall', 'Prec.', 'F1']
top5_results = results.head(5)

# 091 정규화
normalized = top5_results[metrics].apply(lambda x: (x - x.min()) / (x.max() - x.min() + 1e-10))

# 091 시각화
fig, ax = plt.subplots(figsize=(10, 6))
normalized.T.plot(kind='bar', ax=ax)
plt.title('Top 5 Models - Normalized Metrics')
plt.xlabel('Metric')
plt.ylabel('Normalized Score')
plt.legend(top5_results.index, loc='best')
plt.tight_layout()
plt.savefig('model_comparison.png', dpi=150)

통계적 유의성 검정

from pycaret.classification import *
from scipy import stats
import numpy as np

clf = setup(data, target='Class variable', session_id=42, verbose=False)

# 091 두 모델 비교
rf = create_model('rf')
xgb = create_model('xgboost')

# 091 교차 검증 점수 추출
from sklearn.model_selection import cross_val_score

X = get_config('X_train_transformed')
y = get_config('y_train_transformed')

rf_scores = cross_val_score(rf, X, y, cv=10, scoring='accuracy')
xgb_scores = cross_val_score(xgb, X, y, cv=10, scoring='accuracy')

print(f"RF: {rf_scores.mean():.4f} ± {rf_scores.std():.4f}")
print(f"XGBoost: {xgb_scores.mean():.4f} ± {xgb_scores.std():.4f}")

# 091 대응 t-검정
t_stat, p_value = stats.ttest_rel(rf_scores, xgb_scores)
print(f"\n대응 t-검정:")
print(f"t-통계량: {t_stat:.4f}")
print(f"p-value: {p_value:.4f}")

if p_value < 0.05:
print("→ 두 모델 간 유의미한 차이 있음")
else:
print("→ 두 모델 간 유의미한 차이 없음")

학습 시간 비교

from pycaret.classification import *
import time
import pandas as pd

clf = setup(data, target='Class variable', session_id=42, verbose=False)

# 091 학습 시간 측정
models = ['rf', 'xgboost', 'lightgbm', 'catboost', 'lr', 'knn']
timing_results = []

for model_id in models:
start = time.time()
model = create_model(model_id, verbose=False)
elapsed = time.time() - start

results = pull()
timing_results.append({
'Model': model_id,
'Accuracy': results['Accuracy'].values[0],
'Time (s)': elapsed
})

timing_df = pd.DataFrame(timing_results)
print(timing_df.sort_values('Time (s)'))

# 091 효율성 점수 (정확도 / 시간)
timing_df['Efficiency'] = timing_df['Accuracy'] / timing_df['Time (s)']
print("\n=== 효율성 순위 ===")
print(timing_df.sort_values('Efficiency', ascending=False))

모델 복잡도 분석

from pycaret.classification import *
import pandas as pd

clf = setup(data, target='Class variable', session_id=42, verbose=False)

def get_model_complexity(model):
"""모델 복잡도 추정"""
model_name = type(model).__name__

if hasattr(model, 'n_estimators'):
return {'trees': model.n_estimators}
elif hasattr(model, 'coef_'):
return {'params': model.coef_.size}
elif hasattr(model, 'support_vectors_'):
return {'support_vectors': len(model.support_vectors_)}
else:
return {'unknown': None}

# 091 여러 모델 비교
models = {
'rf': create_model('rf', verbose=False),
'xgboost': create_model('xgboost', verbose=False),
'lr': create_model('lr', verbose=False),
'knn': create_model('knn', verbose=False)
}

for name, model in models.items():
complexity = get_model_complexity(model)
print(f"{name}: {complexity}")

오버피팅 분석

from pycaret.classification import *
import pandas as pd

clf = setup(data, target='Class variable', session_id=42, verbose=False)

def check_overfitting(model):
"""학습/검증 점수 비교로 오버피팅 확인"""
from sklearn.model_selection import cross_validate

X = get_config('X_train_transformed')
y = get_config('y_train_transformed')

cv_results = cross_validate(
model, X, y, cv=5,
scoring='accuracy',
return_train_score=True
)

train_score = cv_results['train_score'].mean()
test_score = cv_results['test_score'].mean()
gap = train_score - test_score

return {
'train': train_score,
'test': test_score,
'gap': gap,
'overfit': gap > 0.05
}

# 091 모델별 오버피팅 확인
models = ['rf', 'xgboost', 'lr', 'dt']
overfit_results = []

for model_id in models:
model = create_model(model_id, verbose=False)
result = check_overfitting(model)
result['model'] = model_id
overfit_results.append(result)

overfit_df = pd.DataFrame(overfit_results)
print(overfit_df)

앙상블 후보 선택

from pycaret.classification import *

clf = setup(data, target='Class variable', session_id=42, verbose=False)

# 091 다양한 유형의 모델 선택 (다양성 확보)
# 091 트리 기반
rf = create_model('rf', verbose=False)
xgb = create_model('xgboost', verbose=False)

# 091 선형
lr = create_model('lr', verbose=False)

# 091 거리 기반
knn = create_model('knn', verbose=False)

# 091 블렌딩 (다양한 모델로)
blended = blend_models([rf, xgb, lr, knn])

# 091 결과 비교
print("=== 앙상블 vs 개별 모델 ===")
results = pull()
print(results)

회귀 모델 비교

from pycaret.regression import *
from pycaret.datasets import get_data

# 091 회귀 데이터
data = get_data('boston')

reg = setup(data, target='medv', session_id=42, verbose=False)

# 091 모든 모델 비교
best = compare_models()
results = pull()

# 091 회귀 메트릭: MAE, MSE, RMSE, R2, RMSLE, MAPE
print("\n=== 메트릭별 최고 모델 ===")
for metric in ['MAE', 'MSE', 'RMSE', 'R2']:
if metric in results.columns:
if metric == 'R2':
best_idx = results[metric].idxmax()
else:
best_idx = results[metric].idxmin()
print(f"{metric}: {best_idx}")

클러스터링 모델 비교

from pycaret.clustering import *
from pycaret.datasets import get_data

# 091 클러스터링 데이터
data = get_data('jewellery')

clust = setup(data, session_id=42, verbose=False)

# 091 여러 클러스터링 모델 비교
models_to_try = ['kmeans', 'ap', 'meanshift', 'sc', 'hclust', 'dbscan']
cluster_results = []

for model_id in models_to_try:
try:
model = create_model(model_id, verbose=False)
result = pull()
cluster_results.append({
'model': model_id,
'silhouette': result['Silhouette'].values[0] if 'Silhouette' in result.columns else None
})
except Exception as e:
print(f"{model_id} 오류: {e}")

import pandas as pd
cluster_df = pd.DataFrame(cluster_results)
print(cluster_df.sort_values('silhouette', ascending=False))

종합 비교 보고서

from pycaret.classification import *
import pandas as pd

clf = setup(data, target='Class variable', session_id=42, verbose=False)

def generate_comparison_report(models_to_compare):
"""종합 비교 보고서 생성"""

report = []

for model_id in models_to_compare:
model = create_model(model_id, verbose=False)
results = pull()

# 오버피팅 체크
from sklearn.model_selection import cross_validate
X = get_config('X_train_transformed')
y = get_config('y_train_transformed')
cv = cross_validate(model, X, y, cv=5, return_train_score=True)

report.append({
'Model': model_id,
'Accuracy': results['Accuracy'].values[0],
'AUC': results['AUC'].values[0] if 'AUC' in results.columns else None,
'F1': results['F1'].values[0],
'Train-Test Gap': cv['train_score'].mean() - cv['test_score'].mean(),
'CV Std': cv['test_score'].std()
})

report_df = pd.DataFrame(report)

# 종합 점수 (정규화 후 평균)
score_cols = ['Accuracy', 'AUC', 'F1']
for col in score_cols:
if col in report_df.columns:
report_df[f'{col}_norm'] = (report_df[col] - report_df[col].min()) / (report_df[col].max() - report_df[col].min() + 1e-10)

norm_cols = [c for c in report_df.columns if c.endswith('_norm')]
report_df['Overall'] = report_df[norm_cols].mean(axis=1)

return report_df.sort_values('Overall', ascending=False)

# 091 보고서 생성
models = ['rf', 'xgboost', 'lightgbm', 'lr', 'knn']
report = generate_comparison_report(models)
print(report)

정리

  • compare_models(): 한 번에 모든 모델 비교
  • 메트릭 선택: sort 파라미터로 기준 지정
  • 통계 검정: 모델 간 유의미한 차이 확인
  • 오버피팅: 학습-검증 갭 분석
  • 앙상블 후보: 다양한 유형 조합
  • 종합 평가: 정확도 + 안정성 + 효율성

다음 글 예고

다음 글에서는 PyCaret의 확장과 커스터마이징을 다룹니다.


PyCaret 머신러닝 마스터 시리즈 #091