一、为什么要给特征“减肥”?
想象你在训练一个模型来预测房价。
一开始你有这些特征:
面积
卧室数量
地段
小区绿化率
附近奶茶店数量 ☕
附近奶茶店老板星座 ♌
模型看到这么多特征,感动得眼泪掉下来:
“你这是要我算房价,还是要我算命?”
这就是维度灾难(Curse of Dimensionality):
特征越多,数据越稀疏
计算越来越慢
噪声越来越多
模型越来越容易过拟合
于是,我们需要特征归约(Feature Reduction)。
二、特征归约到底是啥?
一句话版:
在不明显伤害模型性能的前提下,把没用的特征砍掉,或者把多个特征压缩成一个。
专业一点:
特征归约 = 降低特征空间维度
目标:保留有用信息,减少冗余、噪声和计算成本
三、三大门派:特征归约怎么搞?
我们用一个武侠比喻:
门派 | 核心思想 | 代表人物 |
|---|---|---|
过滤法(Filter) | 先筛特征,再训练模型 | 老中医望闻问切 |
包裹法(Wrapper) | 用模型本身挑特征 | 选秀节目评委 |
嵌入法(Embedded) | 训练过程中顺便挑 | 一边跳舞一边扫地 |
下面一个个来。
四、过滤法:像体检一样筛特征
核心思想
不看模型表现
只看特征和标签之间的统计关系
常见指标:
相关系数(Correlation)
卡方检验(Chi-square)
互信息(Mutual Information)
举个栗子 🌰
气温 ↑ → 冰淇淋销量 ↑ 相关系数 ≈ 0.9 ✅ 奶茶店老板星座 ↔ 房价 相关系数 ≈ 0.001 ❌流程图
✅ 优点:快
❌ 缺点:不考虑特征组合效果
五、包裹法:模型亲自选秀
核心思想
把特征选择当成搜索问题
用模型准确率当评分标准
常见玩法:
前向选择(Forward Selection)
后向消除(Backward Elimination)
通俗解释
就像你收拾行李:
先只带一件衣服试试能不能出门
再慢慢加,直到不能再加了为止
示意图
✅ 优点:效果好
❌ 缺点:慢,非常慢,巨慢
六、嵌入法:一边训练一边选
核心思想
特征选择是模型训练的一部分
最典型的代表:正则化(Regularization)
Lasso 回归(L1 正则化)
公式简单说一下(不吓人版):
损失函数 = 预测误差 + λ × |权重|
L1 的特性:
不重要特征的权重直接压成0
等于自动做特征选择 ✅
示意图
✅ 优点:高效、稳定
❌ 缺点:解释性略弱
七、PCA特征提取:不是删,而是“炼”
前面讲的是删特征,
还有一种叫特征提取(Feature Extraction):
把多个旧特征,合成几个新特征
PCA(主成分分析)
找方差最大的方向
把高维数据投影到低维空间
一句话解释:
把三维物体拍成一张照片,尽量保留原貌
示意图
⚠️ 注意:
PCA 后的特征是“合成特征”,可解释性较差
八、该怎么选?一张速查表
场景 | 推荐方式 |
|---|---|
特征多、算力少 | Filter |
特征不多、追求极致效果 | Wrapper |
工业级、线上系统 | Embedded |
特征高度相关 | PCA |
九、🧪 实战案例:用 scikit‑learn 完成一次“标准特征归约流水线”
任务设定
数据集:加州房价(
fetch_california_housing)目标:预测房价中位数
特征归约策略:
删除低方差特征(过滤法)
保留高相关特征(Filter)
使用 Lasso 做嵌入法特征选择
对比有无特征归约的模型效果
9.1 环境准备
import numpy as np import pandas as pd from sklearn.datasets import fetch_california_housing from sklearn.model_selection import train_test_split from sklearn.preprocessing import StandardScaler from sklearn.feature_selection import ( VarianceThreshold, SelectKBest, f_regression ) from sklearn.linear_model import Lasso, LinearRegression from sklearn.metrics import mean_squared_error, r2_score9.2 加载并拆分数据
X, y = fetch_california_housing(return_X_y=True, as_frame=True) X_train, X_test, y_train, y_test = train_test_split( X, y, test_size=0.2, random_state=42 ) print("原始特征数:", X_train.shape[1])9.3 Step 1:过滤法 —— 低方差特征剔除
如果一个特征几乎不变,那它对模型基本没用。
variance_selector = VarianceThreshold(threshold=0.01) X_train_var = variance_selector.fit_transform(X_train) X_test_var = variance_selector.transform(X_test) print("低方差筛选后特征数:", X_train_var.shape[1])✅作用:去掉“死水特征”
9.4 Step 2:过滤法 —— 单变量特征选择
看每个特征和房价之间的统计关系(F‑score)
k_best_selector = SelectKBest(score_func=f_regression, k=5) X_train_kbest = k_best_selector.fit_transform(X_train_var, y_train) X_test_kbest = k_best_selector.transform(X_test_var) selected_features = X_train.columns[k_best_selector.get_support()] print("保留的特征:", list(selected_features))📌这一步相当于:
“模型还没训练,我就先把看起来有用的特征挑出来。”
9.5 Step 3:嵌入法 —— Lasso 自动特征选择
标准化(非常重要)
scaler = StandardScaler() X_train_scaled = scaler.fit_transform(X_train_kbest) X_test_scaled = scaler.transform(X_test_kbest)训练 Lasso 回归
lasso = Lasso(alpha=0.1, random_state=42) lasso.fit(X_train_scaled, y_train)查看哪些特征被“干掉了”
coef_df = pd.DataFrame({ "feature": selected_features, "coefficient": lasso.coef_ }) print(coef_df)📉系数为 0 的特征 = 被 Lasso 自动淘汰
9.6 Step 4:用 Lasso 权重再做一次特征筛选
important_features_mask = lasso.coef_ != 0 X_train_lasso = X_train_scaled[:, important_features_mask] X_test_lasso = X_test_scaled[:, important_features_mask] final_features = selected_features[important_features_mask] print("Lasso 最终保留特征:", list(final_features))9.7 建模对比:归约前 vs 归约后
1️⃣ 基线模型(无特征归约)
baseline_model = LinearRegression() baseline_model.fit( StandardScaler().fit_transform(X_train), y_train ) y_pred_baseline = baseline_model.predict( StandardScaler().transform(X_test) ) print("Baseline R²:", r2_score(y_test, y_pred_baseline))2️⃣ 特征归约后模型
reduced_model = LinearRegression() reduced_model.fit(X_train_lasso, y_train) y_pred_reduced = reduced_model.predict(X_test_lasso) print("Reduced R²:", r2_score(y_test, y_pred_reduced))9.8 结果解读(重点)
模型 | 特征数 | R²(越高越好) |
|---|---|---|
Baseline | 8 | ~0.60 |
特征归约后 | ≤5 | 持平甚至略升 ✅ |
✅结论:
特征更少
泛化能力更强
推理更快
模型更好解释
9.9 完整流程图(Mermaid)
9.10 最佳实践建议(来自踩坑经验)
✅顺序很重要
Filter → Scaler → Embedded → Model
✅不要对测试集做任何 fit
✅树模型 ≠ 必须标准化
✅线性模型强烈建议标准化
十、总结一句话
特征归约不是“删数据”,
而是帮模型少走弯路、少背垃圾、多学本质。