SHAP对机器学习模型进行解释性分析
什么是SHAP?
Shapley 值:源自博弈论,衡量每个特征对模型输出的边际贡献,满足公平性理论属性(效率性、对称性、空玩家、加性)。
SHAP:统一了多种解释方法,能够提供全局(global)和局部(local)两种视角的可解释性。
shap值的计算公式:
如何使用SHAP?
本文以python的shap库做说明
pip install shap
SHAP不同的解释器
Explainer | 模型类型 | 精度 | 速度 | 通用性 |
---|---|---|---|---|
TreeExplainer | 树模型 | 高(精确) | 快 | 低 |
KernelExplainer | 任意黑盒 | 中(近似) | 慢 | 高 |
DeepExplainer | 常见神经网络 | 高(近似) | 较快 | 中 |
GradientExplainer | 可导深度模型 | 高(近似) | 非常快 | 中 |
LinearExplainer | 线性模型 | 精确 | 非常快 | 低 |
PartitionExplainer | 任意黑盒(特征少时最佳) | 中高 | 中 | 中 |
选择时,优先考虑模型类型与数据规模,再权衡速度与精度。若有专用 Explainer(如树模型用TreeExplainer、线性模型用 LinearExplainer、深度模型用 DeepExplainer/GradientExplainer),则尽量使用;否则可用 Partition 或 Kernel。
基本流程
准备背景数据
用于估计特征基线影响,通常选取训练集的一个子集:
import shap
background = X_train.sample(100, random_state=0)
创建 Explainer
# 以 TreeExplainer 为例
explainer = shap.TreeExplainer(model, data=background)
计算 Shapley 值
# 对测试集前 50 条进行解释
shap_values = explainer.shap_values(X_test.iloc[:50])
可视化
全局重要性:
特征越靠上,说明对模型影响越大。
如果点分布在右侧(正值),说明该特征值对输出有正向推动作用;左侧(负值)则是抑制作用。
颜色趋势可以看出:红色点(特征值高)分布在右侧,说明该特征值高时更倾向推高预测结果;如果红色在左,则反之。
shap.summary_plot(shap_values, X_test.iloc[:50])
特征依赖图:
主效应:横纵轴趋势告诉你,这个特征取值如何影响其 SHAP 值(模型输出)。
非线性:如果曲线不是直线,说明特征与输出关系有非线性(例如凸、凹、拐点)。
交互效应:点的颜色随另一特征变化,能看出当该交互特征高低时,对 SHAP 值的影响如何不同。
shap.dependence_plot("特征名", shap_values, X_test.iloc[:50])
单点解释(局部):
用于单个样本的局部解释,直观展示每个特征是如何一步步把预测值从基线推到最终值的。
条的长度反映贡献大小:越长说明该特征对单个预测的影响越显著。
颜色与方向(推高/拉低)结合,帮助快速判断哪几个特征最关键。
shap.force_plot(
explainer.expected_value,
shap_values[0],
X_test.iloc[0]
)
综合示例
import shap
from sklearn.ensemble import RandomForestClassifier
from sklearn.datasets import load_breast_cancer
from sklearn.model_selection import train_test_split
# 1. 加载数据并拆分
data = load_breast_cancer(as_frame=True)
X, y = data.data, data.target
X_train, X_test, y_train, y_test = train_test_split(X, y,
test_size=0.3,
random_state=42)
# 2. 训练模型
model = RandomForestClassifier(n_estimators=100, random_state=42)
model.fit(X_train, y_train)
# 3. 选取背景数据并创建解释器
background = X_train.sample(200, random_state=42)
explainer = shap.TreeExplainer(model, data=background)
# 4. 计算并可视化 SHAP 值
shap_values = explainer.shap_values(X_test)
shap.summary_plot(shap_values[1], X_test) # 类别 1 的全局重要性
shap.dependence_plot("mean radius", shap_values[1], X_test)
shap.force_plot(explainer.expected_value[1],
shap_values[1][0],
X_test.iloc[0], matplotlib=True)