特征选择基础理论:方法分类与偏差-方差权衡

特征选择是信用评分模型里绕不开的一道坎。我刚开始做评分卡时,图省事直接把所有变量扔进模型,结果训练集上AUC高得离谱,一上线就崩了。后来才明白——特征选不对,模型跑得再快也是白搭。

这一节咱们就掰开揉碎,把特征选择的三大门派讲清楚。顺便聊聊那个总被忽略的“偏差-方差权衡”,它才是决定你模型泛化能力的关键。

特征选择方法分类 特征选择方法 过滤式 (Filter) 包裹式 (Wrapper) 嵌入式 (Embedded) 常用方法 • 方差阈值 (VarianceThreshold) • 卡方检验 (Chi-Square) • 互信息 (Mutual Information) 常用方法 • 递归特征消除 (RFE) • 前向/后向选择 • 遗传算法 (GA) 常用方法 • Lasso (L1正则化) • 树模型特征重要性 • Elastic Net 偏差-方差权衡 与 特征选择 • 特征太多 → 方差↑(过拟合) • 特征太少 → 偏差↑(欠拟合) • 好的特征选择就是找到平衡点: 保留足够信号,剔除噪声,让模型既准又稳

一、过滤式方法 (Filter Methods)

过滤式方法,说白了就是先打分后建模。它不依赖任何模型,只靠数据本身的统计量来筛选特征。我习惯先拿Filter方法做个快速扫荡,把明显没用的变量干掉。

核心思想:用统计指标(方差、相关性、互信息等)给每个特征打分,设定阈值直接剔除低分特征。

举个例子:有个字段叫“客户ID”,显然后面不会保留。但有些数值字段乍一看正常,方差却接近0——比如“逾期月数”全是0,这种变量对区分好坏客户毫无贡献。

我用Python做初期筛选时,经常写这样的代码:

from sklearn.feature_selection import VarianceThreshold

selector = VarianceThreshold(threshold=0.01)  # 去掉方差低于0.01的特征
X_selected = selector.fit_transform(X)

为什么Filter方法受欢迎?因为它快。数据量再大,跑一遍卡方检验也就几秒钟。但我曾经在一个信用评分项目里吃过亏——Filter方法把两个强相关的变量都选了进来(比如“月收入”和“年收入”),导致模型共线性严重,权重解释性全乱套。

避坑指南:Filter方法选出的特征之间可能存在高度相关,建议再跑一遍相关性分析,剔除重复信息。

二、包裹式方法 (Wrapper Methods)

包裹式方法就不同了,它是“以模型为裁判”。每次选一个特征子集,跑一遍模型看效果,然后根据反馈增删特征。你想想看,这就像你面试候选人的时候,让实际业务团队先试用一个月再决定去留——结果肯定准,但代价也高。

我记得曾经参与过一个特征数量超过500的评分卡项目,团队想用递归特征消除(RFE)来精筛。结果跑了一个通宵还没出结果——因为每轮都要重新训练逻辑回归,而且K折交叉验证叠加上去,计算量直接爆炸。

个人习惯:在特征数≤50、样本量适中的场景下,我才会考虑Wrapper方法。否则容易把服务器跑崩。

常用的包裹式方法有:

  • 递归特征消除 (RFE):每轮训练后剔除权重最小的特征,迭代直到达目标数目。
  • 前向选择:从空集开始,每一步添加一个使模型效果提升最多的特征。
  • 后向消除:从全量特征开始,每一步踢掉一个贡献最小的特征。
  • 遗传算法:模拟进化过程,随机交叉变异找最优子集——适合特征维度极高但资源充足的情况。

如果你必须用Wrapper,我建议配合早停策略。比如设定“连续3轮效果不提升就终止”,能省不少时间。

三、嵌入式方法 (Embedded Methods)

嵌入式方法是我个人最偏爱的。它把特征选择和模型训练合二为一,训练过程中自动给特征做“惩罚”或“剪枝”。说白了,模型自己就知道哪些变量没用,不用你额外折腾。

最典型的例子就是Lasso回归(L1正则化)。它在损失函数里加了一项λ|β|,让弱特征的系数直接变成0。看代码:

from sklearn.linear_model import Lasso

lasso = Lasso(alpha=0.01)
lasso.fit(X_train, y_train)
coef = lasso.coef_
# 系数为0的特征自动被剔除
selected_features = X_train.columns[coef != 0]

树模型(如随机森林、XGBoost)也会内置特征重要性评分。你训练完直接看feature_importances_,把低于阈值的特征扔掉就行。省事,而且效果往往不差。

嵌入式 vs 其余两种:速度比Wrapper快,选择又比Filter精准,是工业界的“黄金中间人”。

但是有个坑——Lasso的正则化强度α需要调参。选大了,有效特征也被压成0;选小了,起不到筛选作用。我在项目中一般先用交叉验证跑个LassoCV,让模型自动选α。

from sklearn.linear_model import LassoCV

lasso_cv = LassoCV(cv=5)
lasso_cv.fit(X_train, y_train)
print("最优 alpha:", lasso_cv.alpha_)

四、偏差-方差权衡 与 特征选择

聊特征选择,绕不开这个核心概念。你想想看,特征选多了,模型会记住太多噪声,方差变大——换一批数据立马拉胯。特征选少了,模型学不到规律,偏差变大——连训练集都拟合不好。

为什么会这样?我举个极端的例子。假设你有100个随机噪声特征,强行扔进逻辑回归。模型为了在训练集上“表现”好,会给这些噪声特征分配非零权重。结果呢?测试集上完全失效——这就是方差在作祟。

反过来,如果只保留两个弱特征(比如“年龄”和“职业”),模型永远学不透坏客户的复杂模式,预测准确性始终偏低——这就是偏差的锅。

特征数量偏差方差典型后果
过少高低欠拟合,预测不准
适中低低泛化能力最强
过多低高过拟合,上线崩盘

所以特征选择的本质,就是在偏差和方差之间找那个“甜蜜点”。我常用的方法是:先用Filter快速砍掉无价值特征,再用Embedded方法(比如LassoCV)精筛,最后用一份独立验证集做交叉验证,看AUC和KS的稳定性。如果验证集和训练集差异超过5个百分点,大概率是特征过多了。

速记口诀:Filter保下限,Embedded提上限,Wrapper留给小样本。

好了,理论部分就到这。理解了这三大门派和偏差-方差的关系,后面案例实战你自然就知道该选哪种方法了。