Kaggle竞赛分类任务中训练与测试集类别不一致的编码处理咨询
处理训练集与测试集类别不一致的编码方案
首先明确:测试集先fit再transform的操作是错误的
你对测试集单独做fit再transform的操作完全不对,原因很直接:
- 标签编码(Label Encoding)的
fit过程是建立类别到数字的固定映射关系,训练集和测试集必须共用同一套映射,模型才能正确识别特征含义。 - 如果测试集单独fit,会生成一套全新的映射——比如训练集里的"HTTP"可能对应1,测试集里的"HTTP"可能对应3,模型拿到测试数据时会完全无法理解,直接导致预测失效。
- 正确做法:只在训练集上调用
fit,然后用同一个编码器实例分别对训练集和测试集做transform。
针对训练集多2个类别的处理方案
针对训练集service列比测试集多2个类别的情况,推荐以下几种实用方案:
1. 合并罕见类别(最推荐)
如果训练集里那2个独有的类别出现次数极少(比如占比不到1%),直接在训练阶段把它们合并成一个统一的"其他"类别:
# 统计训练集service列的类别频数 freq = train['service'].value_counts() # 定义罕见类别阈值,比如出现次数少于50的归为其他 rare_cats = freq[freq < 50].index train['service'] = train['service'].replace(rare_cats, 'other') # 用处理后的训练集fit编码器 le = LabelEncoder() le.fit(train['service']) # 对测试集做预处理,未知类别替换为other test['service'] = test['service'].replace(test['service'].difference(le.classes_), 'other') # 执行编码 train['service_encoded'] = le.transform(train['service']) test['service_encoded'] = le.transform(test['service'])
2. 使用目标编码/频数编码
这类编码基于训练集的统计信息(比如类别对应的目标变量均值、类别出现频率),不需要严格的类别-数字映射,测试集里没有的类别直接用训练集的全局统计值填充:
- 频数编码:用训练集里每个类别的出现频率作为编码值,测试集未知类别用0或者训练集的平均频率填充。
- 目标编码:用训练集里每个类别对应的目标变量均值作为编码值,测试集未知类别用目标变量的全局均值填充。
3. 修正One-Hot编码的维度
如果用One-Hot编码,必须保证训练集和测试集的特征维度完全一致:
- 用训练集生成所有66个类别对应的One-Hot列,测试集里没有的那2个类别列直接填充0。
- 可以用
pandas.get_dummies结合reindex实现:
train_onehot = pd.get_dummies(train, columns=['service']) test_onehot = pd.get_dummies(test, columns=['service']) # 对齐列,测试集没有的列填0 test_onehot = test_onehot.reindex(columns=train_onehot.columns, fill_value=0)
4. 使用支持未知类别的编码器
比如category_encoders库中的CatBoostEncoder或者TargetEncoder,它们默认会处理训练集未见过的类别,自动用训练数据的统计值填充,不需要额外处理:
from category_encoders import CatBoostEncoder encoder = CatBoostEncoder(cols=['service']) encoder.fit(train['service'], train['target']) train['service_encoded'] = encoder.transform(train['service']) test['service_encoded'] = encoder.transform(test['service'])
内容的提问来源于stack exchange,提问作者user22689820
相关产品推荐
相关产品推荐

