Добрый день, уважаемые читатели. Темой сегодняшней статьи станет объединение множества трансформаторов и классификатора в конвейер с сеточным поиском лучшей комбинации параметров.

Сеточный поиск настройки гиперпараметров

Подпишись на группу Вконтакте и Телеграм-канал. Там еще больше полезного контента для программистов.

А на моем YouTube-канале ты найдешь обучающие видео по программированию. Подписывайся!

Сеточный поиск — алгоритм поиска лучшей выборки гиперпараметров модели.

Он довольно прост:

  • выбираете модель обучения
  • выбираете метрику оценки (accuracy/recall и т.д. для классификации, R^2 для регрессии)
  • определяете массивы с различными вариантами значения определённого гиперпараметра
  • создаёте сетку путём прямого произведения массивов (тут может быть непонятно, пример ниже)
  • обучаете модель с различными вариантами настройки для определения лучшей комбинации

Пример с сеткой поиска:

C_param = [1, 2, 3]
gamma_param = [10, 20, 30]

C_gamma_param = 
[
(1, 10) (2, 10) (3, 10)
(1, 20) (2, 20) (3, 10)
(1, 30) (2, 30) (3, 30)
]

Конвейер sklearn

Конвейер — объединение трансформаторов и модели для последовательной обработки данных и предсказания на обработанных данных.

Трансформатор в sklearn — класс, в котором определены методы transform и fit_transform.

Модель в sklearn — класс, в котором определен метод predict.

Конвейер в sklearn представлен классом Pipeline из под-модуля sklearn.pipeline.

Его создание будет продемонстрировано непосредственно на практике, когда мы перейдём к нашей задаче.

Задача классификации

Задача — создать модель, которая сможет с высокой точностью предсказывать, является ли определённая звезда пульсаром, основываясь на некоторые показатели.

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

В качестве набора для обучения и тестирования моделей мною был выбран датасет из Kaggle, который содержит информацию о восьми признаках различных звёзд. Я часто тестирую на этом наборе определённые модели классификации, поскольку он довольно «чист».

Модель обучения — классификатор на основе последовательной нейросети, алгоритм которой реализован в классеsklearn.neural_network.MLPClassifier.

Создание конвейера

Я начну реализацию с импорта всех необходимых нам имён. Хоть их и можно импортировать по мере надобности в программе, однако PEP8 рекомендует делать это в начале файла.

In[1]:
import pandas as pd
import numpy as np

from sklearn.preprocessing import StandardScaler
from sklearn.pipeline import Pipeline
from sklearn.model_selection import GridSearchCV
from sklearn.model_selection import train_test_split

from sklearn.neural_network import MLPClassifier

Загрузка данных, используя pandas:

In[2]:
pulsar_df = pd.read_csv('pulsar_stars.csv')
pulsar_df.head(5)

Отделение исходных признаков от цели предсказания.

In[3]:
X = pulsar_df.drop(['target_class'], axis=1).values
y = pulsar_df['target_class'].values

X[:1], y[:1]

Out[3]:
(array([[140.5625    ,  55.68378214,  -0.23457141,  -0.6996484 ,
           3.19983278,  19.11042633,   7.97553179,  74.24222492]]),
 array([0], dtype=int64))

Также необходимо разделить данные на тренировочный и тестовый набор. Для этого используется стандартный для этой задачи инструмент — функцию train_test_split из под-модуля sklearn.model_selection.

In[4]:
X_train, X_test, y_train, y_test = train_test_split(X, 
                          y,
                          test_size=0.2)

Прекрасно. Теперь, когда готовы все данные, можно приступить к «постройке» конвейера.

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

Алгоритм стандартизации реализован в классе StandardScaler. Так же создадим экземпляр класса классификатора.

In[5]:
scaler = StandardScaler()
clf = MLPClassifier()

Далее создаём массив последовательности «шагов» конвейера. Сначала необходимо стандартизировать данные, а уже затем выполнить предсказание. Выглядит это так:

In[6]:
steps = [('normalizer', scaler), ('classifier', clf)]

pipe = Pipeline(steps)

Запомните, под каким «именем» я указал классификатор, в будущем это пригодится.

Сеточный поиск

Теперь пора выбирать гиперпараметры. Я осуществил поиск трёх параметров — максимального кол-ва итераций, параметра alpha для регуляризации и кол-ва скрытых слоёв сети.

In[7]:
params = \
     {'classifier__solver': ['lbfgs'], 
     'classifier__max_iter': [300, 500, 700], 
     'classifier__alpha': 10.0 ** -np.arange(7, 10), 
     'classifier__hidden_layer_sizes': np.arange(7, 10)}

grid_search = GridSearchCV(pipe, params)

Обратите внимание, как заданны имена параметров. Именно об этом шла речь чуть выше. Теперь используется метод fit(), чтобы адаптировать нашу «модель».

Сам алгоритм сеточного поиска

In[8]:
grid_search.fit(X_train, y_train)

print(grid_search.score(X_test, y_test)) #0.982122905027933

grid_search.best_params_

Out[8]:
{'classifier__alpha': 1e-09,
 'classifier__hidden_layer_sizes': 9,
 'classifier__max_iter': 700,
 'classifier__solver': 'lbfgs'}

С помощью метода score() проводится оценка точности модели на тестовых данных, в атрибуте best_params_ хранится словарь с лучшей комбинацией гиперпараметров.

Заключение

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

Надеюсь этот материал был вам полезен. Желаю вам незатухающего градиента и данных без шумов.

Документ .ipynb с исходным кодом можно загрузить и просмотреть по ссылке.