分类表格有很多数值特征时,可以用 SelectKBest 按每列与标签的统计关联,保留得分最高的 k 列。把筛选器放进 Pipeline,训练时只在训练集学习筛选规则,预测时复用同一组字段。本文演示从四列鸢尾花特征选出两列,并把筛选结果对应回原始列名;不承诺筛列一定提高准确率。
先确定筛选任务和环境
这适合已有数值特征 X、人工确认分类标签 y,希望减少输入列数的读者。SelectKBest 保留原始列,不产生新的组合特征;它与 PCA 的投影结果不同,也与训练后打乱字段测模型依赖的置换重要性不同。

示例已于 2026 年 10 月 1 日在 Windows、Python 3.11.15、scikit-learn 1.7.2、pandas 2.3.3、NumPy 2.4.6、SciPy 1.17.1 环境运行。使用库内置 Iris 教学数据,运行输出只证明这组教学实验可复现,不是企业数据上的效果。新建目录后可在终端准备环境:
python -m venv .venv
.venv\Scripts\python -m pip install "scikit-learn==1.7.2" "pandas==2.3.3" "numpy==2.4.6" "scipy==1.17.1"
官方特征选择指南把单变量筛选作为估计器之前的预处理步骤;SelectKBest API说明 k 表示保留数量、f_classif 为分类任务计算 ANOVA F 值,并提供列掩码和输出列名接口。
先划分数据,再在 Pipeline 中学习要保留的列
将下面代码保存为 select_features.py,运行 .venv\Scripts\python select_features.py。输入是 Iris 的四个数值字段,输出是保留字段、每列得分、筛选后的形状和测试预测。这里预先固定 k=2,测试集没有参与选列或决定 k。
import numpy as np
from sklearn.datasets import load_iris
from sklearn.feature_selection import SelectKBest, f_classif
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import accuracy_score
from sklearn.model_selection import train_test_split
from sklearn.pipeline import Pipeline
from sklearn.preprocessing import StandardScaler
data = load_iris(as_frame=True)
X_train, X_test, y_train, y_test = train_test_split(
data.data, data.target, test_size=0.3, stratify=data.target,
random_state=7)
model = Pipeline([
("select", SelectKBest(score_func=f_classif, k=2)),
("scale", StandardScaler()),
("classify", LogisticRegression(max_iter=500))
])
model.fit(X_train, y_train)
selector = model.named_steps["select"]
names = selector.get_feature_names_out()
print("保留字段:", names.tolist())
for name, score, selected in zip(
X_train.columns, selector.scores_, selector.get_support()):
print(name, f"F={score:.3f}", "保留" if selected else "删除")
selected_test = selector.transform(X_test)
prediction = model.predict(X_test)
print("验证输入形状:", X_test.shape, "筛选后:", selected_test.shape)
print("验证准确率:", f"{accuracy_score(y_test, prediction):.4f}")
assert selected_test.shape == (len(X_test), 2)
assert names.tolist() == X_train.columns[selector.get_support()].tolist()
assert np.isfinite(selector.scores_).all()
顺序是 select → scale → classify。model.fit() 先让筛选器仅查看 X_train 与 y_train,再把保留的两列交给标准化和逻辑回归。model.predict(X_test) 接受完整原始四列,自动完成同一套变换。不要先在全部数据上 fit_transform 再划分;官方常见错误指南明确说明,特征选择接触测试集会让评估偏乐观。
如何核对筛选结果
本次实际输出如下。三个 assert 分别检查筛选后确实剩两列、输出列名与原始列掩码一致、得分为有限值:
保留字段: ['petal length (cm)', 'petal width (cm)']
sepal length (cm) F=103.533 删除
sepal width (cm) F=31.455 删除
petal length (cm) F=947.499 保留
petal width (cm) F=664.949 保留
验证输入形状: (45, 4) 筛选后: (45, 2)
验证准确率: 0.9778
petal length (cm) 和 petal width (cm) 被保留,sepal 两列被删除;这只是本次训练划分中按 F 值排序得到的结果。验证输入仍是 45 行、4 列,经筛选变成 45 行、2 列。测试准确率 0.9778 对应这次教学实验,不能据此判断真实业务应当永远使用这两个字段。
替换自己的表格时,先固定特征字段列表和标签列,保证标签不混入 X;保留 DataFrame 的字符串列名,然后照样划分、训练、读取 get_feature_names_out()。部署预测时仍提交原始字段及其原始含义,不把两列结果当成四列输入再次送进 Pipeline。
哪些情况下先停下来检查
- k 超过输入列数、标签行数与特征行数不一致或数据含不可处理的字符串:先修正输入契约,不能通过删报错行掩盖问题。
- 常量列导致 F 值无效、存在缺失或无穷值:先确认数据处理方案,并把处理步骤放在训练流程内。
- F 值较小不等于该字段完全无用。单变量统计不检查多列共同作用,不证明因果关系,也不能代替模型在独立样本上的验证。
- 想比较不同 k:在训练集内部做交叉验证,确定方案后再用保留的测试集验收;不要反复看测试结果决定删哪列。
下一步可以用业务训练数据执行同一流程,保存保留列清单,再用未参与选列的样本核对预测与错误类型。若减少字段后错误代价升高,就保留原方案并分析损失的信号,不为追求更少列强行上线。
Ai菜鸟网。发布者:AI小管家,转载请注明出处:https://www.alyyhw.com/30806.html