4.4 特征重要性与模型可读性 特征重要性有 gain、weight、cover 三种口径,结论可能互相打架;它只回答"模型用了谁",不回答"用得对不对"。 本节对比三种口径的排序差异,演示一次数据泄漏如何在重要性上现形,并预告 SHAP 将在第 5 章补上"方向与个体"的缺口。 模型选好了,业务方抛来第一个问题:"它凭什么判断这个客户会流失?"本节两个知识点:三种重要性口径的算法与差异、重要性诊断如何抓出数据泄漏。 一、三种口径,三张排行榜 XGBoost 的 plotimportance 默认按 weight(该特征被用作分裂节点的次数)排序,另有 gain(该特征带来的总增益)与 cover(分裂时覆盖的样本二阶导数总和)。
特征重要性有 gain、weight、cover 三种口径,结论可能互相打架;它只回答"模型用了谁",不回答"用得对不对"。 本节对比三种口径的排序差异,演示一次数据泄漏如何在重要性上现形,并预告 SHAP 将在第 5 章补上"方向与个体"的缺口。
模型选好了,业务方抛来第一个问题:"它凭什么判断这个客户会流失?"本节两个知识点:三种重要性口径的算法与差异、重要性诊断如何抓出数据泄漏。
XGBoost 的 plot_importance 默认按 weight(该特征被用作分裂节点的次数)排序,另有 gain(该特征带来的总增益)与 cover(分裂时覆盖的样本二阶导数总和)。三种口径各说各话:
import matplotlib matplotlib.use('Agg') from xgboost import plot_importance import xgboost as xgb booster = clf.get_booster() for imp in ('weight', 'gain', 'cover'): scores = booster.get_score(importance_type=imp) top = sorted(scores.items(), key=lambda kv: -kv[1])[:3] print(f"{imp:6s} 口径前三:", [(k, round(v,1)) for k, v in top]) # 运行输出: # weight 口径前三: [('tenure', 148), ('monthly_fee', 103), ('age', 61)] # gain 口径前三: [('tenure', 2411.9), ('contract_month', 886.3), ('monthly_fee', 712.5)] # cover 口径前三: [('monthly_fee', 48210.0), ('tenure', 43996.0), ('age', 23117.0)]
同一个模型:weight 说月费第二,gain 说 one-hot 出来的 contract_month 第二,cover 又把月费抬回第一。分歧的根源是口径问题——一个频繁分裂但每次只带来微小改善的特征(weight 高、gain 低)与一个只分裂几次但刀刀见血的特征(weight 低、gain 高),谁更重要取决于你问的是什么。汇报用 gain 更贴近预测贡献,排查用 weight 更容易发现被反复试探的低效特征。
构造一个带泄漏特征的版本:把"本月的挽留优惠券使用记录"混入特征——现实中只有决定流失的客户才会收到优惠券,这个特征在训练时几乎等于标签的影子:
X_leak = X_tr_enc.copy() X_leak['coupon_used'] = (y_tr.values * (rng.random(len(y_tr)) < 0.85) + (1-y_tr.values) * (rng.random(len(y_tr)) < 0.02)) leak_clf = xgb.XGBClassifier(n_estimators=200, max_depth=4, eval_metric='logloss') leak_clf.fit(X_leak, y_tr) scores = leak_clf.get_booster().get_score(importance_type='gain') for k, v in sorted(scores.items(), key=lambda kv: -kv[1])[:3]: print(f"{k}: {v:.1f}") # 运行输出: # coupon_used: 9063.4 # tenure: 1436.2 # monthly_fee: 560.8
coupon_used 的 gain 是正常特征头名的六倍以上,模型几乎躺在这个特征上。上线后这个特征要么不存在、要么语义完全不同(优惠券成了结果而非先兆),线上效果必然崩塌。重要性排行榜的第一功能不是解释模型,而是审计特征:任何一个重要性异常突出的特征,都要回答"它在预测时点真的拿得到吗"。

gain 类重要性只给"总量",不给"方向"——不知道 tenure 增大时流失概率升还是降;也不给"个体"——无法回答"这位客户"的预测由什么构成。树模型里特征间存在大量交互,同一个特征对不同样本的作用方向可以相反,全局重要性对此完全沉默。补齐这两个维度的工具是 SHAP,第 5.3 节将展开;此处先留一个判断:重要性是审计工具,解释工具要等 SHAP。
💡 关键直觉:把重要性榜单当成"体检报告的异常指标"来读。它最值得信任的用法不是向业务解释模型多聪明,而是暴露模型正在偷懒依赖哪个特征——泄漏、代理变量、口径错误,多半在这一步现形。
模型可信了,最后一站是让它离开实验环境:保存、加载、以什么形态服务线上请求。
先别删。低 gain 可能因为它的信息被更强特征覆盖(相关特征分账),删掉后强特征的缺失它补不上。正确做法做一次消融实验:删掉后验证分数掉多少,掉得少才考虑删除;也可以把它与新构造的交互特征合并,帮模型用更少的分裂吃到同一份信息。
会,而且这本身就是监控信号。第 6.2 节的推荐场景里,头部特征每周重排是常态;若某个特征的重要性突然塌到零,多半是上游特征生产断了——重要性榜单因此值得纳入线上监控看板,与分数分布监控互为补充。