Передача категориальных данных в Дерево решений Sklearn

Есть несколько сообщений о том, как кодировать категориальные данные в деревьях Decle Sklearn, но из документации Sklearn мы получили эти

Некоторые преимущества деревьев решений:

(...)

Возможность обработки как числовых, так и категориальных данных. Другие методы обычно специализируются на анализе наборов данных, которые имеют только один тип переменной. Дополнительные сведения см. В разделе "Алгоритмы".

Запустив script

import pandas as pd
from sklearn.tree import DecisionTreeClassifier

data = pd.DataFrame()
data['A'] = ['a','a','b','a']
data['B'] = ['b','b','a','b']
data['C'] = [0, 0, 1, 0]
data['Class'] = ['n','n','y','n']

tree = DecisionTreeClassifier()
tree.fit(data[['A','B','C']], data['Class'])

выводится следующая ошибка:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/local/lib/python2.7/site-packages/sklearn/tree/tree.py", line 154, in fit
    X = check_array(X, dtype=DTYPE, accept_sparse="csc")
  File "/usr/local/lib/python2.7/site-packages/sklearn/utils/validation.py", line 377, in check_array
    array = np.array(array, dtype=dtype, order=order, copy=copy)
ValueError: could not convert string to float: b

Я знаю, что в R можно передавать категориальные данные с помощью Sklearn, возможно ли это?

Ответы

Ответ 1

Вопреки принятому ответу, я бы предпочел использовать для этой цели инструменты, предоставляемые Scikit-Learn. Основная причина для этого заключается в том, что они могут быть легко интегрированы в конвейер.

Сам Scikit-Learn предоставляет очень хорошие классы для обработки категориальных данных. Вместо написания вашей пользовательской функции вы должны использовать LabelEncoder который специально разработан для этой цели.

Обратитесь к следующему коду из документации:

from sklearn import preprocessing
le = preprocessing.LabelEncoder()
le.fit(["paris", "paris", "tokyo", "amsterdam"])
le.transform(["tokyo", "tokyo", "paris"]) 

Это автоматически кодирует их в числа для ваших алгоритмов машинного обучения. Теперь это также поддерживает возврат к строкам из целых чисел. Вы можете сделать это, просто вызвав inverse_transform следующим образом:

list(le.inverse_transform([2, 2, 1]))

Это вернет ['tokyo', 'tokyo', 'paris'].

Также обратите внимание, что для многих других классификаторов, помимо деревьев решений, таких как логистическая регрессия или SVM, вы хотели бы кодировать свои категориальные переменные, используя кодирование One-Hot. Scikit-learn также поддерживает это с помощью класса OneHotEncoder.

Надеюсь это поможет!

Ответ 2

(Это всего лишь переформатирование моего комментария выше от 2016 года... оно все еще верно.)

Принятый ответ на этот вопрос вводит в заблуждение.

В настоящее время деревья решений sklearn не обрабатывают категориальные данные - см. Выпуск № 5442.

Рекомендуемый подход с использованием Label Encoding преобразует в целые числа, которые DecisionTreeClassifier() будет считать числовым. Если ваши категориальные данные не являются порядковыми, это нехорошо - вы получите расщепления, которые не имеют смысла.

Использование OneHotEncoder является единственным действующим способом, позволяющим произвольные разбиения, не зависящие от порядка меток, но требующие больших затрат в вычислительном отношении.

Ответ 3

(..)

Способен обрабатывать как числовые, так и категориальные данные.

Это только означает, что вы можете использовать

  • класс DecisionTreeClassifier для задач классификации
  • класс DecisionTreeRegressor для регрессии.

В любом случае вам нужно быстро кодировать категориальные переменные до того, как вы поместите дерево с помощью sklearn, например:

import pandas as pd
from sklearn.tree import DecisionTreeClassifier

data = pd.DataFrame()
data['A'] = ['a','a','b','a']
data['B'] = ['b','b','a','b']
data['C'] = [0, 0, 1, 0]
data['Class'] = ['n','n','y','n']

tree = DecisionTreeClassifier()

one_hot_data = pd.get_dummies(data[['A','B','C']],drop_first=True)
tree.fit(one_hot_data, data['Class'])

Ответ 4

Деревья решений Sklearn Деревья не обрабатывают преобразование категориальных строк в числа. Я предлагаю вам найти функцию в Sklearn (возможно this), которая делает это или вручную пишет какой-то код, например:

def cat2int(column):
    vals = list(set(column))
    for i, string in enumerate(column):
        column[i] = vals.index(string)
    return column