MultiIndex数据框LabelEncoder编码时未知标签ValueError问题求解
解决LabelEncoder测试集未知标签报错问题
现有18×80的Pandas MultiIndex数据框,分为“TEAM ONE”和“TEAM TWO”两组,需对categoricals数组指定的分类列做LabelEncoder编码,但测试集执行时出现ValueError: y contains previously unseen labels报错。由于LabelEncoder没有handle_unknown参数,try/except方案实用性不足,可通过以下几种方式解决:
方法1:提前检测并替换未知标签
先在训练集拟合编码器时记录所有已知标签,处理测试集前将不在训练集中的标签统一替换为“unknown”,再更新编码器的类别列表后执行转换:
import numpy as np from sklearn.preprocessing import LabelEncoder categoricals = ['TRAITS', 'UNIT_1', 'UNIT_2', 'UNIT_3', 'AUGMENT_1', 'AUGMENT_2', 'AUGMENT_3'] le = {col: LabelEncoder() for col in categoricals} # 处理训练集,同时记录每个列的已知标签 for col in train_data.columns.levels[0]: for sub_col in train_data.columns.levels[1]: if sub_col in le: train_series = train_data[(col, sub_col)].astype(str) le[sub_col].fit(train_series) train_data[(col, sub_col)] = le[sub_col].transform(train_series) # 保存该列的已知标签集合 le[sub_col].known_labels = set(le[sub_col].classes_) # 处理测试集:替换未知标签并转换 for col in test_data.columns.levels[0]: for sub_col in test_data.columns.levels[1]: if sub_col in le: test_series = test_data[(col, sub_col)].astype(str) # 替换不在训练集中的标签为统一值 test_series = test_series.apply(lambda x: x if x in le[sub_col].known_labels else 'unknown') # 将统一值加入编码器的类别列表(避免transform报错) if 'unknown' not in le[sub_col].classes_: le[sub_col].classes_ = np.append(le[sub_col].classes_, 'unknown') test_data[(col, sub_col)] = le[sub_col].transform(test_series)
方法2:改用OrdinalEncoder(推荐)
OrdinalEncoder支持handle_unknown参数,可直接指定未知标签的编码值(如-1),无需额外处理,更适合批量列的编码场景:
from sklearn.preprocessing import OrdinalEncoder categoricals = ['TRAITS', 'UNIT_1', 'UNIT_2', 'UNIT_3', 'AUGMENT_1', 'AUGMENT_2', 'AUGMENT_3'] encoders = {} for col in train_data.columns.levels[0]: for sub_col in categoricals: # 初始化编码器,设置未知标签处理规则 enc = OrdinalEncoder(handle_unknown='use_encoded_value', unknown_value=-1) # 拟合并转换训练集 train_col = train_data[(col, sub_col)].astype(str).values.reshape(-1, 1) train_data[(col, sub_col)] = enc.fit_transform(train_col).flatten() # 转换测试集 test_col = test_data[(col, sub_col)].astype(str).values.reshape(-1, 1) test_data[(col, sub_col)] = enc.transform(test_col).flatten() encoders[(col, sub_col)] = enc
方法3:手动构建标签映射字典
跳过LabelEncoder,自己建立训练集标签到编码的映射,测试集遇到未知标签时返回默认值(如-1):
categoricals = ['TRAITS', 'UNIT_1', 'UNIT_2', 'UNIT_3', 'AUGMENT_1', 'AUGMENT_2', 'AUGMENT_3'] label_maps = {} # 构建训练集的标签-编码映射 for col in train_data.columns.levels[0]: for sub_col in categoricals: train_series = train_data[(col, sub_col)].astype(str) unique_labels = train_series.unique() label_map = {label: idx for idx, label in enumerate(unique_labels)} label_maps[(col, sub_col)] = label_map # 转换训练集 train_data[(col, sub_col)] = train_series.map(label_map) # 转换测试集,未知标签用-1标记 for col in test_data.columns.levels[0]: for sub_col in categoricals: test_series = test_data[(col, sub_col)].astype(str) label_map = label_maps[(col, sub_col)] test_data[(col, sub_col)] = test_series.map(lambda x: label_map.get(x, -1))
内容的提问来源于stack exchange,提问作者Mangohero1
相关产品推荐
相关产品推荐

