分类模型的 SHAP 值归因分析
一、直观理解:把一次预测的“功劳”公平分给各个特征
模型给出“该客户违约概率 0.82”,业务要问:是负债率太高,还是近期待还款过多?SHAP(SHapley Additive exPlanations)借用合作博弈论中的 Shapley 值:把特征当作玩家,把预测相对基线的变化当作联盟收益,按“边际贡献的加权平均”给每个特征打分。
对单次预测:
- :基线(通常是训练集预测均值);
- :特征 把预测从基线推高或推低了多少。
全局解释则汇总许多样本的 或画蜂群图。SHAP 满足局部准确性、缺失性、一致性等理想性质,是当前表格模型解释的主流工具之一。
二、适用场景与优缺点
| 类型 | 说明 |
|---|---|
| 适用场景 | 黑箱/集成模型上线或写论文需要解释;要同时做局部(个案)与全局(特征排序)说明;对比不同模型的驱动因素;检查模型是否用了“泄漏特征”。 |
| 核心优点 | 有公理化基础;加性分解清晰;TreeSHAP 对树模型高效一致;可视化体系成熟。 |
| 局限与缺点 | 相关特征时归因会分摊、解读需谨慎;计算对模型无关法可能很慢;解释的是模型而非世界因果;实现依赖工具版本。 |
使用前:固定训练好的模型与背景数据;明确解释的是对数几率还是概率;相关特征成组解读。
三、核心原理
1. Shapley 值
特征集合 ,模型对特征子集 的预测期望为 。特征 的 Shapley 值:
即:在所有加入顺序下,特征 带来的平均边际贡献。
2. 与模型结合
- KernelSHAP:模型无关,加权回归近似,较慢;
- TreeSHAP:针对树/森林/GBDT 的多项式时间精确算法;
- 线性模型:SHAP 与“系数 × 特征偏离”密切相关。
3. 依赖与相关
若特征相关,边缘期望与条件期望两种路径会导致不同归因哲学(interventional vs conditional)。论文中应说明工具默认行为,避免把相关特征的 SHAP 读成独立因果效应。
四、关键决策
| 决策点 | 建议 |
|---|---|
| 背景集 | 从训练集抽样 50–200 点作期望基线 |
| 解释尺度 | 树模型常在 log-odds;展示时说明 |
| 全局图 | mean( |
| 局部图 | waterfall / force plot 讲个案 |
| 相关特征 | 合并讨论或分层分析 |
| 工具 | MATLAB 可手写线性 SHAP;复杂树模型可导出到 Python shap |
五、MATLAB 示例
下面给出线性模型闭式 SHAP 风格分解(标准化特征下,, 为截距/均值项),以及树模型的排列重要性对照。完整 TreeSHAP 可在外部用 Python 计算后读回表格。
% ---- 1) 线性 Logistic / 线性得分的加性归因 ----
X = [
25 4.5 0.45;
40 9.0 0.20;
33 6.2 0.38;
50 12.0 0.15;
29 5.0 0.50;
45 10.5 0.22
];
y = [1;0;1;0;1;0];
names = ["年龄","收入","负债率"];
[Xz, mu, sig] = zscore(X);
mdl = fitclinear(Xz, y, "Learner", "logistic", ...
"Regularization", "ridge", "Lambda", 1e-2, "Solver", "lbfgs");
beta = mdl.Beta; % p x 1
b0 = mdl.Bias; % 截距
% 对样本 i: f = b0 + sum beta_j * Xz_ij
% 线性模型在独立特征假设下的 Shapley 即各维贡献
i = 1;
phi0 = b0;
phi = beta .* Xz(i, :)';
f = phi0 + sum(phi);
fprintf("样本 %d 的模型得分 f=%.4f\n", i, f);
fprintf("基线 phi0=%.4f\n", phi0);
for j = 1:numel(names)
fprintf(" %s: phi=%.4f (标准化值=%.3f)\n", names(j), phi(j), Xz(i,j));
end
% 可视化单样本归因
figure;
barh(phi);
set(gca, "YTickLabel", names);
xlabel("SHAP 风格贡献(线性)");
title("个案特征贡献");
% ---- 2) 树模型:用排列重要性做全局解释对照 ----
rf = TreeBagger(80, X, y, "Method", "classification", ...
"OOBPredictorImportance", "on", "MinLeafSize", 1);
imp = rf.OOBPermutedPredictorDeltaError;
figure; bar(imp);
set(gca, "XTickLabel", names);
ylabel("OOB 排列重要性");
title("随机森林全局重要性(非 SHAP,可作对照)");
% ---- 3) 若已用 Python shap 导出 csv ----
% T = readtable("shap_values.csv");
% meanAbs = mean(abs(T{:,:}), 1);
% bar(meanAbs); set(gca,"XTickLabel", T.Properties.VariableNames);
Python 侧(可选,供赛题复现)示意:
# import shap, sklearn
# explainer = shap.TreeExplainer(model)
# shap_values = explainer.shap_values(X)
# shap.summary_plot(shap_values, X)
六、如何解释结果
- 个案:哪些特征把预测推离基线,方向是否符合业务;
- 全局排序:mean(|SHAP|) 高的特征是模型主要依赖;
- 依赖图:SHAP 随特征值变化是否单调、是否有阈值效应;
- 异常归因:若某无业务意义的变量 SHAP 很高,检查泄漏;
- 报告:模型类型、背景数据、解释尺度、Top 特征、1–2 个典型案例瀑布说明。
七、常见误区
1. 把 SHAP 当成因果效应
它解释模型计算,不自动等于干预世界后的结果。
2. 相关特征上过度解读“唯一功臣”
共线时贡献会拆分或不稳定。
3. 背景集用测试集或含未来信息
解释基线应来自合理的参照分布。
4. 只给全局条形图,不给个案
分类题常需要“为什么这个人被判高风险”。
5. 不同模型的 SHAP 绝对值横比
尺度与基线不同,不宜直接比大小跨模型硬刚,应比排序与方向。
八、小结
SHAP 用 Shapley 值把单次预测分解为各特征的加性贡献,是连接黑箱分类器与论文叙事、业务沟通的标准桥梁。
好的可解释性流程是:先有准确且验证过的模型,再用 SHAP 做全局与局部归因,并明确“解释模型 ≠ 证明因果”。线性模型可闭式分解,树模型优先 TreeSHAP,必要时 MATLAB 与 Python 分工协作。