scikit-learn 1.0 强制特征名称对齐,predict() 严格校验列名与顺序;0.24 几乎不校验,训练用 dataframe、预测用 ndarray 可能静默通过。1.0 新增 model.feature_names_in_ 属性,记录训练列名,且 columntransformer 默认 remainder='drop',易引发列数不匹配报错。

Scikit-learn 1.0 强制要求特征名称对齐,0.24 几乎不校验——如果你训练用 DataFrame、预测用 numpy.ndarray,0.24 可能静默通过,1.0 会直接报错。
predict() 输入类型不一致时,1.0 会严格比对列名与顺序
0.24 版本中,SVC、RandomForestClassifier 等模型对输入类型宽容:训练时传 pd.DataFrame(X_train, columns=['a', 'b']),预测时传 np.array([[1, 2]]),只要维度匹配就跑得通。1.0 则会在 predict() 时检查 X.columns 是否等于训练时的 model.feature_names_in_;若传入 ndarray,它会尝试推断列名失败,抛出 ValueError: Number of features must match,哪怕 shape 完全一样。
常见触发场景:
- pipeline 中用了
ColumnTransformer+OneHotEncoder,训练时喂DataFrame,但线上预测只构造了ndarray - 用
model.feature_names_in_手动构造预测数据,但列顺序写反了(比如['age', 'income']vs['income', 'age']) - 训练后保存模型,加载时没同步保存原始
DataFrame的列信息,导致重建输入时丢失顺序
feature_names_in_ 成为 1.0+ 的标配属性,0.24 没有
model.feature_names_in_ 是 1.0 新增的只读属性,记录训练时输入的列名(仅当输入是 DataFrame 或带 feature_names 的 DictVectorizer 等)。0.24 根本不存在这个属性,调用会报 AttributeError。它不是可选功能,而是 1.0 内部校验逻辑的基础设施。
调试建议:
- 预测前先打印
model.feature_names_in_和你的输入X的列名或形状:print(model.feature_names_in_, getattr(X, 'columns', None)) - 若必须用
ndarray,确保列顺序与model.feature_names_in_严格一致,可用np.array(X)[:, [1, 0]]显式重排 - 避免依赖
model.feature_names_in_的存在来写兼容代码——0.24 环境下它不存在,1.0 下它一定存在且非空(只要训练输入带名)
ColumnTransformer 默认 remainder 行为变化影响特征名传递
0.24 中 ColumnTransformer 默认 remainder='passthrough',未指定的列会原样保留并参与后续步骤(如传给 SVC),其列名会被继承;1.0+(特别是 ≥1.2)默认改为 remainder='drop',未匹配的列直接丢弃,导致最终送入 estimator 的列数变少、列名缺失,feature_names_in_ 记录的也是过滤后的名字。
后果:
- 同一份配置 YAML,在 0.24 下训练出的模型有 10 个特征名,1.0 下只有 7 个
- 预测时若仍按旧逻辑构造 10 列输入,1.0 会因列数不匹配报错,而 0.24 可能靠
passthrough把多出的列也塞进去 - 修复方式:显式设
remainder='passthrough',或在 pipeline 开头加FunctionTransformer统一处理列名
最易被忽略的一点:特征名校验不是“开关式”行为,它嵌在 predict()、transform()、score() 等多个方法里,且只在输入为 DataFrame 时激活——你可能在 fit() 阶段一切正常,直到第一次 predict() 才暴露问题。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











