4. XGBoost 内置特征重要性:三种核心指标的数学定义与业务含义
XGBoost 模型训练完成后,内置的 feature_importances_ 属性提供了三种不同视角的特征重要性度量。理解这三种指标的数学本质与适用场景,是进行特征筛选的第一步,也是避免“误删重要特征”的关键。
4.1 三种重要性指标概览
| 指标名称 | 计算依据 | 默认值 | 核心问题 |
|---|---|---|---|
| weight | 特征被选为分裂点的次数 | 是 | 哪个特征被用得最多? |
| gain | 特征分裂带来的平均信息增益 | 否 | 哪个特征对模型性能提升最大? |
| cover | 特征分裂覆盖的样本数量(加权) | 否 | 哪个特征影响的样本范围最广? |
weight 指标。在大多数业务场景中,gain 比 weight 更能反映特征对预测精度的真实贡献。cover 则用于判断特征的“稳定性”与“泛化范围”。
4.2 数学定义与计算逻辑
4.2.1 weight(分裂次数)
数学定义:
\[ \text{weight}_j = \sum_{t=1}^{T} \sum_{k=1}^{K_t} \mathbb{1}(\text{node}_k \text{ uses feature } j) \]
其中 \(T\) 为树的总数,\(K_t\) 为第 \(t\) 棵树的内部节点数。只要某个内部节点以特征 \(j\) 作为分裂特征,就计数一次。
业务含义:
- 反映特征在树结构中的“出场频率”。
- 容易偏向数值型特征或取值较多的特征,因为这类特征更容易找到分裂点。
- 在特征数量多、噪声大的场景下,
weight可能高估无用特征的重要性。
4.2.2 gain(平均信息增益)
数学定义:
\[ \text{gain}_j = \frac{1}{N_j} \sum_{\text{splits using } j} \left[ \frac{G_L^2}{H_L + \lambda} + \frac{G_R^2}{H_R + \lambda} - \frac{(G_L + G_R)^2}{H_L + H_R + \lambda} \right] - \gamma \]
其中 \(G\) 为一阶梯度之和,\(H\) 为二阶梯度之和,\(\lambda\) 为 L2 正则化项,\(\gamma\) 为分裂惩罚项。\(N_j\) 为特征 \(j\) 被使用的总分裂次数。
业务含义:
- 直接衡量特征分裂对损失函数降低的贡献。
- 是三种指标中与模型精度关联最紧密的指标。
- 推荐作为特征筛选的首选指标。
4.2.3 cover(覆盖样本数)
数学定义:
\[ \text{cover}_j = \frac{1}{N_j} \sum_{\text{splits using } j} (H_L + H_R) \]
其中 \(H_L\) 和 \(H_R\) 分别为分裂后左右子节点的二阶梯度之和。在默认参数下,二阶梯度近似等于样本权重,因此 cover 近似表示特征分裂所覆盖的加权样本数量。
业务含义:
- 反映特征分裂的“影响广度”。
- 高 cover 的特征通常作用于数据中的大多数样本,具有全局性。
- 低 cover 但高 gain 的特征,往往是针对小众但关键的子群体(如异常检测中的少数类特征)。
4.3 三种指标的对比与选择策略
4.4 代码实现:提取三种重要性指标
以下代码展示如何从训练好的 XGBoost 模型中提取三种指标,并构建特征重要性 DataFrame:
import xgboost as xgb
import pandas as pd
# 假设已训练好模型 model
# model = xgb.XGBClassifier().fit(X_train, y_train)
# 提取三种重要性
importance_weight = model.get_booster().get_score(importance_type='weight')
importance_gain = model.get_booster().get_score(importance_type='gain')
importance_cover = model.get_booster().get_score(importance_type='cover')
# 转换为 DataFrame
df_weight = pd.DataFrame(list(importance_weight.items()), columns=['feature', 'weight'])
df_gain = pd.DataFrame(list(importance_gain.items()), columns=['feature', 'gain'])
df_cover = pd.DataFrame(list(importance_cover.items()), columns=['feature', 'cover'])
# 合并
df_importance = df_weight.merge(df_gain, on='feature', how='outer') \
.merge(df_cover, on='feature', how='outer')
df_importance.fillna(0, inplace=True)
# 按 gain 降序排列
df_importance.sort_values('gain', ascending=False, inplace=True)
print(df_importance.head(10))
4.5 业务场景中的指标选择
| 业务场景 | 推荐指标 | 原因 |
|---|---|---|
| 信用评分卡(追求精度) | gain | 直接关联 AUC/KS 提升,筛选出对违约预测贡献最大的特征 |
| 推荐系统(覆盖广泛) | cover | 需要特征能覆盖大多数用户行为,避免只对少数人有效的特征 |
| 工业异常检测(样本不均衡) | gain + cover 联合 | 高 gain 低 cover 的特征可能只对少数异常样本有效,需谨慎保留 |
| 快速基线模型(初筛) | weight | 计算最快,用于快速剔除从未被使用的特征(重要性为 0) |
importance_type 下的数值大小。weight 是整数次数,gain 和 cover 是浮点数平均值,三者量纲不同。正确的做法是:在同一指标内进行特征排序,然后跨指标观察特征排名的变化。
4.6 可视化:三种指标的特征排名对比
通过对比同一特征在不同指标下的排名差异,可以发现特征的“行为模式”:
- 高 gain + 高 cover:全局强特征,应优先保留。
- 高 gain + 低 cover:局部强特征,需结合业务判断是否保留。
- 低 gain + 高 cover:全局弱特征,通常可剔除。
- 高 weight + 低 gain:特征被频繁使用但贡献不大,可能是噪声或冗余特征。
4.7 小结
- weight 是“使用频率”,适合快速初筛,但容易误导。
- gain 是“精度贡献”,特征筛选的首选指标。
- cover 是“影响广度”,辅助判断特征的稳定性和泛化能力。
- 实际项目中,建议同时输出三种指标,通过排名对比和四象限分析,做出更稳健的特征筛选决策。