one-hot 编码的可用类别的一致性

Posted

技术标签:

【中文标题】one-hot 编码的可用类别的一致性【英文标题】:consistency in available categories for one-hot encoding 【发布时间】:2020-08-27 13:01:22 【问题描述】:

假设我有两个数据集,一个用于训练,一个用于预测。

在两个数据集中,我有相同的分类变量,我希望使用 sklearn 的 preprocessing.OneHotEncoder() 进行一次热编码。

接下来,让我们看看变量 X 可能的唯一值:['a', 'b', 'c', 'd', 'e']

因此,变量 X 存在于训练和测试数据集中。但是,只有值'a''b' 出现在训练集中,而只有'c''d''e' 出现在测试集中。

所以,如果我将以下代码应用于这两个数据集:

enc1 = pre.OneHotEncoder()
to_encode = train_df.select_dtypes(include='object')
encoded = enc1.fit_transform(to_encode).toarray()
dum_df = pd.DataFrame(encoded, columns=enc1.get_feature_names(to_encode.columns))
train_df = train_df.join(dum_df)
train_df.drop(to_encode.columns, axis=1, inplace=True)

# And repeat, just replace train_df with test_df

我得到两个单热编码数据帧。但是,它们的维度会有所不同,因为训练集中的一些值没有出现在测试集中(反之亦然)。

假设我已经在训练集上训练了一个算法:

    当我将测试集中的数据输入机器学习算法时会发生什么,该算法在训练集上进行了训练 不同的维度? 算法是否会关心某些数据列是否丢失?具体来说,我使用的是XGBoost.XGBRegressor(),但我也有兴趣知道是否有一个通用的答案。

【问题讨论】:

1.你不/不能。无论您用于训练的任何功能都需要用于测试。如果您的特征是 [a, b, c] 但您的测试数据只有 [d,e] 那么它不会为 d 和 e 获得 2 列,因为 [a, b, c] 它会获得全 0 的 3 列是您的功能,而您没有。您可以研究更复杂的数据拆分方法(分层随机拆分),以确保在必要时代表所有类别。 @ALollz 我在数据拆分方面受到限制,因为“测试”数据来自 kaggle 比赛并且是预先拆分的。他们对某些类别的测试数据没有全部可能的唯一值。我刚刚读到,如果我使用适合训练集的相同编码器,如果它没有这些值,它将插入所有 0 的列用于测试集编码。这似乎是一个合理的选择。你怎么看? 你不应该将 enc1.fit_transform() 应用于测试集,它应该只是 enc1.transform() 因为如果你再次适应,你正在从测试集中学习。然后,在 OneHotEncoder 中,您可以使用选项 handle_unknown="ignore" 来避免出现以前未见过的新类别时出现的错误。算法不管理缺失值,因为您必须先估算:scikit-learn.org/stable/modules/impute.html @jjsantoso 但是,我将丢失那些未知类别的数据。也许最好的办法是加入测试和训练数据,以便对所有可能的类别进行编码。然后,我可以稍后将它们拆分出来进行训练和预测。 @rocksNwaves 可能是这样,但你永远不知道全新的看不见的数据会带来什么,你需要能够处理所有这些情况。您可以使用已知类别创建字典,以未知类别缺失值的方式映射到新列。然后使用插补来填补缺失的新类别。您将以一个收集所有未知类别的新类别结束。并不完美,但您不会丢失所有信息。 【参考方案1】:

我认为 align 是您正在寻找的。如下例所示

train = pd.get_dummies(train)   #assume it  gives (1451, 221)  
test = pd.get_dummies(test)    #assume it gives (1459, 206)
# now doing alignment of train and test will do the trick  
final_train, final_test = train.align(test, join='inner', axis=1)  # inner join

【讨论】:

谢谢。我认为这仍然会导致数据丢失,即使形状是正确的。我决定加入我的测试和训练数据帧以达到 one-hot 的目的,因为在这种情况下不存在数据泄漏的危险。 确实是数据泄露的情况。如果在合并之前你做了一个热门并说你没有列“X”但在合并之后你得到列 X 因为火车,这意味着你的测试现在对你的火车有了一些想法。实际上,即使您这样做,测试数据中的 X 列也将包含全零! 很抱歉,但我不明白这是怎么回事。我处理过的每个算法都要求测试数据与训练数据的形状相同。如果列不同,您将抛出错误,直到包含那些缺失的列。由于一种热编码依赖于可能值的字典,或者它根据可用数据自动生成列,因此只有两种方法可以继续。 1.) 手动告诉它缺少的类别。 2.) 合并一个热点,然后再次拆分。无论哪种方式,结果都是一样的,而且是必要的。

以上是关于one-hot 编码的可用类别的一致性的主要内容,如果未能解决你的问题,请参考以下文章

PyTorch 对类别张量进行 one-hot 编码

多类分割One-hot 编码实现方式(转)

PyTorch——Tensor_把索引标签转换成one-hot标签表示

机器学习One-Hot编码

分类数据集的 One-hot 编码:如何处理分类数据中的不同值(数量较少)

one-hot编码(pytorch实现)