May 15, 2022

Ранняя остановка с LightGBM

Рассмотрим, как осуществить подбор оптимального количества деревьев для максимизации качества заданной метрики с градиентным бустингом LightGBM. Сначала сгенерируем рабочий датасет:

import pandas as pd
from sklearn.datasets import make_classification
import numpy as np
np.random.seed(0)

ar, y = make_classification(n_samples=1000, n_features=3, n_informative=2, 
                           n_redundant=0, class_sep = 0.5, shuffle=False, 
                           flip_y=0, n_clusters_per_class=2)

df = pd.DataFrame(ar, columns = ['feat1', 'feat2', 'feat3'])
df['feat4'] = pd.cut(df['feat2'], 5, labels=False)
df['y'] = y
# мешаем
df = df.sample(frac=1).reset_index(drop=True)
df

Разделим данные на выборки:

from sklearn.model_selection import train_test_split

X_cv, X_ts, y_cv, y_ts = train_test_split(df.drop(columns='y').copy(), 
                                          df['y'], test_size=0.2)
X_tr, X_val, y_tr, y_val = train_test_split(X_cv.copy(), y_cv, test_size=0.25)
y_tr.shape[0], y_ts.shape[0], y_val.shape[0]

Инициализируем объект класса LGBMClassifier максимальным количеством деревьев и количеством итераций, в течение которых если метрика не улучшается, происходит останов (подробнее писал здесь). В методе fit для раннего останова передадим валидационный датасет (параметр eval_set) и метрику (eval_metric, список здесь). При этом в последнем может задаваться список метрик, которые будут отслеживаться на валидационном датасете и использоваться для останова (выбор итерации будет происходит с учетом их всех либо первой, если при создании модели указать first_metric_only=True). Также для приглушения вывода значений метрики по умолчанию можно в конструктор класса указать metric='None':

from lightgbm import LGBMClassifier

clf = LGBMClassifier(n_estimators=1000, early_stopping_rounds=80, 
                     first_metric_only=True, metric='None')
clf.fit(X_tr, y_tr, eval_set=(X_val, y_val), eval_metric=['auc', 'cross_entropy'], 
        categorical_feature=['feat4'])

y_p = reg.predict(X_ts)

Как можно заметить, алгоритм выбирает 6 итерацию в качестве оптимальной. Однако, несмотря на то, что при выводе параметров классификатора количество количество деревьев в "обрезанном" лесу не указывается, в реальности используется лучшая итерация:

clf.get_params()

метрика roc_auc, соответствует лучшей:

В свойствах best_score_ и evals_result_ хранятся лучший результат обученной модели и история оценок на валидационном датасете:

clf.best_score_
clf.evals_result_

Также отмечу, что в параметр categorical_feature метода fit можно передать список категориальных признаков (по умолчанию 'auto' - для pandas датафрейма извлекаются признаки с категориальным типом). Чтобы признаки расценивались как категориальные, их надо преобразовать в этот тип (набрать что-то вроде df.astype({it:'category' for it in cat_cols}) )

Подробнее о параметрах можно узнать здесь.

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

1. Тюнинг параметров LightGBM

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

Яндекс Дзен

Telegram