2013-11-20 9 views
11

回帰木(またはランダムフォレスト回帰)でカテゴリインパクトを使用しようとしていますが、sklearnはエラーを返して数値入力を求めています。回帰木または無作為のフォレスト回帰器(カテゴリ入力あり)

import sklearn as sk 
MODEL = sk.ensemble.RandomForestRegressor(n_estimators=100) 
MODEL.fit([('a',1,2),('b',2,3),('a',3,2),('b',1,3)], [1,2.5,3,4]) # does not work 
MODEL.fit([(1,1,2),(2,2,3),(1,3,2),(2,1,3)], [1,2.5,3,4]) #works 

MODEL = sk.tree.DecisionTreeRegressor() 
MODEL.fit([('a',1,2),('b',2,3),('a',3,2),('b',1,3)], [1,2.5,3,4]) # does not work 
MODEL.fit([(1,1,2),(2,2,3),(1,3,2),(2,1,3)], [1,2.5,3,4]) #works 

私の理解では、これらの方法では、どのような変換(例えばWOE置換)もせずにカテゴリ入力が可能でなければなりません。

誰にもこの問題がありましたか?

ありがとうございました!

答えて

16

scikit-learn(R要因別名)カテゴリ変数には、専用の表現を持っていない、一つの可能​​な解決策はLabelEncoderを使用してintとして文字列を符号化することである。

import numpy as np 
from sklearn.preprocessing import LabelEncoder 
from sklearn.ensemble import RandomForestRegressor 

X = np.asarray([('a',1,2),('b',2,3),('a',3,2),('c',1,3)]) 
y = np.asarray([1,2.5,3,4]) 

# transform 1st column to numbers 
X[:, 0] = LabelEncoder().fit_transform(X[:,0]) 

regressor = RandomForestRegressor(n_estimators=150, min_samples_split=2) 
regressor.fit(X, y) 
print(X) 
print(regressor.predict(X)) 

出力:

[[ 0. 1. 2.] 
[ 1. 2. 3.] 
[ 0. 3. 2.] 
[ 2. 1. 3.]] 
[ 1.61333333 2.13666667 2.53333333 2.95333333] 

しかし、覚えていますabが独立したカテゴリであり、ツリーベースの見積もりでのみ動作する場合、これはわずかなハックです。どうして? bは実際にaより大きくないためです。正しい方法は、またはpd.get_dummiesの後にを使用して、X[:, 0]の2つの別々の1ホットコード化列を生成することです。

import numpy as np 
from sklearn.preprocessing import LabelEncoder, OneHotEncoder 
from sklearn.ensemble import RandomForestRegressor 

X = np.asarray([('a',1,2),('b',2,3),('a',3,2),('c',1,3)]) 
y = np.asarray([1,2.5,3,4]) 

# transform 1st column to numbers 
import pandas as pd 
X_0 = pd.get_dummies(X[:, 0]).values 
X = np.column_stack([X_0, X[:, 1:]]) 

regressor = RandomForestRegressor(n_estimators=150, min_samples_split=2) 
regressor.fit(X, y) 
print(X) 
print(regressor.predict(X)) 
+1

ありがとうございます。私はそれが問題を解決するとは思わない。 「数値ラベル」は、あなたが予測しようとしているものに真実でない可能性が高い線形進行の仮定を作成します。決定木ノードを想像し、例えば '<2 and > = 2'を使用して次のカットオフスプリットを決定するときは、「if( 'a'、 'c')」と同じ意味を持ちません。 – jpsfer

+0

質問が間違っています。私はちょうどあなたがすべてをカテゴリー的なものとして扱いたいと思っていました。私はそれに応じて例を更新します... – Matt

+0

多くのありがとうマット! – jpsfer

1

Pythonで手作業でダミーコードを作成する必要があります。 1つのホットエンコーディングにはpandas.get_dummies()を使用することをお勧めします。ブーストされたツリーの場合、私はfactorize()を使用して序数エンコーディングを達成しました。

hereのこの種のパッケージ全体もあります。

さらに詳しい説明は、this Data Science Stack Exchangeポストを参照してください。