Можно ли указать handle_unknown = 'ignore' для определенных столбцов и 'error' для других внутри OneHotEncoder? - PullRequest
4 голосов
/ 14 июня 2019

У меня есть фрейм данных со всеми категориальными столбцами, которые я кодирую, используя oneHotEncoder из sklearn.preprocessing. Мой код, как показано ниже:

from sklearn.preprocessing import OneHotEncoder
from sklearn.pipeline import Pipeline


steps = [('OneHotEncoder', OneHotEncoder(handle_unknown ='ignore')) ,('LReg', LinearRegression())]

pipeline = Pipeline(steps)

Как видно из OneHotEncoder, параметр handle_unknown принимает либо error, либо ignore. Я хочу знать, если есть способ выборочно игнорировать неизвестные категории для определенных столбцов, тогда как дать ошибку для других столбцов?

import pandas as pd

df = pd.DataFrame({'Country':['USA','USA','IND','UK','UK','UK'],
                   'Fruits':['Apple','Strawberry','Mango','Berries','Banana','Grape'],
                   'Flower':   ['Rose','Lily','Orchid','Petunia','Lotus','Dandelion'],
                   'Result':[1,2,3,4,5,6,]})

from sklearn.preprocessing import OneHotEncoder
from sklearn.linear_model import LinearRegression
from sklearn.pipeline import Pipeline

steps = [('OneHotEncoder', OneHotEncoder(handle_unknown ='ignore')) ,('LReg', LinearRegression())]

pipeline = Pipeline(steps)

from sklearn.model_selection import train_test_split

X = df[["Country","Flower","Fruits"]]
Y = df["Result"]
X_train, X_test, y_train, y_test = train_test_split(X,Y,test_size=0.3, random_state=30, shuffle =True)

print("X_train.shape:", X_train.shape)
print("y_train.shape:", y_train.shape)
print("X_test.shape:", X_test.shape)
print("y_test.shape:", y_test.shape)

pipeline.fit(X_train,y_train)

y_pred = pipeline.predict(X_test)

from sklearn.metrics import mean_squared_error
from sklearn.metrics import r2_score

#Mean Squared Error:
MSE = mean_squared_error(y_test,y_pred)

print("MSE", MSE)

#Root Mean Squared Error:
from math import sqrt

RMSE = sqrt(MSE)
print("RMSE", RMSE)

#R-squared score:
R2_score = r2_score(y_test,y_pred)

print("R2_score", R2_score)

В этом случае для всех столбцов, которые равны Country, Fruits и Flowers, если появляется новое значение, модель все равно сможет предсказать вывод.

Я хочу знать, есть ли способ игнорировать неизвестные категории для Fruits и Flowers, но, тем не менее, вызвать ошибку для неизвестного значения в столбце Country?

Ответы [ 2 ]

7 голосов
/ 18 июня 2019

Я думаю, ColumnTransformer() поможет вам решить проблему. Вы можете указать список столбцы, для которых вы хотите применить OneHotEncoder с ignore для handle_unknown и аналогично для error.

Преобразуйте ваш конвейер в следующее, используя ColumnTransformer

from sklearn.compose import ColumnTransformer

ct = ColumnTransformer([("ohe_ignore", OneHotEncoder(handle_unknown ='ignore'), 
                              ["Flower", "Fruits"]),
                        ("ohe_raise_error",  OneHotEncoder(handle_unknown ='error'),
                               ["Country"])])

steps = [('OneHotEncoder', ct),
         ('LReg', LinearRegression())]

pipeline = Pipeline(steps)

Теперь, когда мы хотим предсказать

>>> pipeline.predict(pd.DataFrame({'Country': ['UK'], 'Fruits': ['Apple'], 'Flower': ['Rose']}))

array([2.83333333])

>>> pipeline.predict(pd.DataFrame({'Country': ['UK'], 'Fruits': ['chk'], 'Flower': ['Rose']}))

array([3.66666667])


>>> pipeline.predict(pd.DataFrame({'Country': ['chk'], 'Fruits': ['Apple'], 'Flower': ['Rose']}))

> ValueError: Found unknown categories ['chk'] in column 0 during
> transform

Примечание: ColumnTransformer доступна с версии 0.20.

1 голос
/ 18 июня 2019

Начиная с версии 0.20, вы можете использовать ColumnTransformer API. Однако для более старых версий вы можете легко развернуть собственную реализацию препроцессора, который обрабатывает столбцы выборочно.

Вот простой прототип, который я реализовал и который расширяет OneHotEncoder. . Вам потребуется указать список столбцов, чтобы вызвать ошибку в аргументе raise_error_cols. Любой столбец, не указанный в этом аргументе, неявно обрабатывается как «игнорируемый».

Пробный прогон

# Setup data
X_train

  Country     Flower  Fruits
2     IND     Orchid   Mango
0     USA       Rose   Apple
4      UK      Lotus  Banana
5      UK  Dandelion   Grape

X_test

  Country   Flower      Fruits
3      UK  Petunia     Berries
1     USA     Lily  Strawberry

X_test2 = X_test.append(
    {'Country': 'SA', 'Flower': 'Rose', 'Fruits': 'Tomato'}, ignore_index=True)
X_test2

  Country   Flower      Fruits
0      UK  Petunia     Berries
1     USA     Lily  Strawberry
2      SA     Rose      Tomato

from selective_handler_ohe import SelectiveHandlerOHE

she = SelectiveHandlerOHE(raise_error_cols=['Country'])
she.fit(X_train)

she.transform(X_test).toarray()
# array([[0., 1., 0., 0., 0., 0., 0., 0., 0., 0., 0.],
#        [0., 0., 1., 0., 0., 0., 0., 0., 0., 0., 0.]])


she.transform(X_test2)
# ---------------------------------------------------------------------------
# ValueError: Found unknown categories SA in column Country during fit
...