본문으로 건너뛰기

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