2017-08-25 170 views
1

你好,並提前感謝您的任何提示或建議。LabelEncoder與sklearn,transform和inverse之間的單值關係?

我在Python 3.6中使用sklearn和DecisionTree Classifier。我使用標籤編碼器,因爲我的熊貓數據框有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 

之前拆分數據幀進入到訓練和測試集,我用標籤編碼和字典來enconde它(提示,我讀到這裏在StackOverflow的,感謝喬恩!)。作爲結果的編碼數據幀的樣子:

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     

訓練後和測試決策樹分類,我想通過另一個數據框的模式,以獲得預測。 例如,我想將下列數據幀XX傳遞給我的模型,以獲得predicition:

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

我方式編碼它使用相同的字典(d = defaultdict(preprocessing.LabelEncoder)),Labelenconding用於原始數據框中,我只用「改造」我認爲一切都在「裝」:

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

但是結果是在編碼方面incosintents。我看到它被編碼象:

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

然而,下面的用於訓練和測試模型的原始數據幀的編碼,將得到的數據幀應該是:

  Origin Duration Origin Octave Origin Pitch 
0    6    3   6 

所以,問題是,如何保持相同和一致的LabelEnconding我用於培訓和測試模型,當我實際使用模型進行預測後, 這是:如何對輸入數據幀進行編碼以獲得預測,使用與用於訓練的標籤相同的標籤並測試模型?

謝謝!

回答

0

我想你可以存儲你的原始標籤,例如在字典中,並將其用於進一步標籤。

下面是一個將未標記的df作爲參數的例子,作爲標記的df作爲參數,並將其作爲標記的參數作爲參數標記。一旦你標記了你的數據框,你就可以建立字典。

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]) 

編輯

此代碼應用它實際產生使用LabelEncoder與Python 2.7一致的結果。這可能會幫助您找到問題所在。

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 

這似乎是一致的。

+0

尊敬的Delforge。非常感謝您花時間閱讀我的問題和答案。我認爲你的解決方案會起作用,因爲它基本上會跟蹤由LabelEnconder完成的標籤。我唯一擔心的是,這不是自動發生的,並且對於使用LabelEncoder Transform和Inverse_transform方法的用戶來說是透明的嗎?我的意思是,一旦「適合」轉換應該能夠透明地處理轉換,不是嗎? – MarkSpain

+0

奇怪的行爲確實。當我檢查LabelEncoder似乎工作正常。你確定你的測試集包含所有現有的分類值嗎?否則,您也可以在將訓練集,測試和預測集分開之前對其進行標記。 – Delforge

+0

嗨Deltaforge,再次感謝您的回答。實際上,這就是我的代碼所做的,它在調用「train_test_split」之前使用LabelEncoder進行調用。 – MarkSpain