Post

Shapley Value와 SHAP

Shapley Value와 SHAP에 대해서 간략한 설명과 실습 코드

Shapley Value와 SHAP(SHapley Additive exPlanations)

Shapley Value 와 SHAP는 이 데이터(분석단위)는 왜 그러한 결과로 예측 되었을까? 를 설명할 수 있는 방법 중 하나이다. 즉, 모델이 하나의 분석단위를 그렇게 예측한 이유에 대해 설명할 수 있다. 이는 실제 업무에서 사용자에게 설명할 수 있는 좋은 방법이라고 한다.

✅ Shapley Value

Shapley Value는 Feature의 가중 평균 기여도라고 할 수 있다.

예를 들어, A B C 라는 특성이 있을 때 A에 대한 Shapley Value를 계산하는 방법은 다음과 같다.

  1. A를 고정 시켜 놓고, 나머지 변수들로 조합을 구성한다.
    즉, (A), (A, B), (A, C), (A, B, C) 총 4(=$2^2$)개 가 있다.
  2. 이 각각의 조합에서 A를 포함했을 때의 예측 값과 A를 제외했을 때의 예측 값의 차이를 구한다.
    ex) (A, B, C) 에서의 예측값 - (B, C) 에서의 예측 값
  3. 여기에 가중치를 곱해서, 각 조합의 기여도를 합친다.

이를 식으로 표현하면 아래와 같다.

\[\large \phi_i(f, x) = \sum_{z^\prime \subseteq x^\prime}{\frac{\vert z^\prime \vert (M - \vert z^\prime \vert - 1)!}{M!}} \cdot [ f_x(z^\prime ) - f_x ( z^\prime | i) ]\]

식을 뜯어보지말고, 대략적인 느낌으로만 이해해보자.

  • $\sum_{z^\prime \subseteq x^\prime}$ : 조합 하나씩 더하기

  • ${\frac{\vert z^\prime \vert (M - \vert z^\prime \vert - 1)!}{M!}}$ : 가중치

  • $[f_x(z^\prime ) - f_x (z^\prime \vert i)]$ : 기여도

즉, 조합 별로 가중치 x 기여도의 값을 더한 것이 Shapley Value이다.

여기서 중요한 것은 예측 값에 대한 설명이라는 점이다. 실제 값과는 전혀 상관이 없다!

✅ SHAP(SHapely Additive exPlanation) 코드 실습

[SHAP 관련 코드]

파이썬에서 Shapley Value를 구하고, SHAP 분석을 시각화해보자. SHAP Explainer는 종류가 다양하게 있으며, 각 모델에 맞게 사용하면 된다.
[SHAP Explainers API Reference]

  1. 먼저 shap 라이브러리를 받자. pip install shap or conda install shap. Colab에서 한다면 !pip install shap을 실행하자.
  2. 모델을 학습시키고, SHAP 값으로 모델의 예측을 설명하면 된다.

✔️ Shapley Value 구하기

1
2
3
4
5
6
7
# 학습
rf_model = RandomForestRegressor()
rf_model.fit(x_train, y_train)

# 해석
explainer = shap.TreeExplainer(rf_model)
shap_values = explainer.shap_values(x_train)
  • x_train과 shap_values의 크기는 동일하다.
  • shap_values가 각 feature에 대한 기여도를 담고 있기 때문이다.
  • Shapley Value의 행 별의 합 = $\hat{y}$ - 평균
1
2
# 동일한 크기
x_train.shape, shap_values.shape
1
((404, 12), (404, 12))
1
pd.DataFrame(shap_values, columns=list(x))[:1]
crimzninduschasnoxrmagedisradtaxptratiolstat
00.401934-0.006239-0.092199-0.0145150.241373-2.3661290.085752-0.365353-0.0094920.3438640.25944-0.504673
1
x_train.iloc[:1, :]
crimzninduschasnoxrmagedisradtaxptratiolstat
500.0887321.05.6400.4395.96345.76.8147424316.813.45
  • 예측 값
1
2
y_pred = rf_model.predict(x_train.iloc[:1, :])
y_pred[0]
1
19.83200000000003
  • train의 예측 값의 전체 평균
1
rf_model.predict(x_train).mean()
1
21.84210891089109
  • 예측 값과 예측 평균 간의 차이
1
y_pred[0] - rf_model.predict(x_train).mean()
1
-2.0101089108910593
  • Shapley Value의 합
1
shap_values[:1, :].sum()
1
-2.026235148514834
  • 하나의 분석단위에 대한 Shapley Value 의 합 = 예측 값 - 예측 평균
    • 랜덤 포레스트의 경우, 알고리즘의 특성상 약간의 차이가 발생 될 수 있다고 한다.

✔️ shap.force_plot

  • 화살표의 길이 : Shapley Value, 기여도
  • base value : 예측 값의 평균
1
2
3
4
5
shap.initjs() # javascript 시각화 라이브러리 --> colab에서는 모든 셀에 포함시켜야 함

idx = 0
# force_plot(전체평균, shapley_values, input)
shap.force_plot(explainer.expected_value, shap_values[idx, :], x_train.iloc[idx,:])

force_plot

✔️ shap.summary_plot

  • 각 변수별 shapley value 분포를 한눈에 보여준다.
  • 색깔은 해당 변수의 값의 크기를 나타낸다.
1
shap.summary_plot(shap_values, x_train)

output_21_0

✔️ shap.force_plot 특정 관점으로 보기

1
2
shap.initjs()
shap.force_plot(explainer.expected_value, shap_values, x_train)

force_plot2

✔️ shap.dependence_plot

  • 특정 변수 값과 변수의 shap value 간의 관계 확인
1
shap.dependence_plot('lstat', shap_values, x_train)

output_25_0

1
shap.dependence_plot('lstat', shap_values, x_train, interaction_index = 'nox')

output_26_0

This post is licensed under CC BY 4.0 by the author.

Feature Importance

비즈니스 관점의 모델 평가