You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

经独热编码后SVM分类器预测报错:测试集特征数不匹配

解决SVM预测时特征数不匹配的问题

嘿,这个报错其实是机器学习预处理里最常见的坑之一——训练集和测试集的特征处理必须严格保持一致!你训练时把特征扩到了982维,但测试集还是原始的7维,模型当然会懵圈。而且你现在的代码里每次独热编码都重新初始化OneHotEncoder还调用fit_transform,这会导致编码规则每次都变,后续的列索引也全乱了,测试集根本没法复用这些规则。

我给你梳理下核心问题和修复方案:

核心问题

  1. 你在训练集上多次调用OneHotEncoder.fit_transform(),每次都会重新学习编码规则,而且因为独热编码会增加特征数,后续的categorical_features参数(比如[14]、[37])其实已经对应不上原来的列位置了,完全是错误的。
  2. 测试集没有经过和训练集完全一样的编码流程,直接用原始特征去预测,维度自然不匹配。

修复方案:复用训练阶段的编码器,统一预处理流程

最稳妥的做法是用ColumnTransformer来统一管理所有列的预处理,同时保存训练时用到的编码器,测试集只做transform(复用训练规则),不做fit。

修改后的完整代码

import pandas as pd
import numpy as np
from sklearn.preprocessing import LabelEncoder, OneHotEncoder
from sklearn.svm import LinearSVC
from sklearn.compose import ColumnTransformer

# ---------------------- 训练集预处理 ----------------------
df = pd.read_csv('train.csv', header=None)
features = df.iloc[:,:-1].values
labels = df.iloc[:,-1].values

# 第一步:先给所有分类列做LabelEncoder(把字符串转成模型能识别的数值)
# 你原来处理的是列2、3、4、5,先把这些列存下来
categorical_columns = [2, 3, 4, 5]
label_encoders = {}

for col in categorical_columns:
    le = LabelEncoder()
    # 训练集上用fit_transform,同时保存这个编码器
    features[:, col] = le.fit_transform(features[:, col])
    label_encoders[col] = le

# 第二步:用ColumnTransformer一次性处理独热编码,避免手动跟踪列索引
# 这个工具会自动处理分类列的编码,非分类列直接保留
column_transformer = ColumnTransformer(
    transformers=[
        # 指定对categorical_columns做独热编码,输出为密集数组
        ('onehot_encoder', OneHotEncoder(sparse_output=False), categorical_columns)
    ],
    remainder='passthrough'  # 其他列不做处理,直接保留
)

# 训练集上做fit_transform,学习编码规则
encoded_train_features = column_transformer.fit_transform(features)

# 训练SVM模型
X_train = np.array(encoded_train_features)
y_train = np.array(labels)
clf = LinearSVC()
clf.fit(X_train, y_train)

# ---------------------- 测试集预处理 ----------------------
d_test = pd.read_csv('query.csv')
Z_test = d_test.values

# 第一步:用训练时保存的LabelEncoder转换测试集的分类列
for col in categorical_columns:
    # 注意:如果测试集出现训练集没有的类别,这里会报错,可以加handle_unknown='ignore'(sklearn>=0.24支持)
    Z_test[:, col] = label_encoders[col].transform(Z_test[:, col])

# 第二步:用训练好的ColumnTransformer做transform,得到和训练集维度一致的特征
encoded_test_features = column_transformer.transform(Z_test)

# 现在可以正常预测了
confidence = clf.predict(encoded_test_features)
print("The query image belongs to Class ")
print(confidence)

关键注意点

  • 绝对不要在测试集上用fit/fit_transform:fit是从数据中学习规则,测试集必须复用训练集的规则,否则特征的维度、含义都会和训练时不一样,模型根本无法识别。
  • 用ColumnTransformer替代手动编码:手动一次次调用OneHotEncoder很容易因为特征数变化导致列索引错误,ColumnTransformer会自动帮你管理列的位置,靠谱得多。
  • 保存LabelEncoder:独热编码的前提是分类列已经转成数值,所以必须用训练时的LabelEncoder来转换测试集的对应列,不能重新训练。
  • 处理未知类别(可选):如果测试集可能出现训练集没见过的分类值,可以在初始化LabelEncoder时加le = LabelEncoder(handle_unknown='ignore'),这样遇到未知类别会自动忽略(或者用其他方式填充),避免报错。

内容的提问来源于stack exchange,提问作者arindom

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.28 07:30:41