LabelEncoder与sklearn,transform和值之间的反向单一关系?

时间:2017-08-25 11:01:05

标签: python pandas encoding scikit-learn decision-tree

您好,并提前感谢您的任何提示或建议。

我在Python 3.6中使用sklearn和DecisionTree Classifier。我使用标签编码器,因为我的Pandas Dataframe有4列,有些是字符串。

      Origin Duration   Origin Octave  Origin Pitch   Next Pitch
0          quarter           3          B                    G   
1          quarter           4          D                    D   
2          quarter           4          A                    D   
3             16th           4          A                    D 

在将数据帧分成训练和测试集之前,我使用标签编码和dict来进行对话(我在StackOverflow中阅读了这篇文章,感谢Jon!)。生成的编码数据框如下所示:

from collections import defaultdict

d = defaultdict(preprocessing.LabelEncoder)
encoded = scoredf.apply(lambda x: d[x.name].fit_transform(x))


      Origin Duration   Origin Octave  Origin Pitch   Next Pitch
0                 5            1           1                0                
1                 5            2           2                4                 
2                 5            2           0                4                 
3                 0            2           0                4                 

在训练和测试决策树分类器之后,我想为模型传递另一个数据帧,以获得预测。 例如,我想将以下DataFrame XX传递给我的模型,以获得预测:

print(XX)
Origin Duration Origin Octave Origin Pitch
0            zero             5            G

我使用相同的dict(d = defaultdict(preprocessing.LabelEncoder)),用于原始Dataframe的Labelenconding,我只使用" transform" ,因为我认为一切是"适合":

XXX = XX.apply(lambda x: d[x.name].transform(x))

然而,结果在编码方面是无关紧要的。我看到它被编码为:

    print(XXX)
           Origin Duration  Origin Octave  Origin Pitch
    0                6              3            10

但是,在对用于训练和测试模型的原始数据帧进行编码之后,结果数据框应为:

            Origin Duration  Origin Octave  Origin Pitch
0                6              3            6

所以问题是,当我实际使用模型进行预测时,如何保持我用于训练和测试模型的相同且一致的LabelEnconding, 这是:如何使用与用于训练和测试模型的标签相同的标签对输入数据帧进行编码以获得预测?

谢谢!

1 个答案:

答案 0 :(得分:0)

我猜您可以将原始标签存储在字典中,并将其用于进一步标记。

这是一个将未标记的df称为'df_orig'并将标记的df称为'df_label'的示例。标记数据帧后,您可以构建字典。

map_dict = dict()

# First level keys are columns names
keys_lvl1 = df_orig.columns

# As values for each column,
# I store a new dictionary corresponding to the labeling 
for k in keys_lvl1:
   keys = df_orig[k]
   values = df_label[k]
   sub_dict = dict(zip(keys, values))
   map_dict[k] = sub_dict 

稍后,您可以将其应用于

# just a copy of the original df for testing purpose
df_label2 = df_orig.copy()

for column in df_label2.columns:
    df_label2[column] = df_label2[column].apply(lambda x: map_dict[column][x])

修改

此代码实际上使用带有python 2.7的LabelEncoder生成一致的结果。这可能有助于您找到问题所在。

import pandas as pd
from StringIO import StringIO
from sklearn import preprocessing
from collections import defaultdict

# Reproducing your dataframe
data = StringIO("""
0    quarter    3    B    G   
1    quarter    4    D    D   
2    quarter    4    A    D   
3    16th     4    A    D
""")

columns = ['col_{}'.format(i) for i in range(4)]
df = pd.read_csv(data, delim_whitespace=True, index_col = 0, header=None )
df.columns = columns

print df

返回

         col_0  col_1 col_2 col_3
0                            
0  quarter      3     B     G
1  quarter      4     D     D
2  quarter      4     A     D
3     16th      4     A     D

然后,

# Label encoding
d = defaultdict(preprocessing.LabelEncoder)
df_label = df.apply(lambda x: d[x.name].fit_transform(x))
print df_label

返回

       col_0  col_1  col_2  col_3
0                            
0      1      0      1      1
1      1      1      2      0
2      1      1      0      0
3      0      1      0      0

对于预测集,我将数据帧混乱并删除第3列

# Apply to new data
df2 = df.sample(frac=1).drop('col_3', axis=1) # sample(frac=1) shuffles the df
print df2

返回

     col_0  col_1 col_2
 0                      
 3     16th      4     A
 1  quarter      4     D
 0  quarter      3     B
 2  quarter      4     A

然后,

df2_label = df2.apply(lambda x: d[x.name].transform(x))
print df2_label

返回

   col_0  col_1  col_2
0                     
3      0      1      0
1      1      1      2
0      1      0      1
2      1      1      0

似乎一致。