如何在训练/验证/测试中对齐 pandas get_dummies?

How can I align pandas get_dummies across training / validation / testing?

我有 3 组数据(训练、验证和测试),当我 运行:

    training_x = pd.get_dummies(training_x, columns=['a', 'b', 'c'])

它给了我一定数量的功能。但是当我 运行 它跨越验证数据时,它给了我一个不同的数字和相同的测试。有没有什么方法可以对所有数据集进行标准化(我知道是错误的词),从而使特征数量保持一致?

您可以将需要转换为虚拟变量的列的数据类型转换为category

df.col_1=df.col_1.astype('category')
df1=df.iloc[:1,:].copy()
df2=df.drop(df1.index)
pd.get_dummies(df1,columns=['col_1'])
Out[701]: 
      col_2 col3  col_1_A  col_1_D  col_1_G  col_1_J
index                                               
0         B    C        1        0        0        0# it will show zero even missing in the sub-set
pd.get_dummies(df2,columns=['col_1'])
Out[702]: 
      col_2 col3  col_1_A  col_1_D  col_1_G  col_1_J
index                                               
1         E    F        0        1        0        0
2         H    I        0        0        1        0
3         K    L        0        0        0        1

在将数据集划分为训练、测试或验证之前应创建假人

假设我有如下训练和测试数据框

import pandas as pd  
train = pd.DataFrame([1,2,3], columns= ['A'])
test= pd.DataFrame([7,8], columns= ['A'])

#creating dummy for train 
pd.get_dummies(train, columns= ['A'])

o/p
   A_1  A_2  A_3  A_4  A_5  A_6
0    1    0    0    0    0    0
1    0    1    0    0    0    0
2    0    0    1    0    0    0
3    0    0    0    1    0    0
4    0    0    0    0    1    0
5    0    0    0    0    0    1



# creating dummies for test data
pd.get_dummies(test, columns = ['A'])
    A_7  A_8
0    1    0
1    0    1

所以 7 和 8 类别的虚拟对象只会出现在测试中,因此会产生不同的特征

final_df = pd.concat([train, test]) 

dummy_created = pd.get_dummies(final_df)

# now you can split it into train and test 
from sklearn.model_selection import train_test_split
train_x, test_x = train_test_split(dummy_created, test_size=0.33)

现在训练和测试将具有相同的特征集

如前所述,通常您应该在拆分前进行一次热编码。 但是还有一个问题。有一天,您肯定想将经过训练的 ML 模型应用到自然环境中的数据。我的意思是数据,你以前没有见过,你需要对假人进行完全相同的转换,就像你训练模型时一样。 那么你可能不得不处理两种情况。

  1. 是,新数据包含您的训练数据中没有的类别,并且
  2. 相反,一个类别不再出现在你的数据集中,但你的模型已经用它训练过。 在情况 1 中,您应该忽略该值,因为您的模型很可能无法处理它,而不是对其进行训练。在情况 2 中,您仍然应该生成这些空类别,以便在您要预测的数据中具有与训练集中相同的结构。请注意,pandas 方法不会为这些类别生成虚拟变量,因此不能保证您从预测数据中获得与训练数据相同的结构,因此您的模型很可能不适用于数据。

您可以使用相当于 get_dummies 的 sklearn 来解决这个问题(只需多做一点工作),它看起来像这样:

import pandas as pd
from sklearn.preprocessing import OneHotEncoder

# create some example data
df= pd.DataFrame({'x': [1, 2, 3], 'y': [2, 4, 8]})

# create a one hot encoder to create the dummies and fit it to the data
ohe= OneHotEncoder(handle_unknown='ignore', sparse=False)
ohe.fit(df[['x']])

# now let's simulate the two situations A and B
df.loc[1, 'x']= 1
df= df.append(dict(x=5, y=5), ignore_index=True)

# the actual feature generation is done in a separate step
tr=ohe.transform(df[['x']])

# if you need the columns in your existing data frame, you can glue them together
df2=pd.DataFrame(tr, columns=['oh1', 'oh2', 'oh3'], index=df.index)
result= pd.concat([df, df2], axis='columns')

借助 sklearn OneHotEncoder,您可以将类别的识别与实际 one-hot-encoding(虚拟对象的创建)分开。您还可以保存安装的一个热编码器,以便稍后在您的模型应用过程中应用它。注意 handle_unknown 选项,它告诉一个热编码器,如果它以后会遇到未知的东西,它应该忽略它,而不是引发错误。

一个简单的解决方案是在应用虚拟函数后将验证集和测试集与训练数据集对齐。方法如下:

# Pandas encoding the data, dummies function creates different feature for each dataset
train = pd.get_dummies(train)
valid = pd.get_dummies(valid)
test = pd.get_dummies(test)

# Align the number of features across validation and test sets based on train dataset
train, valid = train.align(valid, join='left', axis=1)
train, test = train.align(test, join='left', axis=1)

引用自 kaggle : Link

不要忘记添加 fill_value=0 以避免在测试中出现 NaN...