Обработка кодирования, преобразования и оценки меток в одном объекте - PullRequest
0 голосов
/ 13 сентября 2018

Похоже: Конвейер не работает с Label Encoder

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

. Я пытался использовать конвейер следующим образом:

import numpy as np
from sklearn.preprocessing import StandardScaler
from sklearn.pipeline import Pipeline
from sklearn.preprocessing import LabelEncoder

# mock training dataset
X = np.random.rand(1000, 100)
y = np.concatenate([["label1"] * 300, ["label2"] * 300, ["label3"] * 400])

le = LabelEncoder()
ss = StandardScaler()
clf = MyClassifier()
pl = Pipeline([('encoder', le),
               ('scaler', ss),
               ('clf', clf)])
pl.fit(X, y)

, который дает:

File "sklearn/pipeline.py", line 581, in _fit_transform_one
    res = transformer.fit_transform(X, y, **fit_params)
TypeError: fit_transform() takes exactly 2 arguments (3 given)

Пояснения:

  • X и y - мой набор данных для обучения, X - значения, а y - целевые метки.

  • X представляет собой numpy.ndarray формы (n_sample, n_features) и типа float, значения в диапазоне от 0 до 1.

  • y - это numpy.ndarray формы (n_sample,) и типа string

  • Я ожидаю, что LabelEncoder закодирует y, а не X.

  • Мне нужно y только для MyClassifier, и мне нужно, чтобы оно кодировалось в целые числа для MyClassifier для работы.

Посленекоторые мысли и, столкнувшись с ошибкой выше, я чувствую, что было бы наивно думать, что Pipeline справится с этим.Я понял, что Pipeline вполне может справиться с моим преобразованием и классификатором вместе, но это была часть кодирования меток, которая потерпит неудачу.

Как правильно достичь того, чего я хочу?Под правильным я подразумеваю сделать что-то, что позволило бы многократное использование и некоторую согласованность с sklearn.Есть ли в библиотеке sklearn класс, который делает то, что я хочу?

Я очень удивлен, что не нашел ответа в Интернете, потому что я чувствую, что то, что я делаю, не является чем-то необычным.Я мог бы что-то здесь упустить.

Ответы [ 3 ]

0 голосов
/ 22 октября 2018

Я считаю, что это невозможно.

Во-первых, все преобразователи наследуются от sklearn.base.TransformerMixin . Метод fit_transform принимает X и, необязательно, y аргументы, но возвращает только X_new. scikit-learn не предназначен для такого преобразования.

Во-вторых, LabelEncoder потерпит неудачу в конвейере, потому что fit и transform принимают только один аргумент, y, а не X, y.

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

0 голосов
/ 23 октября 2018

Как писал Вивек Кумар в комментариях:

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

Итак, вот решение моей проблемы:

import numpy as np
from sklearn.preprocessing import StandardScaler
from sklearn.pipeline import Pipeline

# mock training dataset
X = np.random.rand(1000, 100)
y = np.concatenate([["label1"] * 300, ["label2"] * 300, ["label3"] * 400])

ss = StandardScaler()
clf = MyClassifier()  # my own classifier
pl = Pipeline([('scaler', ss),
               ('clf', clf)])
pl.fit(X, y)

Единственная разница, теперь pl.predict(X) будет возвращать массив строк, содержащих значения "label1", "label2" или "label3" (что имеет смысл, поскольку это то, чем мы его кормили).

При необходимости, чтобы вернуть LabelEncoder, который автоматически используется sklearn.pipeline, вы можете сделать:

from sklearn.preprocessing import LabelEncoder
le = LabelEncoder(pl.classes_)

Что даст мне копию кодировщика меток, используемого конвейером pl.

0 голосов
/ 13 сентября 2018

Я реализовал категориальное кодирование с помощью панд, а в качестве классификатора я использовал SGDClassifier.Ваш код выше вызывает MyClassifier(), но он не определен внутри самого кода.

import numpy as np
import pandas as pd
# from sklearn.preprocessing import LabelEncoder # No longer used
from sklearn.preprocessing import StandardScaler
from sklearn.pipeline import Pipeline
from sklearn.linear_model import SGDClassifier

X = np.random.randn(1000, 10)

y_initial = np.concatenate([["label1"] * 300, ["label2"] * 300, ["label3"] * 400])

df = pd.DataFrame({'y':y_initial})
df['y'] = df['y'].astype('category') # Same as the output of LabelEncoder

ss = StandardScaler()
clf = SGDClassifier()

y = df['y']

pl = Pipeline([('scaler', ss),
               ('clf', clf)])

pl.fit(X,y)

Выходными данными является объект подходящего конвейера:

Pipeline(memory=None,
     steps=[('scaler', StandardScaler(copy=True, with_mean=True, with_std=True)), ('clf', SGDClassifier(alpha=0.0001, average=False, class_weight=None, epsilon=0.1,
       eta0=0.0, fit_intercept=True, l1_ratio=0.15,
       learning_rate='optimal', loss='hinge', max_iter=None, n_iter=None,
       n_jobs=1, penalty='l2', power_t=0.5, random_state=None,
       shuffle=True, tol=None, verbose=0, warm_start=False))])
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...