June 17, 2022

Подбор этапов предобработки данных

Рассмотрим, как оптимизировать выбранную модель, подбирая не только ее гиперпараметры, но и разные стадии ее предобработки. Это можно осуществить все в тех же классах GridSearchCV и RandomizedSearchCV из библиотеки Scikit-learn. Фактически нам понадобится создать pipeline и научиться передавать его свойства в объект-переборщик. Сначала создадим демонстрационный датафрейм:

from sklearn.datasets import load_diabetes
from sklearn.metrics import mean_absolute_error, mean_absolute_percentage_error
import pandas as pd
import numpy as np
np.random.seed(0)

df, y = load_diabetes(return_X_y=True, as_frame=True)
df['age'] = pd.cut(df['age'], bins=5, labels=False)
df['target'] = y
df = df.sample(frac=1).reset_index(drop=True)
display(df.head())
display(df.shape)

Разделим данные на тренировочную и валидационную выборки:

from sklearn.model_selection import train_test_split

X_tr, X_val, y_tr, y_val = train_test_split(df.drop(columns='target').copy(), 
                                          df['target'], test_size=0.2)
y_tr.shape[0], y_val.shape[0]

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

from sklearn.linear_model import ElasticNet

model = ElasticNet()
model.fit(X_tr, y_tr)

y_p = model.predict(X_val)

print(f'{mean_absolute_error(y_val, y_p):.2f}',
      f'{mean_absolute_percentage_error(y_val, y_p):.3f}')

Как можно заметить, для повышения качества модели следует провести масштабирование и кодировку переменных. Сделаем это с помощью пайплайна, как рассказывал ранее:

from sklearn.pipeline import Pipeline
from sklearn.compose import ColumnTransformer
from sklearn.preprocessing import StandardScaler, RobustScaler
from sklearn.preprocessing import OneHotEncoder, OrdinalEncoder
from category_encoders import TargetEncoder, CountEncoder

ct = ColumnTransformer([('age_enc', OneHotEncoder(sparse=False, handle_unknown='ignore'), ['age'])], 
                       remainder='passthrough')
model = Pipeline([('enc', ct), ('sc', RobustScaler()), ('reg', ElasticNet())])
model.fit(X_tr, y_tr)

y_p = model.predict(X_val)

print(f'{mean_absolute_error(y_val, y_p):.2f}',
      f'{mean_absolute_percentage_error(y_val, y_p):.3f}')

Качество возросло. А теперь попытаемся с помощью GridSearchCV оптимизировать одновременно и гиперпараметры ElasticNet, и подходящие этапы предобработки. Для этого нужно передать в переборщик словарь параметров, соблюдая некоторые правила. В частности, обращаться к свойствам входящих в pipeline классов посредством указания имени шага, затем двойного подчеркивания и имени свойства, ниже пример:

from sklearn.model_selection import GridSearchCV

params = {'reg__alpha':[0.01,0.1, 1, 10], 'reg__l1_ratio':np.linspace(0,1, 10),
          'enc__age_enc':[TargetEncoder(), CountEncoder(), 
            OneHotEncoder(sparse=False, handle_unknown='ignore'), 
            OrdinalEncoder(handle_unknown='use_encoded_value', unknown_value=-1)], 
           'sc':[StandardScaler(), RobustScaler()]}

gr = GridSearchCV(model, params, cv=5, n_jobs=-1, scoring='neg_mean_absolute_percentage_error')
gr.fit(X_tr, y_tr)

y_p = gr.predict(X_val)

print(f'{mean_absolute_error(y_val, y_p):.2f}',
      f'{mean_absolute_percentage_error(y_val, y_p):.3f}')

Теперь из свойств best_score_, best_params_, best_estimator_ и cv_results_ можно получить лучшую оценку на кросс-валидации, оптимальные параметры, оценщика и результаты кросс валидации для всех итераций:

Полезные ссылки:

  1. Создание пайплайнов предобработки данных
  2. Подбор гиперпараметров модели с GridSearchCV и RandomizedSearchCV

Не пропустите ничего интересного и подписывайтесь на страницы канала в других социальных сетях:

Яндекс Дзен

Telegram