안녕하세요. 오태호입니다.

이 글에서는 SHAP(SHapley Additive exPlanations)에 대해 설명해 보려고 합니다. SHAP은 SHAP Python Package의 공식 문서(https://shap.readthedocs.io)를 살펴봐도 사용법이 간단한 듯 하면서도 어느 정도 동작 원리를 이해하지 못하면 사용하기가 쉽지가 않습니다. 그래서 이 글에서는 SHAP에 대해 복잡하고 깊은 내용은 생략하고 SHAP을 이해하고 활용하는데 문제가 없을 정도 수준으로 이해하기 쉽게 설명해 보도록 하겠습니다.

Shapley Value

SHAP을 이해하기 위해서는 SHAP의 기반이 되는 Shapley Value를 이해해야 합니다. Shapley Value는 다음과 같은 문제를 풀기 위해 고안되었습니다.

Alice, Bob, Charlie, Dave가 함께 일을 해서 \(\$60\)의 이익이 발생했습니다. 이 발생한 이익을 4명에게 공정하게 배분해서 나눠 가지려면 어떻게 나눠 가지면 좋을까요? 공정하게 나눠 가질 수 있는 방법은 무수히 많이 있을 수 있습니다. 모두 똑같이 \(\$15\)씩 나눠 가지는 방법이 있을 수 있습니다. 아니면 각자 혼자 일을 했을 경우 발생할 이익을 각자의 능력으로 보고 능력에 비례해서 나눠 가지는 방법이 있을 수도 있습니다.

참고로 Alice, Bob, Charlie, Dave 각자가 일에 참여했을 때와 참여하지 않았을 때 발생하는 이익은 다음과 같았습니다.

일에 참여한 사람 이익($)
(없음) 0
Alice 15
Bob 21
Alice, Bob 24
Charlie 9
Alice, Charlie 24
Bob, Charlie 33
Alice, Bob, Charlie 36
Dave 30
Alice, Dave 33
Bob, Dave 36
Alice, Bob, Dave 39
Charlie, Dave 51
Alice, Charlie, Dave 54
Bob, Charlie, Dave 57
Alice, Bob, Charlie, Dave 60

이 Data를 살펴보면 다음과 같은 몇 가지 특징을 알 수 있습니다.

  • Alice와 Bob은 각자 혼자 일할 때는 이익이 나쁘지 않은데 함께 일을 할 때는 이익이 많이 좋아지지는 않았습니다. 아마 Alice와 Bob은 일의 잘 하는 영역이 비슷해서 시너지 효과가 크지 않은 것으로 추정됩니다.
  • Charlie는 Alice, Bob, Dave에 비해서 이익을 많이 내지는 못하지만 다른 사람과 함께 일하면 크게 시너지 효과를 내는 것으로 보입니다.
  • Dave는 혼자서 일을 할 때 Alice, Bob, Charlie가 혼자서 일할 때와 비교해 봤을 때 가장 크게 이익을 냅니다.

이 Data를 기반으로 해서 공정하게 이익을 배분하고 싶은데 대충 살펴봤을 때는 어떻게 배분하는게 공정할지 생각이 쉽게 떠오르지 않습니다.

Shapley Value는 이런 문제를 풀기 위해 고안되었습니다. Alice, Bob, Charlie, Dave 각각의 Shapley Value는 Alice, Bob, Charlie, Dave에게 공정하게 배분될 이익입니다.

Alice의 Shapley Value는 다음과 같이 계산합니다. Alice, Bob, Charlie, Dave을 줄을 세우고(Permutation), Alice보다 앞에 있는 사람들이 일에 참여했을 때 이익과, Alice와 Alice보다 앞에 있는 사람들이 일에 참여했을 때 이익의 차이가, Alice의 공헌이라고 볼 수 있습니다. 예를 들어, Charlie, Bob, Alice, Dave로 줄을 세웠다면 Alice보다 앞에 있는 Charlie, Bob가 일에 참여했을 때 발생한 이익인 \(33\)과, 여기에 Alice가 참여해서 Charlie, Bob, Alice가 일에 참여했을 때 발생한 이익인 \(36\)의 차이인, \(36-33=3\)이 Alice의 공헌이라고 볼 수 있습니다. 이때 Alice의 공헌은 Alice, Bob, Charlie, Dave를 어떻게 줄을 세웠냐에 따라 달라지기 때문에, 4명을 줄을 세울 수 있는 모든 경우에 대해 각각 Alice의 공헌을 계산합니다. 이렇게 구한 Alice의 각각의 공헌의 평균이 Alice의 Shapley Value입니다.

4명의 줄세우기 Alice의 공헌 Bob의 공헌 Charlie의 공헌 Dave의 공헌
Alice, Bob, Charlie, Dave 15-0=15 24-15=9 36-24=12 60-36=24
Alice, Bob, Dave, Charlie 15-0=15 24-15=9 60-39=21 39-24=15
Alice, Charlie, Bob, Dave 15-0=15 36-24=12 24-15=9 60-36=24
Alice, Charlie, Dave, Bob 15-0=15 60-54=6 24-15=9 54-24=30
Alice, Dave, Bob, Charlie 15-0=15 39-33=6 60-39=21 33-15=18
Alice, Dave, Charlie, Bob 15-0=15 60-54=6 54-33=21 33-15=18
Bob, Alice, Charlie, Dave 24-21=3 21-0=21 36-24=12 60-36=24
Bob, Alice, Dave, Charlie 24-21=3 21-0=21 60-39=21 39-24=15
Bob, Charlie, Alice, Dave 36-33=3 21-0=21 33-21=12 60-36=24
Bob, Charlie, Dave, Alice 60-57=3 21-0=21 33-21=12 57-33=24
Bob, Dave, Alice, Charlie 39-36=3 21-0=21 60-39=21 36-21=15
Bob, Dave, Charlie, Alice 60-57=3 21-0=21 57-36=21 36-21=15
Charlie, Alice, Bob, Dave 24-9=15 36-24=12 9-0=9 60-36=24
Charlie, Alice, Dave, Bob 24-9=15 60-54=6 9-0=9 54-24=30
Charlie, Bob, Alice, Dave 36-33=3 33-9=24 9-0=9 60-36=24
Charlie, Bob, Dave, Alice 60-57=3 33-9=24 9-0=9 57-33=24
Charlie, Dave, Alice, Bob 54-51=3 60-54=6 9-0=9 51-9=42
Charlie, Dave, Bob, Alice 60-57=3 57-51=6 9-0=9 51-9=42
Dave, Alice, Bob, Charlie 33-30=3 39-33=6 60-39=21 30-0=30
Dave, Alice, Charlie, Bob 33-30=3 60-54=6 54-33=21 30-0=30
Dave, Bob, Alice, Charlie 39-36=3 36-30=6 60-39=21 30-0=30
Dave, Bob, Charlie, Alice 60-57=3 36-30=6 57-36=21 30-0=30
Dave, Charlie, Alice, Bob 54-51=3 60-54=6 51-30=21 30-0=30
Dave, Charlie, Bob, Alice 60-57=3 57-51=6 51-30=21 30-0=30

Alice, Bob, Charlie, Dave의 각각의 Shapley Value는 다음과 같이 평균을 계산합니다.

  • Alice의 Shapley Value
    • \[\tiny{(15+15+15+15+15+15+3+3+3+3+3+3+15+15+3+3+3+3+3+3+3+3+3+3)/24=7}\]
  • Bob의 Shapley Value
    • \[\tiny{(9+9+12+6+6+6+21+21+21+21+21+21+12+6+24+24+6+6+6+6+6+6+6+6)/24=12}\]
  • Charlie의 Shapley Value
    • \[\tiny{(12+21+9+9+21+21+12+21+12+12+21+21+9+9+9+9+9+9+21+21+21+21+21+21)/24=15.5}\]
  • Dave의 Shapley Value
    • \[\tiny{(24+15+24+30+18+18+24+15+24+24+15+15+24+30+24+24+42+42+30+30+30+30+30+30)/24=25.5}\]

Alice, Bob, Charlie, Dave의 각각의 Shapley Value를 합해보면 전체 이익 \(60\)과 일치하는 것을 알 수 있습니다.

  • \[7+12+15.5+25.5=60\]

혼자서 일을 할 때는 Alice와 Bob은 Charlie에 비해 높은 공헌을 하는 것처럼 보이지만 Charlie의 경우에는 다른 사람과 같이 일을 할 때 공헌을 크게 하는 경향이 있어서 Alice나 Bob에 비해 더 크게 이익에 공헌을 했을 수도 있다고 생각하였는데, 이것을 Shapley Value를 계산해서 살펴보면 Charlie가 Alice나 Bob에 비해 크게 공헌하였다는 것을 확인할 수 있습니다.

Shapley Value를 일반화해서 수식으로 다음과 같이 정리할 수 있습니다.

Alice, Bob, Charlie, Dave와 같이 일에 참여한 사람들을 Player라고 정의합니다. 각자 Player는 숫자로 지칭하여 Alice, Bob, Charlie, Dave 각각을 Player 1, Player 2, Player 3, Player 4라고 합니다. 전체 \(n\)명의 Player의 집합 \(N\)은 다음과 같이 정의합니다.

\[N=\left\{1,2,\cdots,n\right\}\]

\(S\)는 \(N\)의 부분집합으로 정의합니다.

\[S \subset N\]

\(v(S)\)는 Value Function이라고 부르고, \(S\)의 Player들이 협력해서 만들어 낸 결과의 가치로 정의합니다.

\(R\)은 \(N\)이 가질 수 있는 임의의 Permutation으로 정의합니다.

\(S_i^R\)은 Permutation R에서 Player \(i\)의 앞에 있는 Player들의 집합으로 정의합니다. 이 집합에 Player \(i\)는 포함되지 않습니다.

\(\phi_i\)는 Player \(i\)의 Shapley Value로 정의합니다.

\(\phi_i\)는 다음과 같이 계산합니다.

\[\phi_i=\frac{1}{|N|!}\sum_R(v(S_i^R \cup \left\{i\right\})-v(S_i^R))\]

정리해서 설명하면, \(n\)명의 전체 Player들을 Permutation(줄세우기)하면서, Player \(i\)의 앞에 있는 사람들이 협력해서 만들어 낸 결과의 가치와, Player \(i\)의 앞에 있는 사람들과 Player \(i\)가 협력해서 만들어 낸 결과의 가치와 차이를, Player \(i\)의 공헌이라고 보고, 이런 식으로 모든 경우의 Permutation에 대해서 Player \(i\)의 공헌을 구하고, 이것의 평균을 계산한 값이 Shapley Value입니다.

Shapley Value가 어떤 것인지 이해가 되더라도 왜 굳이 Player들의 공헌도를 계산하는데 이렇게 직관적이지 않은 이상한 계산방법을 사용하는지 궁금할 것이라고 생각합니다. 이것은 Player들의 공헌도를 공정하게 측정하기 위한 공정함을 다음과 같이 정의했기 때문입니다.

  • Efficiency
    • \[\sum_i^n \phi_i = v(N)\]
    • 모든 Player의 Shapley Value를 합하면 모든 Player가 협력해서 만들어 낸 결과의 가치가 됩니다.
  • Dummy Player
    • 어떤 \(i\)가 있을 때, \(S \subset N - \left\{i\right\}\)인 모든 \(S\)에 대해서 \(v(S \cup \left\{i\right\})-v(S)=0\)이면, \(\phi_i=0\)입니다.
    • 아무런 공헌을 하지 않은 Player의 Shapley Value는 0입니다.
  • Symmetry
    • 어떤 \(i\)와 \(j\) 있을 때, \(S \subset N - \left\{i, j\right\}\)인 모든 \(S\)에 대해서 \(v(S \cup \left\{i\right\})-v(S)=v(S \cup \left\{j\right\})-v(S)\)이면, \(\phi_i=\phi_j\)입니다.
    • 동일한 공헌을 한 Player의 Shapley Value는 같습니다.
  • Additivity
    • 기존 \(v\)와 다른 Value Function인 \(w\)를 정의하고, 새로운 Value Function인 \(w'\)를 \(w'(S \cup \left\{i\right\})-w'(S)=v(S \cup \left\{i\right\})-v(S)+w(S \cup \left\{i\right\})-w(S)\)과 같이 정의하면, \(w'\)의 Value Function으로 구한 Shapley Value인 \(\phi_i(w')\)는 \(\phi_i(w')=\phi(v)+\phi(w)\)가 성립합니다.

여기서 수학적인 증명은 하지 않겠습니다만, 공정한 공헌도를 이와같이 정의를 하고 각 Player의 공헌도를 계산해 봤더니 다음과 같은 Shapley Value의 식이 도출되었습니다.

\[\phi_i=\frac{1}{|N|!}\sum_R(v(S_i^R \cup \left\{i\right\})-v(S_i^R))\]

이것은 Unique Solution이라고 증명되었으며, 이 식을 도출한 Lloyd Shapley는 이 공로로 노벨 경제학상을 수상했습니다.

만약에 공정한 공헌도를 보다 더 합리적인 다른 방법으로 새로 정의한다면 각 Player의 공헌도의 계산방법은 거기에 맞춰서 변경되어야 합니다.

Shapley Value Calculation

Shapley Value는 Player수가 늘어나면 계산량이 매우 크게 늘어나는 것을 알 수 있습니다. 앞에서 살펴봤던 Shapley Value 계산 식을 살펴보면 Shapley Value를 계산하기 위해서는 Player가 \(N\)명일 때 $|N|!$번의 합산이 필요합니다.

\[\phi_i=\frac{1}{|N|!}\sum_R(v(S_i^R \cup \left\{i\right\})-v(S_i^R))\]

이 계산을 자세히 살펴보면 Player \(i\)의 앞에 있는 Player들의 순서가 바뀌어도 계산 결과는 같으며 Player \(i\)의 뒤에 있는 Player들의 순서가 바뀌어도 계산 결과는 같기 때문에, 많은 중복계산을 하고 있는 것을 알 수 있습니다. 이런 중복 계산을 제거할 수 있지만 제거를 해도 여전히 상당히 많은 합산이($2^{\left|N\right|-1}$번의 합산이) 필요합니다.

그래서 Shapley Value를 계산하다 보면 현실적으로 계산하기가 거의 불가능한 경우를 많이 만나게 되고 이런 경우에는 여러 가지 각종 방법을 사용해서 Shapley Value를 Estimation해서 계산해서 사용합니다.

Shapley Value를 Estimattion해서 계산하는 방법중에 하나로 Player들의 Permutation의 모든 경우의 수를 전부 계산하지 않고, 적당히 \(m\)개의 Permutation을 Random Sample해서 계산하는 방식이 있을 수 있습니다. 즉, 모든 경우의 Permutation인 $|N|!$번의 합산을 하고 $|N|!$으로 나누어서 정확한 Shapley Value를 계산하는 것이 아니라, 적당히 감당할 수 있는 Permutation \(m\)개를 Random Sample해서 합산을 하고 $m$으로 나누어서 Shapley Value를 Estimation해서 계산합니다.

예를 들어 앞의 Shapley Value의 예를 기반으로 예를 들어 살펴보면 다음과 같은 방법으로 계산할 수 있습니다.

  1. 24개의 Permutation중에 1개를 Random Sample합니다.
    • 여기서는 Alice, Charlie, Dave, Bob를 Random Sample했습니다.
  2. Alice의 공헌도는, Alice가 일 했을 때 이익과, 아무도 일 하지 않았을 때 이익의, 차이로 계산합니다.
    • 15-0=15
  3. Charlie의 공헌도는, Alice와 Charlie가 함께 일 했을 때 이익과, Alice가 일 했을 때의 이익의, 차이로 계산합니다.
    • 24-15=9
    • Alice가 일 했을 때의 이익은 2에서 계산한 결과를 가져다가 사용해서 계산량을 줄입니다.
  4. Dave의 공헌도는, Alice와 Charlie와 Dave가 함께 일 했을 때의 이익과, Alice와 Charlie가 함께 일 했을 때의 이익의, 차이로 계산합니다.
    • 54-24=30
    • Alice와 Charlie가 함께 일 했을 때의 이익은 3에서 계산한 결과를 가져다가 사용해서 계산량을 줄입니다.
  5. Bob의 공헌도는, Alice와 Charlie와 Dave와 Bob이 함께 일 했을 때의 이익과, Alice와 Charlie와 Dave가 함께 일 했을 때의 이익의, 차이로 계산합니다.
    • 60-54=6
    • Alice와 Charlie와 Dave가 함께 일 했을 때의 이익은 4에서 계산한 결과를 가져다가 사용해서 계산량을 줄입니다.
  6. 1로 돌아가서 다른 Permutation을 Random Sample해서 동일하게 계산하며 이것을 \(m\)번 반복합니다.
  7. 이렇게 구한 \(m\)개의 Alice, Bob, Charlie, Dave의 각각의 \(m\)개의 공헌도를 합하고 \(m\)으로 나눠서 구한 평균이 Shapley Value의 Estimation이 됩니다.

\(m\)을 크게 설정할수록 Shapley Value과 가까운 결과를 얻게 되며, \(m\)을 $|N|!$로 설정하고 Permutation을 Random Sample하지 않고 모든 Permutation을 사용하게 되면 Shapley Value와 결과가 일치하게 됩니다.

SHAP Value

Shapley Value에 대해 설명했으니 이제 Shapley Value를 기반으로 SHAP(SHapley Additive exPlanations)에 대해서 설명하겠습니다.

복잡한 Machine Learning Model \(f(\textbf{x})\)가 있다고 가정해 봅시다. Model의 Feature \(\textbf{x}\)는 \(\textbf{x}=(x_1, x_2, \cdots, x_p)\)와 같이 \(p\)차원으로 구성되어 있습니다.

예를 들어 \(\textbf{x}=(1, 5, 9, 6)\)으로 주어졌고, 이때 \(f(\textbf{x})=f(1, 5, 9, 6)=4\)가 나왔다고 가정해 봅시다.

\(x_1=1\), \(x_2=5\), \(x_3=9\), \(x_4=6\)의 각각의 Feature가 \(f(1, 5, 9, 6)=4\)의 결과에 얼마나 공헌을 했는지 알고 싶습니다. Machine Learning Model \(f(\textbf{x})\)가 구조가 복잡해서 쉽게 파악하기가 쉽지 않은 상황이고 어떤 Feature가 얼마나 크게 Model의 출력값에 영향을 줬는지 알고 싶습니다.

이 문제를 잘 살펴보면 Alice, Bob, Charlie, Dave가 함께 일을 해서 이익을 내고, 각자 공헌도에 따라 이익을 공정하게 배분하기 위해, Shapley Value를 계산해서 이익을 공정하게 나누어 가지는 것과 동일한 문제라는 것을 알 수 있습니다.

앞에서 Alice, Bob, Charlie, Dave의 Shapley Value를 계산할 때 Alice, Bob, Charlie, Dave 각자가 일에 참여한 경우와 참여하지 않은 경우에 발생한 이익을 바탕으로 계산했습니다. 여기서는 \(x_1=1\), \(x_2=5\), \(x_3=9\), \(x_4=6\) 각각의 Feature가 참여한 경우와(Feature를 Model에 입력한 경우와) 참여하지 않은 경우의(Feature를 Model에 입력하지 않은 경우의) \(f(\textbf{x})\)의 값을 바탕으로 계산합니다.

Feature를 Model에 입력하지 않는 것이 얼핏 생각하면 쉽다고 생각할 수도 있는데, 이게 엄밀하게는 하기에는 쉽지 않은 작업이며, 현실적으로는 적절하게 타협이 필요한 경우가 많습니다. 일단은 Feature를 Model에 입력하지 않는 것이 가능하다고 가정하고 설명하고, Feature를 Model에 입력하지 않기 위해서는 어떻게 하면 좋을지 살펴보도록 하겠습니다.

\(x'_i\)를 \(x_i\) Feature가 Model에 입력되는지 유무로 정의합니다. \(x'_i=0\)이면 \(x_i\) Feature를 Model에 입력하지 않는 것을 의미하고 \(x'_i=1\)이면 \(x_i\) Feature를 Model에 입력하는 것을 의미합니다.

\(x_1=1\), \(x_2=5\), \(x_3=9\), \(x_4=6\)이고 \(f(1, 5, 9, 6)=4\)인 경우 다음을 만족하는 \(\phi_0, \phi_1, \cdots, \phi_p\)를 계산합니다. 이렇게 계산한 \(\phi_0, \phi_1, \cdots, \phi_p\)가 SHAP Value입니다.

\[f(1, 5, 9, 6)=\phi_0+\phi_1x'_1+\phi_2x'_2+\cdots+\phi_px'_p=4\]

Shapley Value를 계산할 때 썼던 방법하고 동일한 방법을 사용하기 위해 일단 모든 Feature가 Model에 입력되지 않았을 때 결과가 \(0\)이 되도록 수식을 다음과 같이 수정합니다.

\[f(1, 5, 9, 6)-\phi_0=\phi_1x'_1+\phi_2x'_2+\cdots+\phi_px'_p=4-\phi_0\]

\(\phi_0\)는 Model에 Feature를 아무것도 입력하지 않았을 때 \(f(\textbf{x})\)의 결과값입니다.

앞에서 다뤘던 Shapley Value와 대비해서 생각해 보면 다음과 같은 의미로 이해할 수 있습니다.

  • \(\phi_0\)는 모든 Feature가 Model에 전혀 전달되지 않았을 때 Model의 결과값입니다.
    • \(\phi_0\)는 Model의 평균적인 결과값으로 이해할 수 있습니다.
  • \(\phi_1\)는 \(x_1=1\) Feature가 Model의 결과값이 \(4-\phi_0\)가 되게 한 공헌도입니다.
  • \(\phi_2\)는 \(x_2=5\) Feature가 Model의 결과값이 \(4-\phi_0\)가 되게 한 공헌도입니다.
  • \(\phi_3\)는 \(x_3=9\) Feature가 Model의 결과값이 \(4-\phi_0\)가 되게 한 공헌도입니다.
  • \(\phi_4\)는 \(x_4=6\) Feature가 Model의 결과값이 \(4-\phi_0\)가 되게 한 공헌도입니다.

SHAP Value Calculation

Shapley Value Calculation에서 Permutation을 Random Sample해서 Alice, Bob, Charlie, Dave의 Shapley Value를 계산했었는데, 동일한 방법으로 \(x_1=1\) Feature, \(x_2=5\) Feature, \(x_3=9\) Feature, \(x_4=6\) Feature의 SHAP Value를 다음과 같이 계산할 수 있습니다. \(?\)는 해당 Feature를 Model에 입력하지 않았다는 것을 의미합니다.

  1. 24개의 Permutation중에 1개를 Random Sample합니다.
    • \(x_1=1\), \(x_3=9\), \(x_4=6\), \(x_2=5\)를 Random Sample했습니다.
  2. \(x_1=1\) Feature의 공헌도는, \(x_1=1\) Feature가 Model에 입력되었을 때 결과값과, 아무 Feature도 Model에 입력되지 않았을 때 결과값의, 차이로 계산합니다.
    • \[f(1,?,?,?)-f(?,?,?,?)\]
  3. \(x_3=9\) Feature의 공헌도는, \(x_1=1\) Feature와 \(x_3=9\) Feature가 함께 Model에 입력되었을 때 결과값과, \(x_1=1\) Feature가 Model에 입력되었을 때 결과값의, 차이로 계산합니다.
    • \[f(1,?,9,?)-f(1,?,?,?)\]
    • \(x_1=1\) Feature가 Model에 입력되었을 때 결과값은 2에서 계산한 결과를 가져다가 사용해서 계산량을 줄입니다.
  4. \(x_4=6\) Feature의 공헌도는, \(x_1=1\) Feature와 \(x_3=9\) Feature와 \(x_4=6\) Feature가 함께 Model에 입력되었을 때 결과값과, \(x_1=1\) Feature와 \(x_3=9\) Feature가 함께 Model에 입력되었을 때 결과값의, 차이로 계산합니다.
    • \[f(1,?,9,6)-f(1,?,9,?)\]
    • \(x_1=1\) Feature와 \(x_3=9\) Feature가 함께 Model에 입력되었을 때 결과값은 3에서 계산한 결과를 가져다가 사용해서 계산량을 줄입니다.
  5. \(x_2=5\) Feature의 공헌도는, \(x_1=1\) Feature와 \(x_3=9\) Feature와 \(x_4=6\) Feature와 \(x_2=5\) Feature가 함께 Model에 입력되었을 때 결과값과, \(x_1=1\) Feature와 \(x_3=9\) Feature와 \(x_4=6\) Feature가 함께 Model에 입력되었을 때 결과값의, 차이로 계산합니다.
    • \[f(1,5,9,6)-f(1,?,9,6)\]
    • \(x_1=1\) Feature와 \(x_3=9\) Feature와 \(x_4=6\) Feature가 함께 Model에 입력되었을 때 결과값은 4에서 계산한 결과를 가져다가 사용해서 계산량을 줄입니다.
  6. 1로 돌아가서 다른 Permutation을 Random Sample해서 동일하게 계산하며 이것을 \(m\)번 반복합니다.
  7. 이렇게 구한 \(m\)개의 \(x_1=1\) Feature, \(x_2=5\) Feature, \(x_3=9\) Feature, \(x_4=6\) Feature의 각각의 \(m\)개의 공헌도를 합하고 \(m\)으로 나눠서 구한 평균이 SHAP Value의 Estimation이 됩니다.

참고로 SHAP Python Package에서 이 방법으로 SHAP Value를 계산하고 싶으면 Permutation Explainer를 사용하면 계산할 수 있습니다. Permutation Explainer는 Feature 수가 많은 Tabular Data의 경우에 사용되는 Default Model Agnostic Explainer입니다.

이제 특정 Feature를 Model에 입력하지 않는 방법만 고안하면 SHAP Value를 계산할 수 있습니다.

일단 \(f(?,?,?,?)\)의 경우에는 어떻게 하면 좋을지 알아보도록 하겠습니다. \(f(?,?,?,?)\)는 Feature가 전혀 주어지지 않았을 때 Model의 Output입니다. 이것은 Model을 사용할 때 Input으로 주어지는 Feature들을 모아서 Dataset을 만든 후에, Dataset의 Data를 하나하나 넣어서 \(f(\textbf{x})\)의 출력값을 계산하고, 이 출력값의 평균을 계산하면 구할 수 있습니다. 너무 Data가 많아서 계산하기가 부담되면 적당히 Random Sample해서 평균을 계산합니다. Random Sample의 수가 클수록 값은 정확해집니다. 이런 용도로 사용하는 Dataset을 Background Dataset이라고 부릅니다.

\(f(1,?,?,?)\)의 경우에는 Background Dataset에서 \(x_1=1\)인 경우만 모은 Data 하나하나를 넣어서 \(f(\textbf{x})\)의 출력값을 계산한 후에 이 출력값의 평균을 계산합니다.

\(f(1,?,9,?)\)의 경우에는 Background Dataset에서 \(x_1=1\), \(x_3=9\)인 경우만 모은 Data 하나하나를 넣어서 \(f(\textbf{x})\)의 출력값을 계산한 후에 이 출력값의 평균을 계산합니다.

\(f(1,?,9,6)\)의 경우에는 Background Dataset에서 \(x_1=1\), \(x_3=9\), \(x_4=6\)인 경우만 모은 Data 하나하나를 넣어서 \(f(\textbf{x})\)의 출력값을 계산한 후에 이 출력값의 평균을 계산합니다.

하지만 Background Dataset에서 \(x_1=1\), \(x_3=9\), \(x_4=6\)인 경우의 Data를 모아봤을 때 Data가 매우 희박할 가능성이 높으며 Input Feature의 차원이 높아질수록 Data가 아예 존재하지 않을 가능성이 매우 높아집니다. 그래서 이 부분을 적당한 타협이 필요합니다. 가장 과격한 타협안으로는 \(x_1=1\), \(x_3=9\), \(x_4=6\) 조건없이 Background Dataset에서 Data를 Random Sample하는 방법이 있을 수 있습니다. 하지만 이것은 실제로 존재하지 않는 Feature Input을 Model에 줘서 Model이 오동작하고 SHAP Value도 비정상적으로 계산될 가능성이 있습니다. 예를 들어 \(x_4=6\) Feature가 국가코드 한국을 의미하는 Feature였고 \(x_2=5\) Feature가 도시코드 서울의 의미하는 Feature였을 때, \(x_1=1\), \(x_3=9\), \(x_4=6\)조건을 무시하고 Background Dataset에서 Random Sample을 하게 되면 \(x_4=6\) 국가코드 한국, \(x_2=8\) 도시코드 도쿄로 Model에 입력되면서 Model이 오동작할 가능성이 있습니다. Model의 구성에 따라서는 정상적인 출력을 하지 못하고 Exception이 발생할 수도 있습니다. 그래서 이런 경우에는 \(x_1=1\), \(x_3=9\), \(x_4=6\)조건으로 Background Dataset에서 Random Sample을 시도할 때 \(x_4=6\)조건으로만 Background Dataset에서 Random Sample을 시도하는 방법이 있을 수 있습니다. 만약에 혹시 가능하다면 Feature에 특정 값을 설정하면(ex. \(x_2=0\)) 해당 Feature가 Model에 전달되지 않았다는 뜻으로 해석되도록 Model을 구성하는 방법도 있을 수 있습니다. 아니면, 저렇게 비현실적인 Feature가 Model에 입력되더라도 Model이 비정상작동을 하지 않도록 Model을 구성하고 Background Dataset에서 조건 없이 Random Sample하는 방법도 있습니다.

참고로 SHAP Python Package에서 Model에 전달되는 특정 Feature를 전달되지 않도록 하는 기능을 원하는 방법으로 Custom하게 변경하고 싶으면 Custom Masker를 적절하게 만들어서 설정합니다.

SHAP Value를 계산하기 위해 계산량을 줄이기 위해서는 여러 Feature를 하나의 Feature로 묶어서 SHAP Value를 계산하는 Feature의 수를 줄이는 것도 좋습니다. SHAP Value를 계산하는 Feature의 수가 늘어날수록 각 Feature의 Model에 전달 여부를 고려해야 해서 계산량이 폭증하기 때문입니다. 예를 들어 Model에 Feature중에 1024차원의 Embedding Vector가 있다고 했을 때 이 Feature를 1024개의 Feature로 보고 1024차원의 Vector의 각각의 Element의 SHAP Value를 구할 필요가 있는지 고민해 보는게 좋습니다. 만약에 1024차원의 Vector의 각각의 Element의 SHAP Value가 필요한 것이 아니라 1024차원의 Vector를 가지는 Feature의 SHAP Value가 필요한 것이라면 1024차원의 Vector를 가지는 Feature를 1024개의 Feature가 아니라 1개의 Feature로 보고 SHAP Value를 계산하면 계산량이 많이 줄일 수 있습니다. Correlation이 큰 Feature들은 묶어서 하나의 SHAP Value를 계산하도록 하는 것도 좋습니다. Hierarchical Clustering Tree, Owen Value, Partition Explainer를 사용해서 여러 Feature를 묶어서 SHAP Value를 계산하는 것도 좋습니다.

참고로 여기서 설명한 SHAP Value를 계산하는 방법에 대한 각종 설명은 Model Agnostic한 경우에(Model의 구조에 의존하지 않는 경우에) 해당합니다. 만약에 Model Agnostic할 필요가 없다면 Model의 구조에 의존해서 더 효과적으로 SHAP Value를 계산할 수도 있습니다. 사용하는 Model의 구조를 살펴보고 효과적인 SHAP Value를 계산하는 방법이 존재한다면 그 방법을 사용하는 것이 더 효과적일 수 있습니다.

Conclusion

이 글에서는 SHAP의 기본적인 원리와 어떻게 계산할 수 있는지 알아보았습니다. 이해를 최대한 돕기 위해 너무 추상적으로 설명하는 것을 피하면서 최대한 이해하기 쉬운 문제를 가지고 구체적인 계산을 통해 설명하기 위해 노력하였습니다. SHAP이 잘 이해가 되지 않아서 활용을 잘 못 하셨던 분들에게 조금이라도 도움이 되었으면 좋겠습니다.