手写数字识别:OneVsRest+LogisticRegression预测维度错误排查
问题根源与解决方案
1. 核心错误:predict()传错了数据
你调用ovr_model_best_fit.predict(y)时,把标签数组y当成了预测用的特征数据,完全搞反了用途:
- 模型训练时,
fit(X_train_scaled, y_train)里的X是785维的手写像素特征,y是0-9的数字标签 predict()需要传入特征数据(和训练时X同维度:N个样本×785特征),而不是标签数据
2. 代码里的其他逻辑错误
(1)数据拆分顺序混乱
原代码里train_test_split用到的y还没定义就调用了,而且筛选标签的条件冗余,正确顺序应该是:
# 筛选标签>7的样本(原条件(train['label']>3)&(train['label']>7)等价于label>7) train = train.loc[train['label'] > 7] # 先拆分特征和标签 y = train['label'] X = train.drop(['label'], axis=1) # 再划分训练集测试集 X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.50, random_state=42)
(2)标准化对象错误
原代码用MinMaxScaler处理了带标签的X_train,应该只标准化特征矩阵:
min_max_scaler = MinMaxScaler() X_train_scaled = min_max_scaler.fit_transform(X_train) X_test_scaled = min_max_scaler.transform(X_test) # 测试集复用训练集的缩放规则
3. 标签数据的正确用法
标签y(形状(4125,))不需要额外reshape,scikit-learn的分类模型直接接受1D数组作为标签,训练时直接传y_train即可。之前的维度报错,是因为你错误地把标签当成特征传入predict()导致的,不是标签本身的维度问题。
修正后的完整代码
import pandas as pd import numpy as np from sklearn.model_selection import train_test_split, RandomizedSearchCV, cross_val_score from sklearn.linear_model import LogisticRegression from sklearn.multiclass import OneVsRestClassifier from sklearn.preprocessing import MinMaxScaler # 加载数据 train = pd.read_csv("../data/DigitRecognizer/train.csv") test = pd.read_csv("../data/DigitRecognizer/test.csv") # 筛选标签>7的样本 train = train.loc[train['label'] > 7] # 拆分特征与标签 X = train.drop(['label'], axis=1) y = train['label'] # 划分训练集和测试集 X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.50, random_state=42) # 特征标准化 min_max_scaler = MinMaxScaler() X_train_scaled = min_max_scaler.fit_transform(X_train) X_test_scaled = min_max_scaler.transform(X_test) # 模型与参数搜索 ovr_model = OneVsRestClassifier(LogisticRegression()) param_grid = { 'estimator__max_iter': [2500, 4500, 6500, 9500, 14000], 'estimator__C': [0.1, 1, 100, 200] } ovr_grid_param = RandomizedSearchCV(ovr_model, param_grid, cv=5, n_jobs=3, error_score="raise") ovr_fit = ovr_grid_param.fit(X_train_scaled, y_train) # 输出搜索结果 print("\nOVR最佳估算器:\n", ovr_fit.best_estimator_) print("\nOVR最佳得分:\n", ovr_fit.best_score_) print("\nOVR最佳参数:\n", ovr_fit.best_params_) # 用最佳参数训练模型 ovr_model_best = OneVsRestClassifier(LogisticRegression(multi_class='ovr', C=200, max_iter=9500, solver='liblinear')) ovr_model_best_fit = ovr_model_best.fit(X_train_scaled, y_train) # 正确预测:传入测试集特征数据 ovr_model_best_pred = ovr_model_best_fit.predict(X_test_scaled) # 交叉验证:传入标准化后的特征和标签 ovr_score = cross_val_score(ovr_model_best, X_train_scaled, y_train, cv=3, scoring="accuracy") print("\n交叉验证准确率:\n", ovr_score)
关键提醒
- 严格区分特征X(预测输入,维度N×特征数)和标签y(预测目标,1D数组)
- 模型训练完成后,
predict()必须传入和训练时X维度一致的特征数据,不能传标签 - scikit-learn分类模型对标签的要求是1D数组,不需要额外reshape,只有特征数据需要是2D数组
内容的提问来源于stack exchange,提问作者Data Science Analytics Manager
相关产品推荐
相关产品推荐

