084 모델 해석 - SHAP
키워드: SHAP, 모델 해석
개요
SHAP(SHapley Additive exPlanations)은 게임 이론의 Shapley 값을 기반으로 모델 예측을 해석하는 방법입니다. 각 특성이 개별 예측에 얼마나 기여하는지 정량적으로 설명합니다.
실습 환경
- Python 버전: 3.11 권장
- 필요 패키지:
pycaret[full]>=3.0,shap
SHAP이란?
SHAP (SHapley Additive exPlanations):
핵심 아이디어:
- 각 특성의 "기여도"를 계산
- 게임 이론의 Shapley 값 응용
- 모델에 구애받지 않음 (Model-Agnostic)
Shapley 값:
- 협력 게임에서 각 참여자의 공정한 기여도
- 특성들의 모든 조합을 고려
- 일관성, 공정성 보장
PyCaret에서 SHAP
from pycaret.classification import *
from pycaret.datasets import get_data
# 084 데이터 로드
data = get_data('diabetes')
# 084 환경 설정
clf = setup(data, target='Class variable', session_id=42, verbose=False)
# 084 모델 생성
rf = create_model('rf')
# 084 SHAP 요약 플롯
interpret_model(rf)
# 084 또는 특정 플롯 타입 지정
interpret_model(rf, plot='summary')
SHAP 플롯 종류
Summary Plot (요약)
from pycaret.classification import *
clf = setup(data, target='Class variable', session_id=42, verbose=False)
rf = create_model('rf')
# 084 Summary Plot: 전체 특성 중요도 + 영향 방향
interpret_model(rf, plot='summary')
해석 방법
Summary Plot 해석:
- Y축: 특성 (중요도 순)
- X축: SHAP 값 (예측에 대한 기여)
- 색상: 특성 값 (빨강=높음, 파랑=낮음)
예시:
BMI 특성이 빨간색이고 SHAP > 0
→ BMI가 높을수록 양성 예측 확률 증가
Correlation Plot
from pycaret.classification import *
clf = setup(data, target='Class variable', session_id=42, verbose=False)
rf = create_model('rf')
# 084 특성 값과 SHAP 값의 관계
interpret_model(rf, plot='correlation')
Reason Plot (개별 예측)
from pycaret.classification import *
clf = setup(data, target='Class variable', session_id=42, verbose=False)
rf = create_model('rf')
# 084 특정 관측치의 예측 이유
interpret_model(rf, plot='reason', observation=10) # 11번째 행
해석 방법
Reason Plot 해석:
- 기준선(base value)에서 시작
- 각 특성이 예측을 밀거나 당김
- 빨강: 양성(1) 방향으로 밀음
- 파랑: 음성(0) 방향으로 밀음
결과:
- 최종 예측 확률 표시
- 어떤 특성이 결정에 기여했는지 명확
SHAP 직접 사용
import shap
from sklearn.ensemble import RandomForestClassifier
from pycaret.datasets import get_data
# 084 데이터 준비
data = get_data('diabetes')
X = data.drop('Class variable', axis=1)
y = data['Class variable']
# 084 모델 학습
model = RandomForestClassifier(n_estimators=100, random_state=42)
model.fit(X, y)
# 084 SHAP Explainer
explainer = shap.TreeExplainer(model)
shap_values = explainer.shap_values(X)
# 084 Summary Plot
shap.summary_plot(shap_values[1], X) # 클래스 1에 대한 SHAP
TreeExplainer vs KernelExplainer
import shap
from sklearn.ensemble import RandomForestClassifier
from sklearn.linear_model import LogisticRegression
# 084 트리 기반 모델: TreeExplainer (빠름)
rf = RandomForestClassifier()
rf.fit(X, y)
tree_explainer = shap.TreeExplainer(rf)
shap_values_tree = tree_explainer.shap_values(X)
# 084 다른 모델: KernelExplainer (느림, 범용)
lr = LogisticRegression()
lr.fit(X, y)
kernel_explainer = shap.KernelExplainer(lr.predict_proba, X[:100])
shap_values_kernel = kernel_explainer.shap_values(X[:100])
Force Plot (워터폴)
import shap
from sklearn.ensemble import RandomForestClassifier
model = RandomForestClassifier(n_estimators=100, random_state=42)
model.fit(X, y)
explainer = shap.TreeExplainer(model)
shap_values = explainer.shap_values(X)
# 084 단일 예측 설명
shap.force_plot(
explainer.expected_value[1],
shap_values[1][0],
X.iloc[0],
matplotlib=True
)
# 084 Waterfall Plot (더 명확)
shap.plots.waterfall(shap.Explanation(
values=shap_values[1][0],
base_values=explainer.expected_value[1],
data=X.iloc[0]
))
Dependence Plot
import shap
# 084 특정 특성의 영향 시각화
shap.dependence_plot(
'BMI', # 분석할 특성
shap_values[1], # SHAP 값
X, # 데이터
interaction_index='Age' # 상호작용 특성
)
특성 중요도 비교
import shap
import pandas as pd
import matplotlib.pyplot as plt
# 084 SHAP 기반 특성 중요도
shap_importance = pd.DataFrame({
'feature': X.columns,
'shap_importance': abs(shap_values[1]).mean(axis=0)
}).sort_values('shap_importance', ascending=False)
# 084 모델 내장 특성 중요도
model_importance = pd.DataFrame({
'feature': X.columns,
'model_importance': model.feature_importances_
}).sort_values('model_importance', ascending=False)
# 084 비교
fig, axes = plt.subplots(1, 2, figsize=(14, 6))
axes[0].barh(shap_importance['feature'], shap_importance['shap_importance'])
axes[0].set_title('SHAP Importance')
axes[0].invert_yaxis()
axes[1].barh(model_importance['feature'], model_importance['model_importance'])
axes[1].set_title('Model Feature Importance')
axes[1].invert_yaxis()
plt.tight_layout()
plt.savefig('importance_comparison.png', dpi=150)
회귀 문제에서 SHAP
from pycaret.regression import *
from pycaret.datasets import get_data
# 084 회귀 데이터
data = get_data('boston')
# 084 환경 설정
reg = setup(data, target='medv', session_id=42, verbose=False)
# 084 모델 생성
rf = create_model('rf')
# 084 SHAP
interpret_model(rf, plot='summary')
interpret_model(rf, plot='correlation')
interpret_model(rf, plot='reason', observation=5)
SHAP 값 저장 및 활용
import shap
import pandas as pd
import numpy as np
# 084 SHAP 값 계산
explainer = shap.TreeExplainer(model)
shap_values = explainer.shap_values(X)
# 084 DataFrame으로 변환
shap_df = pd.DataFrame(
shap_values[1], # 클래스 1
columns=[f'{col}_shap' for col in X.columns],
index=X.index
)
# 084 원본 데이터와 결합
result = pd.concat([X, shap_df], axis=1)
# 084 예측과 주요 기여 특성 분석
result['prediction'] = model.predict(X)
result['top_feature'] = shap_df.abs().idxmax(axis=1)
print(result[['prediction', 'top_feature']].head())
SHAP의 장단점
장점:
- 이론적 기반 (Shapley 값)
- 일관된 해석
- 로컬 + 글로벌 해석
- 모델에 구애받지 않음
단점:
- 계산 비용 높음
- 특성 독립성 가정
- 고차원에서 느림
- 상관된 특성 해석 주의
실무 활용
# 084 고객 이탈 예측 예시
# 084 이탈 확률이 높은 고객의 이유 분석
def explain_customer_churn(model, customer_data, explainer):
"""개별 고객의 이탈 예측 설명"""
# 예측
prob = model.predict_proba(customer_data)[0, 1]
# SHAP 값
shap_values = explainer.shap_values(customer_data)
# 상위 기여 특성
feature_contributions = pd.DataFrame({
'feature': customer_data.columns,
'value': customer_data.values[0],
'shap': shap_values[1][0]
}).sort_values('shap', key=abs, ascending=False)
print(f"이탈 확률: {prob:.2%}")
print("\n주요 이탈 요인:")
for _, row in feature_contributions.head(5).iterrows():
direction = "↑" if row['shap'] > 0 else "↓"
print(f" {row['feature']}: {row['value']:.2f} ({direction} {abs(row['shap']):.3f})")
return feature_contributions
정리
- SHAP: 게임 이론 기반 모델 해석
- 각 특성의 예측 기여도 정량화
- Summary Plot: 전체 특성 중요도
- Reason Plot: 개별 예측 설명
- TreeExplainer: 트리 모델용 (빠름)
- KernelExplainer: 범용 (느림)
다음 글 예고
다음 글에서는 모델 해석 - Feature Importance를 다룹니다.
PyCaret 머신러닝 마스터 시리즈 #084