.

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

Показаны сообщения с ярлыком категориальные переменные. Показать все сообщения
Показаны сообщения с ярлыком категориальные переменные. Показать все сообщения

четверг, 27 сентября 2018 г.

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


В продолжение темы препроцессинга категориальных переменных в sklearn pipeline Python.
См. также пост Препроцессинг категориальных переменных в sklearn pipeline Python с LabelEncoder.
Т.е. предыдущий пост про технику препроцессинга на основе LabelEncoder, а в данном посте я покажу, как работаю с LeaveOneOutEncoder.
LeaveOneOutEncoder пожалуй самый необычный способ препроцессинга категориальных переменных.


LeaveOneOutEncoder считается очень удобным, когда у вас много (от нескольких десятков до нескольких сотен) уровней фактора, а также когда часть уровней фактора очень немногочисленны. В моей практике самый лучший пример - уровень зарплат по регионам. У нас 89 регионов в России, причем, львиная доля приходится на Москву, меньше на Санкт-Петербург, а потом уже на остальные регионы, а на некоторые приходится совсем единицы.

Пример

У нас есть такой датасет

df= pd.DataFrame({ 'y': [10,2,3,4,5,6,7,8], 'a': [np.nan, 'b','a', 'b','a', 'b','a', 'b' ],
                  'c': ['a', 'b','a', 'b','a', 'b','b', 'b' ]})
Где y - целевая переменная, которую мы предсказываем, а a, c - категориальные переменные, на основе которых мы прогнозируем y.
После препроцессинга по методу LeaveOneOutEncoder категориальные переменные принимают такой вид
 0 1
0 5.625 6.0
1 5.000 5.4
2 5.000 6.0
3 5.000 5.4
4 5.000 6.0
5 5.000 5.4
6 5.000 5.4
7 5.000 5.4
 
Вы еще не знакомы с техникой препроцессинга категориальных переменных по методу LeaveOneOutEncoder? После препроцессинга переменные становятся типа numeric, т.е. из категориальных превращаются в числовые.


LeaveOneOutEncoder - это среднее по каждому уровню фактора. Возьмем переменную c. Уровню переменной a соответствуют значения целевой переменной Y 10, 3 и 5. Среднее значение по ним равно (10+3+5)/3 = 6. Таким образом, в категориальной переменной с уровень a принимает значение 6.0. А если у нас уровень пропущен, т.е поле пустое, то оно принимает значение среднего по всем данным. В переменной a есть пропущенное значение (np.nan), после препроцессинга оно принимает значение 5.625. Оно получается как среднее значение по всем переменным: (10+2+3+4+5+6+7+8)/8=5.625.
Простой код препроцессинга
lb = df[['a', 'c']]
enc = LeaveOneOutEncoder()
encc = enc.fit(np.asarray(lb), df['y'])
enc_data = enc.transform(np.asarray(lb))
enc_data 
Обратите внимание,  в команде fit у нас участвует целевая переменная. И поэтому код для pipeline у нас будет немного отличаться от того, что мы делали, например, для LabelEncoder.

LeaveOneOutEncoder в в sklearn pipeline Python

загружаем необходимые пакеты
import pandas as pd
import numpy as np
from sklearn import preprocessing
import sklearn
from sklearn.pipeline import Pipeline
from sklearn.pipeline import FeatureUnion
from category_encoders import  LeaveOneOutEncoder
from sklearn import linear_model
Toy датасет
 df= pd.DataFrame({ 'y': [10,2,3,4,5,6,7,8], 'a': [np.nan, 'b','a', 'b','a', 'b','a', 'b' ],
                  'c': ['a', 'b','a', 'b','a', 'b','b', 'b' ], 'b': [5,5,3,4,8,6,7,3],})
Я добавил еще переменную b только для того, чтобы показать, что мы можем брать в препроцессинг любое количество переменных. И декларируем формулу по выбору этим переменных
 
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 для препроцессинга категориальных переменных с помощью LeaveOneOutEncoder.
lb = df[['a', 'c']]
class MyLEncoder(BaseEstimator, TransformerMixin):

    def transform(self, X, **fit_params):
        enc = LeaveOneOutEncoder()
        encc = enc.fit(np.asarray(lb), y)
        enc_data = encc.transform(np.asarray(X))

        return enc_data

    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


На самом деле все просто. И выходим на pipeline
X = df[['a', 'b', 'c']]
y = df['y']

regressor = linear_model.SGDRegressor()

pipeline = Pipeline([
    ('union', FeatureUnion(
        transformer_list=[
             # categorical
            ('categorical', Pipeline([
                 ('selector', MultiColumn(columns=['a', 'c'])),
                ('one_hot', MyLEncoder())
                
            ])),
        
        ])),
    # Use a regression
    ('model_fitting', linear_model.SGDRegressor()),
])

pipeline.fit(X, y)
 
Делаем predict на нашем датасете.
 
pipeline.predict(X)
array([5.49996715, 4.92702859, 5.19722919, 4.92702859, 5.19722919,
       4.92702859, 4.92702859, 4.92702859])



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



воскресенье, 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 - это набор категориальных переменных, на которых мы делаем препроцессинг. Такой код необходим для решения двух проблем:

вторник, 25 февраля 2014 г.

Выбор контрольной группы в программе R при использовании категориальных переменных в регрессионном анализе

При использовании категориальных переменных в регрессионном анализе исследователю бывает важно задать контрольную группу самостоятельно.
Пост - инструментальная подсказка для тех, кто пользуется R. В качестве кейса беру результаты нашего опроса по исследованию факторов текучести персонала (поучаствуйте заодно). В качестве независимой категориальной переменной я беру источники трафика подбора персонала (через какие каналы кандидаты узнали о вакансии).
Знакомые
friend
Социальные сети
 sm
Джоб сайты
jobsites
Объявление в газете
paper
Раздел Вакансии компании (карьерный портал)
cariersite
Работодатель сам вышел на Вас
direct
Вы обратились непосредственно в саму компанию (отдел кадров и т.п.)
self_direct
Кадровое агентство
KA
Центр занятости
Center_job
другое
etc
В R по умолчанию контрольная группа задается первой в алфавитном порядке, т.е. если у вас "арбузы", "апельсины", "мандарины", то по умолчанию контрольной группой будет "апельсины".