SHAP解释模型
1 简介
近年来,模型的可解释性越来越受到重视,SHAP 是一个 Python 工具包,它可以解析任何模型的输出。本文除了介绍 SHAP 的基本用法之外,还示例了新版本提供的一些高级用法,进一步提升了预测的归因效果以及分组分析。
2 环境配置:
以下实验使用当前最新版本 shap:0.39.0
1 | pip install shap |
注意 xgboost 也需要使用对应的较新版本,如:
1 | pip install xgboost==0.82 |
为使用交互界面,notebook 环境下,加载用于可视化的 JS 代码
1 | import shap |
3 实验数据
1 | import shap |
4 实验
4.1.1 实验一
SHAP 的可解释性,基于对每一个训练数据的解析。比如:解析第一个实例每个特征对最终预测结果的贡献。
1 | shap.plots.force(shap_values[0]) |
图中,红色特征使预测值更大(类似正相关),蓝色使预测值变小,而颜色区域宽度越大,说明该特征的影响越大。(此处图中数字是特征的具体数值) 其中 base_value 是所有样本的平均预测值,output_value 即 f(x) 是本实例的预测值。本例分析了回归问题,对于分类问题,可以看到 base_value 和 output_value 并不在 0-1 之间,这是由于对数转换造成的。
4.1.2 实验二
进而可以画出每个特征对结果影响程度的具体大小(此处图中数字是特征权重)
1 | shap.plots.waterfall(shap_values[0]) |
4.1.3 实验三
以上都是对于单个实例的解释,更多的时候我们看到的是这种图:
1 | shap.plots.beeswarm(shap_values)![] |
它对所有实例作图,相当于把图一上的每个特征旋转 90 度画成点图。这样可以看到特征对预测影响的大小,需要注意的是:这里的横坐标是 shap-value,即影响的权重,而非特征的具体值,特征值大小对结果的影响通过颜色表示(红色为值大,蓝色为值小,紫色邻近均值)。因此,区域分布越宽说明它的影响力越大,这个图一般是上宽下窄(影响大的放在上面)。 图中最后一行显示了 Sum of other features,如果不需要显示这一行,可使用函数做图:
1 | shap.summary_plot(shap_values, test, max_display=5) |
4.1.4 实验四
以上只是罗列结果,并未进行统计处理,而对模型产生最大影响的前 N 的特征,一般是通过各个特征绝对值的均值(abs()->mean())得到的,使用绝对值解决了正负抵消的问题,更关注相关性的大小。 从这个图中就没办法看出是正相关还是负相关了,但使用 shap 工具可以得到具体的 shap value,可以自行处理。
1 | shap.plots.bar(shap_values) |
4.1.5 实验五
此处可引申出 SHAP 更多的用法,尤其对于研究和归因,比如研究模型对“老年男性”或者“入院第五天”人群的特征重要性。做柱图的 bar 函数支持 cohort 参数,通过传入 list(与实例个数相等),来划分人群(当前版本 0.39.0 支持 cohort 分群逻辑)。
1 | import numpy as np |
4.1.6 实验六
上述 bar 画出的是统计图,有时还是想在图中看出特征是正相关还是负相关,使用 force 函数可将多个实例的特征贡献度画在一张图上。
1 | shap.plots.force(explainer.expected_value, shap_values.values[:10]) |
force() 工具非常灵活,横纵坐标都可以选择,每个横坐标对应一个实例,可选择:按输出排序,按实例顺序排序,按近似实例排序;纵向可以选择查看哪些特征,默认是查看所有特征。通过转入不同的 shap value 数组,可以研究部分或全部实例。
5 保存图片
静态图可通过 plt.savefig 保存 (只支持单实例),注意设置 matplot 和 show 参数:
1 | shap.force_plot(explainer.expected_value[0], shap_values[0], data_arry, matplotlib=True,show=False) |
动态图只能保存成 html,具体使用:
1 | xx = shap.force_plot(....) |