在 scikit-learn 中进行一种热编码的可能方法?

Posted

技术标签:

【中文标题】在 scikit-learn 中进行一种热编码的可能方法?【英文标题】:Possible ways to do one hot encoding in scikit-learn? 【发布时间】:2016-03-14 05:31:54 【问题描述】:

我有一个带有一些分类列的 pandas 数据框。其中一些包含非整数值。

我目前想对这些数据应用多个机器学习模型。对于某些模型,有必要进行归一化以获得更好的结果。例如,将分类变量转换为虚拟/指标变量。实际上,pandas 有一个名为 get_dummies 的函数用于此目的。但是,此函数根据数据返回结果。因此,如果我在训练数据上调用 get_dummies,然后在测试数据上再次调用它,在两种情况下实现的列可能会有所不同,因为测试数据中的分类列与训练数据。

因此,我正在寻找其他方法来进行 one-hot 编码。

在 python (pandas/sklearn) 中进行一种热编码的可能方法是什么?

【问题讨论】:

在分类数据可能发生变化的训练和测试数据之间总会遇到这个问题。 好吧,如果您在测试(和真实)数据中的值与训练数据不同,那么当遇到未知数据时,您的模型无论如何都不会好...您的测试数据集必须有一个实例至少最终数据将拥有的所有内容。据我所知,机器学习并不神奇! 如果你有真正的班级平衡并检查它是否存在——你正在进入测试集。 【参考方案1】:

Scikit-learn 提供了一个编码器sklearn.preprocessing.LabelBinarizer

对于编码训练数据,您可以使用 fit_transform 来发现类别标签并创建适当的虚拟变量。

label_binarizer = sklearn.preprocessing.LabelBinarizer()
training_mat = label_binarizer.fit_transform(df.Label)

对于测试数据,您可以通过变换使用同一组类别。

test_mat = label_binarizer.transform(test_df.Label)

【讨论】:

感谢您的建议。对此进行调查后,发现 LabelBinarizer 用于类标签,而不是特征。 实际上,它适用于任何一个。只要它是一列包含文本标签(或文本分类特征)的数据,它就会创建一个热编码的矩阵。我经常将它用于功能,然后使用np.hstack() 将其与其他功能结合起来。 是的。这也是解决我问题的一种方法。谢谢你的解释。【参考方案2】:

过去,我发现处理此问题的最简单方法是使用get_dummies,然后强制列在测试和训练之间匹配。例如,您可能会执行以下操作:

import pandas as pd

train = pd.get_dummies(train_df)
test = pd.get_dummies(test_df)

# get the columns in train that are not in test
col_to_add = np.setdiff1d(train.columns, test.columns)

# add these columns to test, setting them equal to zero
for c in col_to_add:
    test[c] = 0

# select and reorder the test columns using the train columns
test = test[train.columns]

这将丢弃有关您在训练集中未见过的标签的信息,但会强制保持一致性。如果您正在使用这些拆分进行交叉验证,我建议您做两件事。首先,对整个数据集执行get_dummies 以获取所有列(而不是像上面代码中那样仅在训练集上)。其次,使用StratifiedKFold 进行交叉验证,以便您的拆分包含相关标签。

【讨论】:

应该是:train = pd.get_dummies(train_df) test = pd.get_dummies(test_df)【参考方案3】:

比如说,我有一个特征“A”,可能值为“a”、“b”、“c”、“d”。但是训练数据集只包含三个类别“a”、“b”、“c”作为值。如果在此阶段使用get_dummies,则生成的特征将是三个(A_a、A_b、A_c)。但理想情况下,还应该有另一个特征 A_d 以及全零。这可以通过以下方式实现:

import pandas as pd
data = pd.DataFrame("A" : ["a", "b", "c"])
data["A"] = data["A"].astype("category", categories=["a", "b", "c", "d"])
mod_data = pd.get_dummies(data[["A"]])
print(mod_data)

输出是

   A_a  A_b  A_c  A_d
0  1.0  0.0  0.0  0.0
1  0.0  1.0  0.0  0.0
2  0.0  0.0  1.0  0.0

【讨论】:

【参考方案4】:

对于文本列,你可以试试这个

from sklearn.feature_extraction.text import CountVectorizer

data = ['he is good','he is bad','he is strong']
vectorizer = CountVectorizer()
vectors = vectorizer.fit_transform(data)

输出:

for i in range(len(data)):
    print(vectors[i, :].toarray())

输出:

[[0 1 1 1 0]]
[[1 0 1 1 0]]
[[0 0 1 1 1]]

【讨论】:

以上是关于在 scikit-learn 中进行一种热编码的可能方法?的主要内容,如果未能解决你的问题,请参考以下文章

如何对变体长度特征进行一种热编码?

一种热编码保留用于插补的 NA

一种热编码分类特征 - 仅稀疏形式

如何使用 Python 和 Scikit 进行线性回归学习使用一种热编码?

一种热编码标签和分层 K 折交叉验证

keras中多标签图像的一种热编码