本篇博客介绍另一种事后可解释性方法:SHAP(SHapley Additive exPlanation)方法。

1. Shapley值理论

  Shapley值是博弈论中的一个概念,通过衡量联盟中各成员对联盟总目标的贡献程度,从而根据贡献程度来进行联盟成员的利益分配,避免了分配的平均主义。
  当Shapley理论用于解释机器学习模型的时候,将输入特征 x x x视为参与成员,模型输出的概率分布 f ( x ) f(x) f(x)视为联盟总目标,通过衡量各特征的贡献度来挖掘重要特征,从而提供可解释性判断依据。其数学模型如下: g ( Z ′ ) = φ 0 + ∑ j = 1 M φ j Z j ′ ≈ f ( x ) (1) g(Z^{'})=\varphi_{0}+\sum_{j=1}^{M}\varphi_{j}Z^{'}_{j}\approx f(x) \tag{1} g(Z)=φ0+j=1MφjZjf(x)(1)其中, g g g是解释模型, f ( x ) f(x) f(x)是原机器学习模型, Z j ′ = { 0 , 1 } M Z^{'}_{j}=\{0,1\}^{M} Zj={0,1}M表示相应特征是否被观察到, M M M是输入特征的数目, φ i \varphi_{i} φi是每个特征的归因值, φ 0 \varphi_{0} φ0是解释模型的常数。
  对于一个特定的输入数据 x 0 x_{0} x0,其Shapley值的计算公式如下: φ i ( f , x 0 ) = ∑ S ⊆ N S / { i } ∣ S ∣ ! ( M − ∣ S ∣ − 1 ) ! ∣ N S ∣ ! [ f ( S ∪ { i } ) − f ( S ) ] (2) \varphi_{i}(f,x_{0})=\sum_{S\subseteq N_{S}/ \{i\}}\frac{|S|!(M-|S|-1)!}{|N_{S}|!}[f(S\cup\{i\})-f(S)]\tag{2} φi(f,x0)=SNS/{i}NS!S!(MS1)![f(S{i})f(S)](2)其中, φ i ( f ) \varphi_{i}(f) φi(f)代表函数 f f f中特征 i i i的贡献度, N S N_{S} NS是所有特征组成的集合, S S S代表特征子集, N S / { i } N_{S}/\{i\} NS/{i}代表在集合 N S N_{S} NS中去除特征 i i i S ∪ { i } S\cup \{i\} S{i}表示子集 S S S中增加特征 i i i ∣ S ∣ |S| S表示集合 S S S中元素的个数。
  为了方面公式(2)的计算,通常将公式(2)转化为如下公式计算: φ i ( f , x 0 ) = ∑ z ′ ∈ { 0 , 1 } M ∣ z ′ ∣ ! ( M − ∣ z ′ ∣ − 1 ) ! M ! [ f S ( z ′ ) − f S ( z ′ ∣ i ) ] (3) \varphi_{i}(f,x_{0})=\sum_{z^{'}\in\{0,1\}^{M}}\frac{|z^{'}|!(M-|z^{'}|-1)!}{M!}[f_{S}(z^{'})-f_{S}(z^{'}|i)]\tag{3} φi(f,x0)=z{0,1}MM!z!(Mz1)![fS(z)fS(zi)](3)其中, f S = E [ f ( x ) ∣ z S ′ ] = 1 N ∑ j = 1 N f ( x j ′ ) f_{S}=E[f(x)|z_{S}^{'}]=\frac{1}{N}\sum_{j=1}^{N}f(x_{j}^{'}) fS=E[f(x)zS]=N1j=1Nf(xj)其中, z S ′ z_{S}^{'} zS为集合 S S S中特征的取值所组成的集合, N N N为原函数 f f f训练数据的个数, x j ′ x_{j}^{'} xj的取值如下: x j ′ = { x 0 i , F i ∈ z S ′ x j i , F i ∉ z S ′ x_{j}^{'}=\left\{\begin{aligned} x_{0i},& F_{i}\in z_{S}^{'} \\ x_{ji},&F_{i}\notin z_{S}^{'} \end{aligned}\right. xj={x0i,xji,FizSFi/zS其中, x 0 i x_{0i} x0i为待解释数据 x 0 x_{0} x0的第 i i i个特征值, x j i x_{ji} xji表示第 j j j个训练数据中第 i i i个特征的取值, F i F_{i} Fi表示第 i i i个特征值。
  SHAP值具备扎实的理论基础,但 φ i \varphi_{i} φi的计算复杂度和 E [ f ( x ) ∣ z S ′ ] E[f(x)|z_{S}^{'}] E[f(x)zS]的有效估计是其在实际应用中的最大阻碍,为了解决这个问题,Lundberg等人提出了Tree SHAP方法。
  Tree SHAP是用于树模型(比如,XGBoost, LightGBM, CatBoost等)的快速SHAP值估计方法,大大增加了SHAP值的实际应用能力。

2 SHAP包用法

  这里仍然以Boston房价为例,使用XGBoost方法训练模型。其用法举例如下:
模型训练

import pandas as pd
import numpy as np
from sklearn.datasets import load_boston
from xgboost import XGBRegressor
from sklearn.model_selection import train_test_split
import shap
shap.initjs()
#分类
boston=load_boston()
X=boston.data
y=boston.target
features=boston.feature_names
X_train,X_test,y_train,y_test=train_test_split(X,y,test_size=0.2,random_state=0)

xgbr=XGBRegressor(n_estimators=200,max_depth=4)
xgbr.fit(X_train,y_train)

对单个样本进行解释

explainer=shap.TreeExplainer(xgbr)
shap_values=explainer.shap_values(X_test[1].reshape(1,-1))
shap.force_plot(explainer.expected_value,shap_values,X_test[1].reshape(1,-1),feature_names=features)

其结果如下:
在这里插入图片描述
关于上图,有以下几个方面需要说明:

  • base_value:全体样本Shape平均值,这里的全体样本指的是模型的训练样本;
  • output_value: 当前样本的Shap输出值,即为模型的预测值;
  • 正向作用特征:红色特征即为正向作用的特征;
  • 反向作用特征:蓝色特征即为反向作用的特征;

整个测试集的Shap分布

explainer=shap.TreeExplainer(xgbr)
shap_values=explainer.shap_values(X_test)
shap.force_plot(explainer.expected_value,shap_values,X_test,feature_names=features)

其结果如下(可以通过调节横纵坐标观察单个特征的效果):
在这里插入图片描述
从特征角度观察样本Shap值

shap.summary_plot(shap_values,X_test,feature_names=features)

其结果如下:
在这里插入图片描述

参考文献

Logo

开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!

更多推荐