树模型可解释性:特征重要性与 SHAP
一句话定义
模型可解释性回答「模型为什么这样预测」:不纯度重要性与置换重要性给出全局特征排序,SHAP 基于博弈论 Shapley 值把单次预测分解为各特征的加性贡献 f(x) = φ0 + ∑i φi。
为什么重要
高风险场景(信贷、医疗、招聘)里「准确」不够,还要「能对监管和用户解释」;排障时知道模型依赖哪些特征才能发现泄漏与捷径学习。树集成的可解释性指标种类多、陷阱也多——用错指标会得出「模型在用 ID 泄漏」却毫不知情的结论。
前置知识
决策树:信息增益、增益率与基尼指数 的分裂与不纯度、随机森林与 Bagging/梯度提升树 GBDT 与 XGBoost 的树集成;特征选择:过滤、包裹与嵌入方法 的特征筛选视角可对照。
核心概念
- 不纯度重要性(MDI):训练期所有节点上该特征带来的不纯度下降之和(树内置,快但偏)。
- 置换重要性:打乱某特征列后模型性能下降多少(模型无关,需在测试集上算)。
- Shapley 值:合作博弈中把总收益公平分给玩家的唯一满足若干公理的分配。
- SHAP:Shapley values 应用到特征归因,φi 为正值推高预测、负值拉低。
- 局部 vs 全局解释:单样本归因(为什么这个人被拒)与整体分布(哪些特征总体最重要)两个层次。
直观类比
球赛后分功劳:Shapley 值的思想是「把每个球员在所有可能出场组合中带来的边际胜利平均」——主力跟弱队同场时贡献大、跟全主力同场时边际小,平均才是公平功劳。特征就是球员,预测值就是胜利,SHAP 把这次预测按这个原则分给各特征。
原理与机制
不纯度重要性的系统性偏差:高基数特征(连续值、ID、随机数)在树里候选切分点多,总能「碰」出几个纯度提升的分裂,MDI 虚高——甚至在完全随机的特征上也算出可观重要性。置换重要性修正了这一点:在留出数据上测「破坏这个特征的信息后性能掉多少」,模型无关、可比;但它对相关特征会低估(打乱一个,另一个仍携带类似信息),且打乱引入不现实的样本。
SHAP 的定义与计算:特征 i 的 Shapley 值
f(S) 表示「只知道特征子集 S 时模型的期望输出」。精确计算是特征数指数级,实践靠 TreeSHAP:利用树结构把树内精确 Shapley 计算降为多项式时间,使大规模树集成的逐样本解释可行。SHAP 满足效率性(∑ φi = f(x) - 𝔼[f])、对称性、哑性与可加性,因此各特征贡献可直接相加还原预测。
公式与推导
效率性公理给出加性分解(归因的「守恒定律」):
推导直觉:把特征一个一个「告知」模型,按所有告知顺序平均每步的边际贡献(恰为上式 Shapley 求和的组合含义),起点是基准 φ0、终点是本次预测——总和守恒。线性模型上 SHAP 退化为 φi = wi(xi - 𝔼[xi]),可作正确性自检。
图示
f(x) = 0.32 对「违约」的 SHAP 分解(瀑布式)
基准 E[f] │────────│ 0.10
负债率 ██████ │ │ +0.15 推高
近期逾期 ████ │ │ +0.09 推高
年龄 ░░░░ │ │ −0.05 拉低
收入 ░░░░░░ │ │ −0.04 拉低
其他 ░░ │ │ +0.07
最终预测 │────────│ 0.32 (守恒:0.10+0.22=0.32)实例或案例
置换重要性暴露不纯度重要性的虚高:
from sklearn.datasets import make_classification
from sklearn.ensemble import RandomForestClassifier
from sklearn.inspection import permutation_importance
from sklearn.model_selection import train_test_split
import numpy as np
X, y = make_classification(n_samples=800, n_features=8, n_informative=4, random_state=0)
rng = np.random.default_rng(1)
X = np.column_stack([X, rng.normal(size=len(X))]) # 追加一个纯噪声特征
X_tr, X_te, y_tr, y_te = train_test_split(X, y, random_state=0)
rf = RandomForestClassifier(n_estimators=200, random_state=0).fit(X_tr, y_tr)
print("MDI (噪声列):", rf.feature_importances_[-1].round(3))
r = permutation_importance(rf, X_te, y_te, n_repeats=20, random_state=0)
print("置换 (噪声列):", r.importances_mean[-1].round(3)) # 应接近 0噪声列的 MDI 常有 0.02~0.05 的虚假值,置换重要性则贴近 0——报告特征排序时应以后者为准。
常见误区
- 在训练集上算置换重要性:训练集上模型可能靠过拟合利用特征,置换后掉分被高估;必须用留出/测试数据。
- 把重要性当因果效应:重要性只说明「模型用了它」,特征间相关时归因会在相关组内分摊,不能推出干预效果。
- 忽略解释的分布:只看平均 SHAP 会漏掉「某特征只对少数样本起反向作用」的交互结构,配 summary 图看散布。
与其他知识点的关系
决策树:信息增益、增益率与基尼指数 的高基数偏袒是 MDI 偏差的机制根源;特征选择:过滤、包裹与嵌入方法 的特征选择可借 SHAP/置换重要性做嵌入后筛选;公平性、可复现性与机器学习伦理 的公平性审计常用 SHAP 检查敏感属性是否被代理变量间接使用。
自测题
- MDI 与置换重要性的核心区别?
- 要点:MDI 训练期不纯度下降、偏向高基数且无法发现过拟合利用;置换在留出数据上做扰动实验、模型无关。
- SHAP 的效率性公理说了什么,为什么重要?
- 要点:∑φi + φ0 = f(x),归因守恒;保证各特征贡献可加总、解释不自相矛盾。
- 为什么相关特征会让置换重要性偏低估?
- 要点:打乱 xi 后与它相关的 xj 仍提供相似信息,模型性能掉得少 → 表面不重要;解读时按相关组看。
延伸阅读
Lundberg & Lee, A Unified Approach to Interpreting Model Predictions(NeurIPS, 2017);Molnar《Interpretable Machine Learning》第 9 章(Shapley)。