python 中二进制单热(K 中的一个)编码的问题
Problems with a binary one-hot (one-of-K) coding in python
二进制单热(也称为 one-of-K)编码在于为分类变量的每个不同值制作一个二进制列。例如,如果一个颜色列(分类变量)采用值 'red'、'blue'、'yellow' 和 'unknown',则二进制单热编码会替换带有二进制列 'color=red'、'color=blue' 和 'color=yellow' 的颜色列。我从 pandas 数据框中的数据开始,我想使用这些数据来训练带有 scikit-learn 的模型。我知道两种进行二进制单热编码的方法,none 令我满意。
Pandas 和 get_dummies 在数据框的分类列中。就原始数据框包含 all 可用数据而言,此方法似乎非常出色。也就是说,您在将数据拆分为训练、验证和测试集之前进行一次性编码。但是,如果数据已经拆分成不同的集合,则此方法效果不佳。为什么?因为其中一个数据集(比如测试集)可以包含更少的给定变量值。例如,训练集可能包含变量颜色的值红色、蓝色、黄色和未知,而测试集仅包含红色和蓝色。所以测试集最终会比训练集有更少的列。 (我不知道新列是如何排序的,即使有相同的列,每组中的顺序也可能不同)。
Sklearn 和 DictVectorizer 这解决了前面的问题,因为我们可以确保对测试集应用完全相同的转换。但是,转换的结果是一个 numpy 数组而不是 pandas 数据框。如果我们想将输出恢复为 pandas 数据帧,我们需要(或者至少这是我这样做的方式):1) pandas.DataFrame(data=DictVectorizer 转换的结果,索引=原始pandas数据框的索引,columns=DictVectorizer().get_features_names)和2)沿着索引连接结果数据框与包含数字列的原始数据框。这行得通,但有点麻烦。
如果我们在训练和测试集中对数据进行拆分,是否有更好的方法在 pandas 数据帧中进行二进制单热编码?
如果您的列顺序相同,您可以连接 dfs,使用 get_dummies
,然后再次拆分它们,例如,
encoded = pd.get_dummies(pd.concat([train,test], axis=0))
train_rows = train.shape[0]
train_encoded = encoded.iloc[:train_rows, :]
test_encoded = encoded.iloc[train_rows:, :]
如果您的列的顺序不同,那么无论您尝试什么方法都会遇到挑战。
您可以将数据类型设置为分类:
In [5]: df_train = pd.DataFrame({"car":Series(["seat","bmw"]).astype('category',categories=['seat','bmw','mercedes']),"color":["red","green"]})
In [6]: df_train
Out[6]:
car color
0 seat red
1 bmw green
In [7]: pd.get_dummies(df_train )
Out[7]:
car_seat car_bmw car_mercedes color_green color_red
0 1 0 0 0 1
1 0 1 0 1 0
参见 Pandas 的 this issue。
二进制单热(也称为 one-of-K)编码在于为分类变量的每个不同值制作一个二进制列。例如,如果一个颜色列(分类变量)采用值 'red'、'blue'、'yellow' 和 'unknown',则二进制单热编码会替换带有二进制列 'color=red'、'color=blue' 和 'color=yellow' 的颜色列。我从 pandas 数据框中的数据开始,我想使用这些数据来训练带有 scikit-learn 的模型。我知道两种进行二进制单热编码的方法,none 令我满意。
Pandas 和 get_dummies 在数据框的分类列中。就原始数据框包含 all 可用数据而言,此方法似乎非常出色。也就是说,您在将数据拆分为训练、验证和测试集之前进行一次性编码。但是,如果数据已经拆分成不同的集合,则此方法效果不佳。为什么?因为其中一个数据集(比如测试集)可以包含更少的给定变量值。例如,训练集可能包含变量颜色的值红色、蓝色、黄色和未知,而测试集仅包含红色和蓝色。所以测试集最终会比训练集有更少的列。 (我不知道新列是如何排序的,即使有相同的列,每组中的顺序也可能不同)。
Sklearn 和 DictVectorizer 这解决了前面的问题,因为我们可以确保对测试集应用完全相同的转换。但是,转换的结果是一个 numpy 数组而不是 pandas 数据框。如果我们想将输出恢复为 pandas 数据帧,我们需要(或者至少这是我这样做的方式):1) pandas.DataFrame(data=DictVectorizer 转换的结果,索引=原始pandas数据框的索引,columns=DictVectorizer().get_features_names)和2)沿着索引连接结果数据框与包含数字列的原始数据框。这行得通,但有点麻烦。
如果我们在训练和测试集中对数据进行拆分,是否有更好的方法在 pandas 数据帧中进行二进制单热编码?
如果您的列顺序相同,您可以连接 dfs,使用 get_dummies
,然后再次拆分它们,例如,
encoded = pd.get_dummies(pd.concat([train,test], axis=0))
train_rows = train.shape[0]
train_encoded = encoded.iloc[:train_rows, :]
test_encoded = encoded.iloc[train_rows:, :]
如果您的列的顺序不同,那么无论您尝试什么方法都会遇到挑战。
您可以将数据类型设置为分类:
In [5]: df_train = pd.DataFrame({"car":Series(["seat","bmw"]).astype('category',categories=['seat','bmw','mercedes']),"color":["red","green"]})
In [6]: df_train
Out[6]:
car color
0 seat red
1 bmw green
In [7]: pd.get_dummies(df_train )
Out[7]:
car_seat car_bmw car_mercedes color_green color_red
0 1 0 0 0 1
1 0 1 0 1 0
参见 Pandas 的 this issue。