Деревья регрессии или регресстор случайного леса с категориальными входами

Я пытаюсь использовать категориальную inpust в дереве регрессии (или Random Forest Regressor), но 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).

У кого-нибудь еще было это затруднение?

спасибо!

Ответ 1

scikit-learn не имеет специального представления для категориальных переменных (коэффициенты a.k.a в R), одним из возможных решений является кодирование строк как int с помощью LabelEncoder:

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]

Но помните, что это небольшой взлом, если a и b являются независимыми категориями и работают только с древовидными оценками. Зачем? Потому что b не больше, чем a. Правильным способом было бы использовать OneHotEncoder после LabelEncoder или pd.get_dummies, давая два отдельных столбца с одним горячим кодированием для X[:, 0].

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

Ответ 2

Вы должны фиктивный код вручную в python. Я бы предложил использовать pandas.get_dummies() для одного горячего кодирования. Для Boosted trees у меня был успех, используя factorize(), чтобы достичь ординального кодирования.

Существует также целый пакет для такого рода здесь.

Более подробное объяснение можно найти в этом Опубликован почтовый обмен данными.