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

独热编码后如何保持训练集与测试集的列数及列名一致?

解决训练集与测试集独热编码特征不匹配问题

问题背景

原始数据集规模为82580×30,包含多个字符串列。在训练阶段对Nationality列做独热编码后,测试集出现了训练集未见过的类别(如CAN),同时训练集存在的部分类别(如AUT、CHE)在测试集中缺失,导致训练集和测试集的特征维度、特征列完全不一致。若直接取.values强行拟合模型,虽能得到高准确率但属于违规操作,且这类方法无法在决策树等依赖特征列匹配的模型中生效。

核心解决方案

1. 复用训练阶段的编码器,禁止在测试集重新拟合

机器学习预处理必须遵循训练集拟合、测试集转换的原则:编码器仅在训练集上执行fit操作,保存训练后的编码器,测试集直接使用该编码器的transform方法。这样测试集会自动对齐训练集的特征结构——训练集有的特征列测试集都会保留,测试集缺少的训练集类别对应列填充0,训练集未见过的新类别会被转换为全0编码向量。

2. 配置编码器处理未知类别

初始化OneHotEncoder时设置handle_unknown='ignore',确保遇到训练集未见过的类别时不会抛出错误,而是生成全0的编码向量,避免特征维度突变。

3. 避免冗余特征

原代码中拼接了编码特征与原始特征,导致Age、DaysSinceCreation等列重复,直接使用编码器转换后的结果作为特征矩阵即可,无需保留原始列。

完整修正代码示例

训练阶段代码

import pandas as pd
from sklearn.preprocessing import OneHotEncoder
from sklearn.compose import make_column_transformer

# 加载训练集数据
train_df = pd.DataFrame(
    {'Nationality': {0: 'DEU', 1: 'PRT', 2: 'PRT', 3: 'PRT', 4: 'FRA', 5: 'DEU', 6: 'CHE', 7: 'DEU', 8: 'GBR', 9: 'AUT', 10: 'PRT', 11: 'FRA', 12: 'OTR', 13: 'GBR', 14: 'ESP', 15: 'PRT', 16: 'OTR', 17: 'PRT', 18: 'ESP', 19: 'AUT'},
     'Age': {0: 27.0, 1: 45.46, 2: 45.46, 3: 58.0, 4: 57.0, 5: 27.0, 6: 49.0, 7: 62.0, 8: 44.0, 9: 61.0, 10: 54.0, 11: 53.0, 12: 50.0, 13: 30.0, 14: 51.0, 15: 45.46, 16: 40.0, 17: 49.0, 18: 49.0, 19: 14.0},
     'DaysSinceCreation': {0: 370, 1: 213, 2: 206, 3: 1018, 4: 835, 5: 52, 6: 597, 7: 217, 8: 999, 9: 1004, 10: 402, 11: 879, 12: 393, 13: 923, 14: 249, 15: 52, 16: 159, 17: 929, 18: 49, 19: 131},
     'BookingsCheckedIn': {0: 1, 1: 0, 2: 0, 3: 1, 4: 1, 5: 1, 6: 1, 7: 2, 8: 1, 9: 1, 10: 1, 11: 1, 12: 1, 13: 1, 14: 1, 15: 0, 16: 0, 17: 1, 18: 1, 19: 0}}
)

# 定义编码器,配置未知类别处理策略
transformer = make_column_transformer(
    (OneHotEncoder(sparse=False, handle_unknown='ignore'), ['Nationality']),
    remainder='passthrough'
)

# 拆分特征与标签,仅在训练集拟合编码器并转换
X_train = transformer.fit_transform(train_df.drop('BookingsCheckedIn', axis=1))
y_train = train_df['BookingsCheckedIn'].values

# 验证训练集特征结构
X_train_df = pd.DataFrame(X_train, columns=transformer.get_feature_names_out())
print(f"训练集编码后形状: {X_train_df.shape}")
print(f"训练集特征列: {X_train_df.columns.tolist()}")

测试阶段代码

# 加载测试集数据
test_df = pd.DataFrame(
    {'Nationality': {0: 'CAN', 1: 'DEU', 2: 'PRT', 3: 'PRT', 4: 'FRA'},
     'Age': {0: 27.0, 1: 29.0, 2: 24.0, 3: 24.0, 4: 46.0},
     'DaysSinceCreation': {0: 222, 1: 988, 2: 212, 3: 685, 4: 1052},
     'BookingsCheckedIn': {0: 0, 1: 1, 2: 1, 3: 1, 4: 0}}
)

# 使用训练好的编码器转换测试集,不重新拟合
X_test = transformer.transform(test_df.drop('BookingsCheckedIn', axis=1))
y_test = test_df['BookingsCheckedIn'].values

# 验证测试集特征与训练集对齐
X_test_df = pd.DataFrame(X_test, columns=transformer.get_feature_names_out())
print(f"测试集编码后形状: {X_test_df.shape}")
print(f"训练/测试集特征维度一致: {X_train.shape[1] == X_test.shape[1]}")
print(f"测试集特征列: {X_test_df.columns.tolist()}")

效果说明

  • 训练集和测试集的特征维度完全一致,特征列一一对应
  • 测试集中的新类别CAN会被转换为全0的编码向量,不会新增特征列
  • 测试集缺失的训练集类别(如AUT、CHE)对应的特征列会保留,值为0
  • 所有模型(决策树、逻辑回归、神经网络等)都能正常使用,无需依赖违规操作

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.21 16:18:18