Может ли sklearn DecisionTreeClassifier действительно работать с категориальными данными?

Работая с DecisionTreeClassifier, я визуализировал его с помощью graphviz, и, к моему удивлению, кажется, что он принимает категориальные данные и использует их как непрерывные данные.

Все мои функции являются категориальными, и, например, вы можете увидеть следующее дерево (обратите внимание, что первая функция, X[0], имеет 6 возможных значений 0, 1, 2, 3, 4, 5: Из того, что я нашел здесь, класс использует класс дерева, который является двоичным деревом, так что это ограничение в sklearn.

Кто-нибудь знает способ, которым мне не хватает использовать дерево категорически? (Я знаю, что это не лучше для задачи, но так как мне нужны категории, в настоящее время я использую один горячий вектор на данных).

РЕДАКТИРОВАТЬ: образец исходных данных выглядит следующим образом:

f1 f2 f3  f4  f5  f6  f7  f8  f9  f10  c1  c2  c3
0  C  S  O   1   2   1   1   2   1    2   0   0   0
1  D  S  O   1   3   1   1   2   1    2   0   0   0
2  C  S  O   1   3   1   1   2   1    1   0   0   0
3  D  S  O   1   3   1   1   2   1    2   0   0   0
4  D  A  O   1   3   1   1   2   1    2   0   0   0
5  D  A  O   1   2   1   1   2   1    2   0   0   0
6  D  A  O   1   2   1   1   2   1    1   0   0   0
7  D  A  O   1   2   1   1   2   1    2   0   0   0
8  D  K  O   1   3   1   1   2   1    2   0   0   0
9  C  R  O   1   3   1   1   2   1    1   0   0   0

где X[0] = f1 и я закодировал строки в целые числа, так как sklearn не принимает строки.

2 ответа

Решение

Что ж, я удивлен, но оказывается, что дерево решений sklearn не может действительно обрабатывать категориальные данные. Существует проблема Github по этому вопросу ( # 4899) с июня 2015 года, но она все еще открыта (и я предлагаю вам быстро взглянуть на ветку, так как некоторые комментарии очень интересны).

Проблема с кодированием категориальных переменных в виде целых чисел, как вы сделали здесь, заключается в том, что это накладывает на них порядок, который может иметь или не иметь смысла, в зависимости от случая; например, вы могли бы закодировать ['low', 'medium', 'high'] как [0, 1, 2], поскольку 'low' < 'medium' < 'high' (мы называем эти категориальные переменные порядковыми), хотя вы все еще неявно делаете дополнительное (и, возможно, нежелательное) предположение о том, что расстояние между 'low' а также 'medium' то же самое с расстоянием между 'medium' а также 'high' (не влияет на деревья решений, но важен, например, для k-nn и кластеризации). Но этот подход полностью терпит неудачу в таких случаях, как, например, ['red','green','blue'] или же ['male','female'], поскольку мы не можем претендовать на какой-либо значимый относительный порядок между ними.

Таким образом, для неординарных категориальных переменных способ их правильного кодирования для использования в дереве решений sklearn заключается в использовании OneHotEncoder модуль. Раздел кодирования категориальных функций руководства пользователя также может быть полезен.

Начиная с v0.24.0, scikit поддерживает использование категориальных функций внутри и изначально ! Из Руководства пользователя :

<tcode id="4176381"></tcode> и <tcode id="4176382"></tcode> имеют встроенную поддержку категориальных функций: они могут рассматривать разбиение неупорядоченных категориальных данных.

Для наборов данных с категориальными функциями использование встроенной категориальной поддержки часто лучше, чем полагаться на одноразовое кодирование ( <tcode id="4176385"></tcode>), поскольку однократное кодирование требует большей глубины дерева для достижения эквивалентных разделений. Также обычно лучше полагаться на собственную категориальную поддержку, чем рассматривать категориальные особенности как непрерывные (порядковые), как это происходит для категориальных данных с порядковым кодированием, поскольку категории являются номинальными величинами, где порядок не имеет значения.

Чтобы включить поддержку категорий, можно передать логическую маску в параметр category_features, указывающий, какая функция является категориальной. В дальнейшем первый признак будет рассматриваться как категориальный, а второй признак - как числовой:

       >>> gbdt = HistGradientBoostingClassifier(categorical_features=[True, False])

Точно так же можно передать список целых чисел, указывающих индексы категориальных признаков:

       >>> gbdt = HistGradientBoostingClassifier(categorical_features=[0])

Вам все равно нужно кодировать ваши строки, иначе вы получите ошибку «не удалось преобразовать строку в число с плавающей запятой». См. Здесь пример использования OrdinalEncoder для преобразования строк в целые числа.

Другие вопросы по тегам