特征归约:给数据“减肥”,让模型不再“虚胖”
一、为什么要给特征“减肥”想象你在训练一个模型来预测房价。一开始你有这些特征面积卧室数量地段小区绿化率附近奶茶店数量 ☕附近奶茶店老板星座 ♌模型看到这么多特征感动得眼泪掉下来“你这是要我算房价还是要我算命”这就是维度灾难Curse of Dimensionality特征越多数据越稀疏计算越来越慢噪声越来越多模型越来越容易过拟合于是我们需要特征归约Feature Reduction。二、特征归约到底是啥一句话版在不明显伤害模型性能的前提下把没用的特征砍掉或者把多个特征压缩成一个。专业一点特征归约 降低特征空间维度目标保留有用信息减少冗余、噪声和计算成本三、三大门派特征归约怎么搞我们用一个武侠比喻门派核心思想代表人物过滤法Filter先筛特征再训练模型老中医望闻问切包裹法Wrapper用模型本身挑特征选秀节目评委嵌入法Embedded训练过程中顺便挑一边跳舞一边扫地下面一个个来。四、过滤法像体检一样筛特征核心思想不看模型表现只看特征和标签之间的统计关系常见指标相关系数Correlation卡方检验Chi-square互信息Mutual Information举个栗子 气温 ↑ → 冰淇淋销量 ↑ 相关系数 ≈ 0.9 ✅ 奶茶店老板星座 ↔ 房价 相关系数 ≈ 0.001 ❌流程图✅ 优点快❌ 缺点不考虑特征组合效果五、包裹法模型亲自选秀核心思想把特征选择当成搜索问题用模型准确率当评分标准常见玩法前向选择Forward Selection后向消除Backward Elimination通俗解释就像你收拾行李先只带一件衣服试试能不能出门再慢慢加直到不能再加了为止示意图✅ 优点效果好❌ 缺点慢非常慢巨慢六、嵌入法一边训练一边选核心思想特征选择是模型训练的一部分最典型的代表正则化RegularizationLasso 回归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_yTrue, as_frameTrue) X_train, X_test, y_train, y_test train_test_split( X, y, test_size0.2, random_state42 ) print(原始特征数:, X_train.shape[1])9.3 Step 1过滤法 —— 低方差特征剔除如果一个特征几乎不变那它对模型基本没用。variance_selector VarianceThreshold(threshold0.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‑scorek_best_selector SelectKBest(score_funcf_regression, k5) 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(alpha0.1, random_state42) 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²越高越好Baseline8~0.60特征归约后≤5持平甚至略升 ✅✅结论特征更少泛化能力更强推理更快模型更好解释9.9 完整流程图Mermaid9.10 最佳实践建议来自踩坑经验✅顺序很重要Filter → Scaler → Embedded → Model✅不要对测试集做任何 fit✅树模型 ≠ 必须标准化✅线性模型强烈建议标准化十、总结一句话特征归约不是“删数据”而是帮模型少走弯路、少背垃圾、多学本质。