.

Сделать репост в соц сети!

воскресенье, 23 сентября 2018 г.

Препроцессинг категориальных переменных в sklearn pipeline Python с LabelEncoder



Для тех, кто работает в Python. Пост показывает ответы на два вопроса:

  1. Препроцессинг категориальных переменных с помощью sklearn pipeline;
  2. Использование LabelEncoder в sklearn pipeline

Код
Загружаем пакеты

import pandas as pd
import numpy as np
from sklearn import preprocessing
from sklearn.preprocessing import LabelEncoder
import sklearn
from sklearn.pipeline import Pipeline
from sklearn.pipeline import FeatureUnion
from sklearn import linear_model

df= pd.DataFrame({ 'y': [10,2,3,4,5,6,7,8], 'a': ['a', 'b','a', 'b','a', 'b','a', 'b' ],
                  'b': ['a', 'b','a', 'b','a', 'b','b', 'b' ],  'c': ['a', 'b','a', 'a','a', 'b','b', 'b' ]})
df
Определяем объект типа class для отбора категориальных переменных из датасета.
 
class MultiColumn():
    def __init__(self,columns = None):
        self.columns = columns # array of column names to encode

    def fit(self,X,y=None):
        return self
    def transform(self, X):                                                           
        return X[self.columns]

Теперь собственно определяю class для препроцессинга категориальных переменных с применением LabelEncoder.
lb = df[['a', 'c']]
class MyLEncoder():

    def transform(self, X, **fit_params):
        enc = preprocessing.LabelEncoder()
        enc_data = []
        for i in list(lb.columns):
            encc = enc.fit(lb[i])
            enc_data.append(encc.transform(X[i]))

        return np.asarray(enc_data).T

    def fit_transform(self, X,y=None,  **fit_params):
        self.fit(X,y,  **fit_params)
        return self.transform(X)

    def fit(self, X, y, **fit_params):
        return self 

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


  1. количество уровней категориальной переменной тренировочного набора данных и нового набора данных могу различаться;
  2. LabelEncoder работает только на единичном векторе данных, но в нашем наборе данных может быть несколько переменных, поэтому, чтобы не делать под каждую переменную свой class, я зашил цикл.

Ниже собственно Pipeline (я беру три категориальные переменные в датасете, но использую две просто потому, что показать, что мы можем работать с любым числом категориальных переменных)
X = df[['a', 'b', 'c']]
y = df['y']
regressor = linear_model.SGDRegressor()

pipeline = Pipeline([

    # Use FeatureUnion to combine the features
    ('union', FeatureUnion(
        transformer_list=[


             # categorical
            ('categorical', Pipeline([
                 ('selector', MultiColumn(columns=['a', 'c'])),
                ('one_hot', MyLEncoder())

            ])),
             # year

        ])),
    # Use a regression
    ('model_fitting', linear_model.SGDRegressor()),
])
pipeline.fit(X, y)
pipeline.predict(X)
array([1.00799316, 1.95769819, 1.00799316, 1.44773543, 1.00799316,
       1.95769819, 1.51795593, 1.95769819])
 
И проверим, работает ли Pipeline на новых данных

new= pd.DataFrame({ 'y': [3, 8], 'a': ['a', 'b' ],'c': ['b', 'a' ], 'b': [3, 6],})
pipeline.predict(new)
array([1.51795593, 1.44773543]) 
На этом все. Не уверен, что это самый простой способ препроцессинга категориальных переменных с помощью LabelEncoder в sklearn pipeline, буду благодарен, если выскажете свои замечания.




Комментариев нет:

Отправить комментарий