4. 基于模型的特征选择:树模型特征重要性、L1正则化(Lasso)、随机森林特征重要性、XGBoost特征重要性

基于模型的特征选择是工业界最常用的筛选方法之一。它利用模型训练过程中对特征的“关注程度”或“惩罚机制”来评估特征的重要性,从而避免人工经验带来的主观偏差。本章将深入剖析四种主流方法:树模型特征重要性、L1正则化(Lasso)、随机森林特征重要性以及XGBoost特征重要性,并指出每个方法在实际应用中的常见陷阱。

4.1 四种方法的核心原理对比

在开始具体讲解之前,我们先通过一张表格快速建立对这四种方法的宏观认知。它们虽然都服务于“特征筛选”,但背后的数学逻辑和适用场景截然不同。

方法 核心原理 输出形式 主要陷阱
树模型特征重要性 基于节点分裂时的不纯度(Gini/熵)减少量 归一化重要性分数 偏向连续型或高基数特征
L1正则化(Lasso) 在损失函数中加入L1惩罚项,迫使部分系数变为0 稀疏系数向量 特征间高度相关时,随机丢弃特征
随机森林特征重要性 袋外数据(OOB)置换测试 + 平均不纯度减少 重要性排序与分数 对类别不平衡敏感
XGBoost特征重要性 基于增益(Gain)、覆盖度(Cover)、频率(Frequency) 多种重要性指标 默认“增益”指标可能被高深度树误导
避坑提示: 不要盲目相信单一的重要性指标。例如,Lasso在多重共线性下会随机选择保留哪个特征,而树模型对数值型特征的偏好可能导致离散型强特征被低估。建议至少使用两种方法交叉验证。

4.2 树模型特征重要性:不纯度减少的陷阱

决策树及其集成模型在分裂节点时,会计算分裂前后不纯度(如基尼系数或信息熵)的减少量。这个减少量被累积到对应的特征上,最终归一化后即为特征重要性。

核心公式(基尼重要性):

Importance(feature_i) = Σ (所有使用 feature_i 分裂的节点上的样本加权基尼减少量)

常见陷阱:

  • 偏向高基数特征: 连续型特征或取值极多的离散特征,更容易找到“看似优秀”的分裂点,从而获得更高的不纯度减少量,即使该特征与目标变量无关。
  • 掩盖弱相关特征: 当存在一个强特征时,其他弱相关特征可能几乎没有机会被选中分裂,导致其重要性被低估为0。
实战避坑: 在使用单棵决策树或浅层树模型进行特征选择时,务必对连续特征进行分箱或使用基于排列的重要性(Permutation Importance)进行交叉验证。

4.3 L1正则化(Lasso):稀疏性与共线性危机

Lasso通过在损失函数中添加L1范数惩罚,使得模型在优化过程中将不重要的特征系数压缩至0,从而实现自动特征选择。

数学表达:

L(β) = MSE(β) + λ * Σ|β_i|

其中 λ 是正则化强度。λ 越大,被压缩为0的系数越多。

核心优势与陷阱:

  • 优势: 直接输出稀疏模型,解释性强,适合高维数据。
  • 陷阱1——共线性随机选择: 当两个特征高度相关时,Lasso会随机选择其中一个保留,另一个系数置0。这意味着两次运行可能选出不同的特征子集。
  • 陷阱2——λ选择敏感: 如果λ过大,会误删重要特征;λ过小,则无法有效稀疏化。通常需要结合交叉验证选择最优λ。
解决方案: 对于高度相关的特征组,可以先进行聚类或使用组Lasso(Group Lasso)来避免随机选择问题。同时,建议使用交叉验证后的 lasso_path 观察系数随 λ 的变化轨迹。

4.4 随机森林特征重要性:OOB与置换的博弈

随机森林提供了两种特征重要性度量方式:

  1. 基于不纯度减少(MDI): 与单棵树类似,但取所有树的平均值。
  2. 基于排列重要性(MDA): 通过打乱某个特征的值,观察模型在OOB数据上的预测误差增加量。增加越多,特征越重要。

两种方式的对比:

指标 计算方式 优点 缺点
MDI(不纯度) 基于训练集分裂增益 计算快,无需额外数据 偏向高基数特征,可能过拟合
MDA(排列) 基于OOB预测误差变化 更稳健,能检测特征交互 计算量大,特征间相关时可能失真
避坑指南: 当特征间存在强相关性时,排列重要性(MDA)可能会给出负值,这并不意味着该特征有害,而是因为打乱该特征后,模型可以用其他相关特征进行补偿。此时应结合业务逻辑判断。

4.5 XGBoost特征重要性:增益、覆盖与频率的选择

XGBoost提供了三种内置的特征重要性类型,理解它们的差异是正确筛选特征的前提。

  • Gain(增益): 特征被用于分裂时带来的平均信息增益。这是最常用的指标,但容易被深度较大的树中分裂次数少的特征拉高均值。
  • Cover(覆盖度): 特征被用于分裂时,覆盖的样本数量(即经过该节点的样本数)的相对比例。它反映了特征的“广度”。
  • Frequency(频率): 特征被用于分裂的次数。这个指标最粗糙,容易偏向于在浅层频繁分裂的特征。

如何选择?

# 在XGBoost中获取不同重要性
import xgboost as xgb

model = xgb.XGBClassifier()
model.fit(X_train, y_train)

# 获取增益重要性(默认)
importance_gain = model.feature_importances_  # 默认type='weight',注意这里weight实际是frequency

# 明确指定类型
importance_gain = model.get_booster().get_score(importance_type='gain')
importance_cover = model.get_booster().get_score(importance_type='cover')
importance_freq = model.get_booster().get_score(importance_type='weight')  # weight即frequency
重要提醒: XGBoost的默认 feature_importances_ 属性返回的是 Frequency(频率),而不是Gain。很多初学者误以为默认是Gain,导致筛选出的特征偏向于“被频繁使用”而非“真正重要”。建议始终使用 get_score(importance_type='gain') 进行特征选择。

4.6 四种方法的选择决策流程

下面这张SVG流程图可以帮助你在实际项目中快速决策应该使用哪种方法。

基于模型的特征选择方法决策流程 开始特征选择 数据维度 > 样本量? 是(高维稀疏) 否(低维稠密) L1正则化(Lasso) 树模型/集成模型 检查共线性 → 使用组Lasso 选择重要性类型(Gain优先) 交叉验证 + 业务规则验证 输出最终特征子集

4.7 综合避坑清单

最后,我们总结一份基于模型特征选择的避坑清单,供你在实际项目中逐条核对。

  • 坑1: 直接使用单棵决策树的特征重要性。→ 解决: 使用集成模型(RF/XGBoost)或排列重要性。
  • 坑2: Lasso在共线性下随机选择特征。→ 解决: 先进行相关性分析,或使用弹性网络(Elastic Net)。
  • 坑3: 混淆XGBoost的Frequency和Gain。→ 解决: 显式指定 importance_type='gain'。
  • 坑4: 只依赖一种重要性指标。→ 解决: 同时使用MDI和MDA,并对比结果。
  • 坑5: 忽略特征重要性背后的业务含义。→ 解决: 将模型输出的重要性排名与领域专家知识进行交叉验证。
核心原则: 基于模型的特征选择是强大的自动化工具,但它不是万能的。最终的特征子集必须经过业务逻辑的检验和模型性能的验证。记住,模型告诉你的是“统计上的重要性”,而不是“因果上的重要性”。