scikit-learn: одна горячая кодировка строковых категориальных функций

Я пытаюсь выполнить горячее кодирование тривиального набора данных.

data = [['a', 'dog', 'red']
        ['b', 'cat', 'green']]

Каков наилучший способ предварительной обработки этих данных с помощью Scikit-Learn?

При первом инстинкте вы посмотрите на OneHotEncoder Scikit-Learn. Но один горячий кодировщик не поддерживает строки как функции; это только дискретизирует целые числа.

Тогда вы должны использовать LabelEncoder, который будет кодировать строки в целые числа. Но затем вы должны применить кодировщик меток к каждому из столбцов и сохранить каждый из этих кодировщиков меток (а также столбцы, к которым они были применены). И это кажется очень неуклюжим.

Итак, как лучше всего это сделать в Scikit-Learn?

Пожалуйста, не предлагайте pandas.get_dummies. Это то, что я обычно использую в настоящее время для одного горячего кодирования. Тем не менее, он ограничен в том, что вы не можете кодировать свой набор тренировок / тестов отдельно.

3 ответа

Для вашего сведения, это скоро будет в производстве в sklearn: см. https://github.com/scikit-learn/scikit-learn/pull/9151

In [30]: cat = CategoricalEncoder()

In [31]: X = np.array([['a', 'b', 'a', 'c'], [0, 1, 0, 1]], dtype=object).T

In [32]: cat.fit_transform(X).toarray()
Out[32]:
array([[ 1.,  0., 0.,  1.,  0.],
       [ 0.,  1.,  0.,  0.,  1.],
       [ 1.,  0.,  0.,  1.,  0.],
       [ 0.,  0.,  1.,  0.,  1.]])

Если вы установите ветку master, вы сможете это сделать.

Другой способ сделать это - использовать category_encoders.

Вот пример:

% pip install category_encoders
import category_encoders as ce
le =  ce.OneHotEncoder(return_df=False, impute_missing=False, handle_unknown="ignore")
X = np.array([['a', 'dog', 'red'], ['b', 'cat', 'green']])
le.fit_transform(X)
array([[1, 0, 1, 0, 1, 0],
       [0, 1, 0, 1, 0, 1]])

Изменить: он уже включен master ветка.
Изменить 2: Это в sklearn==0.20.dev0

Очень хороший вопрос

Однако, в некотором смысле, это частный случай чего-то, что встречается (по крайней мере, для меня) довольно часто - учитывая sklearn этапы, применимые к подмножествам X матрица, я хотел бы применить (возможно, несколько), учитывая всю матрицу. Здесь, например, у вас есть этап, который должен выполняться для одного столбца, и вы хотите применить его трижды - один раз для каждого столбца.

Это классический случай использования Composite Design Pattern.

Вот (эскиз) многоразового этапа, который принимает словарь, отображающий индекс столбца в преобразование, чтобы применить к нему:

class ColumnApplier(object):
    def __init__(self, column_stages):
        self._column_stages = column_stages

    def fit(self, X, y):
        for i, k in self._column_stages.items():
            k.fit(X[:, i])

        return self

    def transform(self, X):
        X = X.copy()
        for i, k in self._column_stages.items():
            X[:, i] = k.transform(X[:, i])

        return X

Теперь, чтобы использовать его в этом контексте, начиная с

X = np.array([['a', 'dog', 'red'], ['b', 'cat', 'green']])
y = np.array([1, 2])
X

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

multi_encoder = \
    ColumnApplier(dict([(i, preprocessing.LabelEncoder()) for i in range(3)]))
multi_encoder.fit(X, None).transform(X)

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

Я сталкивался с этой проблемой много раз и нашел решение в этой книге на его странице 100:

Мы можем применить оба преобразования (от текстовых категорий к целочисленным категориям, затем от целочисленных категорий к горячим векторам) в одном кадре, используя класс LabelBinarizer:

и пример кода здесь:

from sklearn.preprocessing import LabelBinarizer
encoder = LabelBinarizer()
housing_cat_1hot = encoder.fit_transform(data)
housing_cat_1hot

и как результат: обратите внимание, что по умолчанию возвращается массив NumPy. Вместо этого вы можете получить разреженную матрицу, передав sparse_output=True конструктору LabelBinarizer.

И вы можете узнать больше о LabelBinarizer, здесь, в официальной документации sklearn

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