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与置换的博弈
随机森林提供了两种特征重要性度量方式:
- 基于不纯度减少(MDI): 与单棵树类似,但取所有树的平均值。
- 基于排列重要性(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流程图可以帮助你在实际项目中快速决策应该使用哪种方法。
4.7 综合避坑清单
最后,我们总结一份基于模型特征选择的避坑清单,供你在实际项目中逐条核对。
- 坑1: 直接使用单棵决策树的特征重要性。→ 解决: 使用集成模型(RF/XGBoost)或排列重要性。
- 坑2: Lasso在共线性下随机选择特征。→ 解决: 先进行相关性分析,或使用弹性网络(Elastic Net)。
- 坑3: 混淆XGBoost的Frequency和Gain。→ 解决: 显式指定
importance_type='gain'。 - 坑4: 只依赖一种重要性指标。→ 解决: 同时使用MDI和MDA,并对比结果。
- 坑5: 忽略特征重要性背后的业务含义。→ 解决: 将模型输出的重要性排名与领域专家知识进行交叉验证。
核心原则: 基于模型的特征选择是强大的自动化工具,但它不是万能的。最终的特征子集必须经过业务逻辑的检验和模型性能的验证。记住,模型告诉你的是“统计上的重要性”,而不是“因果上的重要性”。