Горячее кодирование в трусиках
Для регрессий я обычно кодирую категориальные переменные, используя склеарны OneHotEncoder
,
Сейчас я изучаю использование patsy, но он не предлагает кодирование One-hot: http://patsy.readthedocs.io/en/latest/categorical-coding.html
Можно ли указать One-hot кодирование с помощью patsy?
2 ответа
Здесь есть две вещи, которые могут быть полезны: (1) patsy по умолчанию включает в себя перехват (есть невидимое 1 +
в начале каждой формулы) и (2) при кодировании категориального значения, patsy автоматически выбирает стратегию кодирования, которая позволяет избежать создания сверхпараметризованной модели.
Если вы комбинируете кодирование с перехватом + полное ранговое однократное кодирование, тогда вы получаете сверхпараметрическую модель. Таким образом, Пэтси переключается на кодирование лечения (= в основном отбрасывает один столбец из одного горячего кодирования, о котором вы думаете). Это позволяет избежать создания линейной зависимости между столбцами кодирования и столбцом перехвата.
Самый простой способ избежать этого - удалить перехват - тогда Пэтси не будет беспокоиться о линейной зависимости и будет использовать тот тип кодирования, который вы ожидаете: y ~ -1 + a
(-1
отменяет невидимое 1
убрать перехват).
В качестве альтернативы, если вам действительно нужна сверхпараметризованная модель, то, если вы прокрутите страницу вниз на странице документов, на которую вы ссылаетесь, она расскажет вам, как определить произвольные пользовательские схемы кодирования.
import numpy as np
from patsy import ContrastMatrix
class FullRankoneHot(object):
def __init__(self, reference=0):
self.reference = reference
# Called to generate a full-rank encoding
def code_with_intercept(self, levels):
return ContrastMatrix(np.eye(len(levels)),
["[My.%s]" % (level,) for level in levels])
# Called to generate a non-full-rank encoding. But we don't care,
# we do what we want, and return a full-rank encoding anyway.
# Take that, patsy.
def code_without_intercept(self, levels):
return self.code_with_intercept(levels)
Тогда вы можете использовать его как: y ~ 1 + C(a, FullRankOneHot)
,
Первый пример в приведенной вами ссылке - это горячая кодировка:
In [3]: data
Out[3]: {'a': ['a1', 'a2', 'a3', 'a1', 'a2', 'a3']}
In [4]: dmatrix("a", data)
Out[4]:
DesignMatrix with shape (6, 3)
Intercept a[T.a2] a[T.a3]
1 0 0
1 1 0
1 0 1
1 0 0
1 1 0
1 0 1
Terms:
'Intercept' (column 0)
'a' (columns 1:3)
Обратите внимание, что для кодирования категориальной переменной с тремя уровнями вам понадобятся только две двоичные переменные. Кодировка в этой документации лечит a1
в качестве базы и добавив еще две двоичные переменные для a2
а также a3
, Если оба a2
а также a3
0, то это означает, что значение a1
,
В склеарне OneHotEncoder
или панд pd.get_dummies()
они возвращают матрицу с тем же числом столбцов, что и уровни ваших категориальных переменных, но которая содержит один дополнительный столбец, поскольку вы можете представить значение одного из столбцов со значениями в других столбцах.