selectkbest需依目标变量类型和特征分布选score_func:分类用chi2(x≥0)、f_classif(x连续近正态)或mutual_info_classif(无分布假设);回归用f_regression(线性)或mutual_info_regression(非线性);稀疏二分类必用chi2。

SelectKBest 不是“选前 K 个特征”那么简单——它按统计得分排序后取 top-K,但得分计算方式取决于你传入的 score_func,选错函数会导致特征被误筛,尤其在非线性关系或分类目标下。
怎么选对 score_func?看目标变量类型和特征分布
选错函数比不筛选更危险:比如用 f_classif 处理类别型特征(如 one-hot 后的 city_A、city_B),会因方差为 0 报 ValueError: Input X must be non-negative;又比如对高偏态连续特征直接套 f_regression,线性假设失效,得分失真。
- 分类任务(y 是离散标签):优先用
chi2(要求 X ≥ 0)、f_classif(要求 X 连续且近似正态)、mutual_info_classif(无分布假设,但需设random_state保证可复现) - 回归任务(y 是连续值):用
f_regression(快但假设线性),或mutual_info_regression(慢但能捕获非线性) - 二分类且特征稀疏(如 TF-IDF):必须用
chi2,f_classif会报错
为什么 fit_transform() 后特征顺序变了,但列名丢了?
SelectKBest 只返回 numpy 数组,不保留列名。如果你依赖列名做后续解释(比如画重要性图、对接下游模型特征工程),必须手动映射回来。
图片提示词生成器?不止如此。 马甲系统 —— 把脑海中的画面,翻译成AI能理解的专业表达。 用得越多,它越懂你:首次需要多问几句确认方向,用久了几乎一说就懂。 用得越多,它越快:缓存机制让后续对话越来越省。 RAG进化:成功案例持续入库,越跑越聪明。 输入「新手指南」查看完整功能介绍
- 先用
selector.get_support()拿到布尔索引,再用它筛选原始 DataFrame 列名:mask = selector.get_support()<br>selected_cols = X_df.columns[mask].tolist()
- 别直接用
X_selected = pd.DataFrame(selector.fit_transform(X, y))——列名全变成 0,1,2… - 如果 pipeline 中要用,建议包一层自定义 transformer,重写
get_feature_names_out方法
用 k=10 真的就只留 10 个?小心数据泄漏和重复计算
常见陷阱:在交叉验证外一次性 fit 整个训练集,导致验证时信息泄露;或者在标准化前用 SelectKBest,让方差大的数值特征天然占优,掩盖了类别特征的真实贡献。
- 务必把
SelectKBest套进Pipeline,和StandardScaler或OneHotEncoder一起 fit:pipe = Pipeline([<br> ('scaler', StandardScaler()),<br> ('skb', SelectKBest(score_func=f_classif, k=10)),<br> ('clf', LogisticRegression())<br>]) -
k是绝对数量,不是比例。当训练集样本数 f_classif 的 F 统计量不稳定,建议换mutual_info_classif或增大k - 同一特征在不同折中可能被筛掉/留下——这不是 bug,是正常现象,说明该特征稳定性差
真正难的不是调 k,而是确认 score_func 和你的数据生成机制是否匹配;很多人卡在 chi2 报错却去查数据缺失,其实只是忘了先把负值特征截断或改用其他函数。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!










