Scikit-learn可通过SelectKBest+Pipeline+GridSearchCV实现自动化特征选择:SelectKBest用mutual_info_classif排序选前k个特征;RFE需绑定模型并搜索n_features_to_select;VarianceThreshold须在标准化前使用,且不可调参。

Scikit-learn 本身不提供“全自动特征选择流水线”,但能通过 SelectorMixin 兼容的类 + Pipeline + GridSearchCV 或 RandomizedSearchCV 实现可复现、可调参、可嵌入模型训练的自动化特征选择——关键在于把选择器当模型组件用,而不是单独跑一遍再手动删列。
用 SelectKBest + mutual_info_classif 做分类任务的自动特征打分与截断
这是最轻量、最可控的自动化起点:它不拟合模型,只按统计量排序选前 K 个特征,适合快速验证特征重要性分布。
-
SelectKBest必须显式指定k(如k=10),不能设为"all"或自动推断;设太小会丢信息,太大则失去筛选意义 - 分类任务优先用
mutual_info_classif(处理非线性关系),回归任务用mutual_info_regression;别误用f_classif处理高度偏态或离散目标 - 注意:输入
X必须是二维数组,y不能含缺失值;若原始数据有NaN,SelectKBest会直接报ValueError: Input contains NaN
from sklearn.feature_selection import SelectKBest, mutual_info_classif
from sklearn.pipeline import Pipeline
<p>selector = SelectKBest(score_func=mutual_info_classif, k=8)
pipe = Pipeline([("select", selector), ("clf", LogisticRegression())])
pipe.fit(X_train, y_train) # 自动完成选特征 + 训练
让 RFE 真正“自动”:绑定模型并参与超参搜索
RFE(递归特征消除)本身需要一个预训练模型来评估特征重要性,但它不自动决定最优特征数——必须和 GridSearchCV 配合,把 n_features_to_select 当超参搜。
-
RFE内部会反复训练模型(如SVC或RandomForestClassifier),计算量明显高于SelectKBest;大数据集慎用 -
step参数控制每次剔除多少特征,默认为 1;设为较大值(如step=5)可加速,但可能跳过局部最优 - 务必使用支持
feature_importances_或coef_的模型;LogisticRegression要加solver="liblinear"(旧版)或"lbfgs"才稳定输出coef_
from sklearn.feature_selection import RFE
from sklearn.model_selection import GridSearchCV
<p>rfe = RFE(estimator=RandomForestClassifier(), step=1)
param_grid = {"n_features_to_select": [5, 10, 15, 20]}
search = GridSearchCV(rfe, param_grid, cv=3)
search.fit(X_train, y_train)
避免 VarianceThreshold 在 pipeline 中“静默失效”
VarianceThreshold 常被当成预处理第一步,但它对标准化后的连续特征几乎无效——方差被缩放到接近 0.01~0.1,远高于默认阈值 0.0,结果就是“什么都没删”。
立即学习“Python免费学习笔记(深入)”;
- 若想删低方差特征,必须在标准化前运行;否则先
StandardScaler再VarianceThreshold,大概率零效果 - 布尔型特征(0/1)方差最大为 0.25,若设
threshold=0.1,会删掉出现频率在 13%~87% 之外的所有布尔列;这个范围比直觉窄得多 - 它不依赖
y,所以不能用在GridSearchCV里调threshold——因为没有score可优化;只能靠领域知识预设
真正难的是特征交互与非线性筛选的自动化边界
像 RFECV 或基于树模型的 importance 排序,都隐含线性可分或单棵树的假设。遇到强交互特征(如 A×B 效应显著,但 A、B 单独不重要),所有内置选择器都会漏掉——此时必须人工构造交互项,再喂给选择器;自动化只负责“从已有列里挑”,不负责“生成新列”。


















