Как оставить числовые столбцы при использовании sklearn OneHotEncoder? - PullRequest
2 голосов
/ 22 марта 2020

Среда:

import pandas as pd
from sklearn.pipeline import Pipeline
from sklearn.preprocessing import OneHotEncoder, StandardScaler
from sklearn.ensemble import RandomForestClassifier

Пример данных:

X_train = pd.DataFrame({'A': ['a1', 'a3', 'a2'], 
                        'B': ['b2', 'b1', 'b3'],
                        'C': [1, 2, 3]})
y_train = pd.DataFrame({'Y': [1,0,1]})

Желаемый результат: Я бы хотел чтобы включить sklearn OneHotEncoder в мой конвейер в следующем формате:

encoder = ### SOME CODE ###
scaler = StandardScaler()
model = RandomForestClassifier(random_state=0)

# This is my ideal pipeline
pipe = Pipeline([('OneHotEncoder', encoder),
                 ('Scaler', scaler),
                 ('Classifier', model)])
pipe.fit(X_train, y_train)

Challenge : OneHotEncoder кодирует все, включая числовые столбцы. Я хочу сохранить числовые столбцы как есть и эффективно кодировать только категориальные функции, совместимые с Pipeline ().

encoder = OneHotEncoder(drop='first', sparse=False) 
encoder.fit(X_train)
encoder.transform(X_train) # Columns C is encoded - this is what I want to avoid

Обойти (не идеально) : я могу получить вокруг проблемы, используя pd.get_dummies(). Однако это означает, что я не могу включить его в свой конвейер. Или есть способ?

X_train = pd.get_dummies(X_train, drop_first=True)

Ответы [ 2 ]

1 голос
/ 22 марта 2020

Что я хотел бы сделать, это создать свой собственный преобразователь и поместить его в конвейер. Таким образом, у вас будет много власти над данными в вашей руке. Итак, шаги, как показано ниже:

1) Создайте пользовательский класс преобразователя, наследующий BaseEstimator и TransformerMixin . В его функции transform() попытайтесь определить значения этого столбца как числовые, так и категориальные. Если вы не хотите иметь дело с логикой c прямо сейчас, вы всегда можете присвоить имя столбца для категориальных столбцов функции transform(), которую нужно выбрать на лету.

2) ( Необязательно ) Создайте собственный преобразователь для обработки столбцов только с категориальными значениями.

3) ( Необязательно ) Создайте собственный преобразователь для обработки столбцов только с числовыми значениями.

4) Создайте два конвейера (один для категориального, другой для числового), используя созданные вами трансформаторы, и вы также можете использовать существующие из sklearn.

5) Объединить два конвейера с FeatureUnion .

6) Объедините свой большой трубопровод с моделью ML.

7) Звоните fit_transform()

Пример кода (дополнительные опции не реализованы): GitHub Jupyter Noteboook

0 голосов
/ 22 марта 2020

Мое предпочтительное решение для этого было бы использовать ColumnTransformer от sklearn (см. здесь ).

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

import pandas as pd
import numpy as np
from sklearn.compose import ColumnTransformer
from sklearn.preprocessing import OneHotEncoder, StandardScaler
from sklearn.pipeline import Pipeline
from sklearn.ensemble import RandomForestClassifier

X = pd.DataFrame({"a":[1,2,3],"b":["A","A","B"]})
y = np.array([0,1,1])

OHE = OneHotEncoder()
scaler = StandardScaler()
RFC = RandomForestClassifier()

cat_cols = ["b"]
num_cols = ["a"]

transformer = ColumnTransformer([('cat_cols', OHE, cat_cols),
                                ('num_cols', scaler, num_cols)])

pipe = Pipeline([("preprocessing", transformer),
                ("classifier", RFC)])
pipe.fit(X,y)

Примечание: я взял лицензию с вашим запросом, потому что это применяет скалер только к числовым данным, что, на мой взгляд, имеет больше смысла? Если вы хотите применить масштабатор ко всем столбцам, вы также можете сделать это, изменив этот пример.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...