Поиск глобального минимума при рассмотрении компромисса смещения и дисперсии

Поскольку Boosting Machine имеет тенденцию к переоснащению, XGBoost уделяет большое внимание решению проблемы компромисс между смещением и дисперсиейи помогает пользователям применять различные методы регуляризации с помощью настройка гиперпараметров.

В этом посте вы познакомитесь с реализацией кода для настройки гиперпараметров с использованием собственного API XGBoost для устранения компромисса между смещением и дисперсией. Весь код этого проекта выложен в мой репозиторий Github.

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

ВВЕДЕНИЕ

Наша цель здесь состоит в том, чтобы выполнить гиперпараметрическую настройку собственного API XGBoost, чтобы улучшить его регрессионную производительность при одновременном решении проблемы компромисса между смещением и дисперсией, особенно для смягчения тенденции Boosting Machine к переоснащению.

Для настройки гиперпараметров в этом анализе используется метод поиска по сетке. Другими словами, мы выбираем поисковую сетку гиперпараметров и рассчитываем производительность модели по всем точкам данных гиперпараметров в поисковой сетке. Затем мы идентифицируем глобальный локальный минимум производительности —или точку данных гиперпараметра, которая дает наилучшую производительность (минимальное значение целевой функции) — как лучшие значения гиперпараметра. для настроенной модели.

Вычислительное ограничение

Настройка гиперпараметров может быть очень дорогостоящей в вычислительном отношении в зависимости от того, как вы устанавливаете сетку поиска. Просто потому, что ему необходимо повторять расчеты производительности по всем точкам данных, которые вы установили в сетке поиска. Чем больше точек данных у вас есть, тем дороже в вычислительном отношении. Очень просто.

К сожалению, мой ноутбук имеет очень ограниченную вычислительную мощность. Но хорошая новость заключается в том, что Google Colab предоставляет один графический процессор на пользователя для своей бесплатной учетной записи. А собственный API XGBoost имеет функцию поддержки графического процессора. В целом я могу ускорить процесс настройки, запустив собственный API XGBoost с графическим процессором Google Colab.

Тем не менее, одного графического процессора по-прежнему недостаточно, когда выбранная поисковая сетка имеет огромное количество точек данных для покрытия. Поэтому мне все еще нужно решить проблемы с ограничениями вычислительных ресурсов.

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

Теперь приступим к кодированию. Во-первых, нам нужно загрузить данные для анализа.

АНАЛИЗ

А. Данные

Для регрессионного анализа мы используем встроенный набор данных California Housing в API sklearn. Источником набора данных является houses.zip в архиве наборов данных StatLib. Лицензию набора данных Лицензия: пункт BSD 3 можно найти в строке 22 кода здесь. Для объяснения о наборе данных, пожалуйста, прочитайте эта ссылка.

Мы можем скачать набор данных California Housing из sklearn.datasets, используя функцию fetch_california_housing.

Мы можем сохранить набор данных в переменной housing_data.

from sklearn.datasets import fetch_california_housing
housing_data = fetch_california_housing()

Теперь нам нужно преобразовать импортированный набор данных в фрейм данных Pandas. Мы разделяем функции и целевую переменную на df1 и df2 соответственно.

descr = housing_data['DESCR']
feature_names = housing_data['feature_names']
data = housing_data['data']
target = housing_data['target']
df1 = pd.DataFrame(data=data)
df1.rename(columns={0: feature_names[0], 1: feature_names[1], 2: feature_names[2], 3: feature_names[3],
 4: feature_names[4], 5: feature_names[5], 6: feature_names[6], 7: feature_names[7]}, inplace=True)
df2 = pd.DataFrame(data=target)
df2.rename(columns={0: 'Target'}, inplace=True)
housing = pd.concat([df1, df2], axis=1)
print(housing.columns)

Теперь давайте посмотрим сводную информацию о функциях фрейма данных.

df1.info()

Вот результат:

<class 'pandas.core.frame.DataFrame'>
RangeIndex: 20640 entries, 0 to 20639
Data columns (total 8 columns):
 #   Column      Non-Null Count  Dtype  
---  ------      --------------  -----  
 0   MedInc      20640 non-null  float64
 1   HouseAge    20640 non-null  float64
 2   AveRooms    20640 non-null  float64
 3   AveBedrms   20640 non-null  float64
 4   Population  20640 non-null  float64
 5   AveOccup    20640 non-null  float64
 6   Latitude    20640 non-null  float64
 7   Longitude   20640 non-null  float64
dtypes: float64(8)
memory usage: 1.3 MB

Б. Библиотеки для импорта

Далее давайте пройдемся по библиотекам, которые мы собираемся использовать.

  • Во-первых, нам нужен собственный XGBoost API для его запуска и его plot_importanceдля отображения важности функции выбранной модели после настройки.
import xgboost as xgb
from xgboost import plot_importance
  • Мы также используем mean_squared_errorиз sklearn.metricsдля показателей.
from sklearn.metrics import mean_squared_error
  • Для разделения набора данных обучения и тестирования train_test_split из sklearn.model_selection может помочь нам разделить фрейм данных.
from sklearn.model_selection import train_test_split
  • Для визуализации мы используем следующие элементы из Matplotlib для рендеринга 3D-изображений.
from matplotlib import pyplot
import matplotlib.pyplot as plt

from mpl_toolkits.mplot3d import Axes3D

С. Гиперпараметры и парная настройка

1. Выбор гиперпараметров для настройки

В собственный API XGBoost встроено так много гиперпараметров. Из-за данной ограниченной доступности вычислительных ресурсов нам приходится делать некоторые выборки.

Джейсон Браунлиподчеркивает, что существует 5 типов гиперпараметров для регуляризации: контроль итераций, сжатие, ограничения дерева, случайная выборка и регуляризация L1 и L2. Следуя его структуре, этот анализ выбирает следующие 9 гиперпараметров для решения проблемы компромисса смещения и дисперсии. Для получения подробной информации о каждом гиперпараметре перейдите по гиперссылке, установленной в каждом гиперпараметре ниже.

а) Контроль итерации: следующие 2 гиперпараметра управляют контролем итерации.

Остальные гиперпараметры должны быть установлены в одном словаре, pram_dict. Мы можем использовать этот словарь параметровдля управления значениями гиперпараметров, когда мы повторяем k-кратную перекрестную проверку точек данных в сетке поиска.

б) Усадка:

c) Ограничения Tree-Booster:

г) Случайная подвыборка:

e) Регуляризации L1 и L2

f) Дополнительные записи не для настройки:

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

  • цель: выберите целевую функцию для регрессии.
  • eval_metric: выберите показатель оценки эффективности для регрессии.
  • gpu_id: 0, как указано ранее Google Colab.
  • tree_method: gpu_hist для выбора настроек графического процессора.

До сих пор мы говорили о трех вещах: выборе гиперпараметров для настройки, начальной настройке словаря параметров и начальных (предварительно настроенных) кривых производительности для оценки начального компромисса смещения и дисперсии. И мы выявили существенную дисперсию или переоснащение.

3. Парная настройка гиперпараметров

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

В целях экономии вычислительных затрат на анализ я сделал 4 пары параметров из 8: а именно

  • (макс_глубина, эта)
  • (подвыборка, colsample_bytree)
  • (min_child_weight, гамма) и
  • (reg_alpha, reg_lambda)

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

Таким образом, каждая попарная настройка постепенно улучшала профиль производительности настроенной модели. Это в целом уменьшило количество точек данных поисковой сетки в целом, таким образом, сэкономив вычислительные затраты на процесс настройки за счет беспристрастности поиска по сетке. Конечно, основное предположение здесь заключалось в том, что результат, полученный с помощью 4 парных настроек, не будет существенно отличаться от результата, полученного идеальной единственной совместной настройкой по всем 8 гиперпараметрам.

Д. Предварительная настройка регрессии: кривые производительности на обучающих и тестовых наборах данных

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

  • Во-первых, мы хотим сравнить производительность обучения и производительность теста, чтобы оценить компромисс между смещением и дисперсией, проблему компромисса между недообучением и переоснащением в начальном состоянии.
  • Во-вторых, в конце настройки мы хотим сравнить кривые производительности до настройки (как для обучения, так и для теста) и кривые производительности после настройки, чтобы оценить влияние настройки на регуляризацию. Мы хотим оценить, эффективно ли настройка выполняет регуляризацию модели для устранения компромисса смещения и дисперсии.

Вот инициализация нашего словаря параметров.

param_dict={'objective': 'reg:squarederror', # fixed. pick an objective function for Regression. 
 'max_depth': 6,
 'subsample': 1,
 'eta': 0.3,
 'min_child_weight': 1,
 'colsample_bytree': 1,
 'gamma': 0,
 'reg_alpha': 0.1,
 'reg_lambda': 1,
 'eval_metric': 'mae', # fixed. picked a evaluation metric for Regression.
 'gpu_id': 0, 
 'tree_method': 'gpu_hist' # XGBoost's built-in GPU support to use Google Colab's GPU
}

Назначенные здесь значения предназначены исключительно для целей инициализации. Эти значения (кроме target, eval_metric, gpu_id и tree_method) изменятся во время настройки гиперпараметра.

Помимо тех гиперпараметров, которые указаны в pram_dict, нам нужно инициализировать 2 других гиперпараметра num_boost_round и Early_stopping_rounds за пределами pram_dict.

num_boost_round = 1000
early_stopping_rounds = 10

Теперь, используя инициализированный словарь параметров param_dict, мы можем использовать встроенную нативную обучающую функцию xgb.train() для определения пользовательской функции, назовем ее bias_variance_performance(). Его цель состоит в том, чтобы оценить компромисс между смещением и дисперсией на итерациях обучения путем сравнения кривых производительности исходной модели между набором обучающих данных и набором тестовых данных.

def bias_variance_performance(params):
   
    evals_result = {}
    model = xgb.train(
        params,
        dtrain=DM_train,
        num_boost_round=num_boost_round,
        evals=[(DM_train, "Train"), (DM_test, "Test")],
        early_stopping_rounds=early_stopping_rounds,
        evals_result=evals_result
    )
    train_error = evals_result["Train"]["mae"]
    test_error = evals_result["Test"]["mae"]
    
   print("Best MAE before the Tuning: {:.4f} with {} rounds".format(model.best_score, model.best_iteration+1))
return model, evals_result

Подробнее о встроенной обучающей функции xgb.train() см. в документации.

Вот результат:

Best MAE before the Tuning: 0.3103 with 121 rounds

Выходные данные показывают наилучшие значения производительности теста, а не производительности обучения. Наилучшая производительность теста была обнаружена на 121-м раунде итераций. Другими словами, исходная (предварительно настроенная) модель (с исходной настройкой гиперпараметров) определялась за 121 раунд итераций.

Давайте сравним начальные (предварительно настроенные) характеристики модели между набором данных поезда и набором тестовых данных на 121-й итерации.

[120]	Train-mae:0.17322	Test-mae:0.31031

Исходная (предварительно настроенная) модель (с начальной настройкой гиперпараметра), определенная на 121 раунде итерации, имеет эффективность обучения 0,17322 и производительность теста 0,3103. Существенный разрыв предполагает дисперсию или чрезмерную подгонку.

На приведенной ниже диаграмме представлены две начальные (предварительно настроенные) кривые производительности вместе с итерационными раундами: одна выделена синим цветом для эффективности обучения, а другая — красным для производительности теста.

По мере продолжения итерации начальная (предварительно настроенная) производительность обучения продолжала улучшаться, в то время как начальная (предварительно настроенная) производительность теста в какой-то момент оставалась на прежнем уровне. Это свидетельствует о заметной дисперсии или переоснащении исходной (предварительно настроенной) модели.

Теперь, чтобы найти компромисс между смещением и дисперсией, мы применяем регуляризацию модели, настраивая гиперпараметры собственного API XGBoost.

Э. Метод настройки:

Что касается методологии настройки, здесь я хотел бы выделить несколько важных сносок.

  • Я установил поисковую сетку для каждой пары гиперпараметров и применил метод поиска по сетке для настройки парных параметров. .
  • Я повторил k-кратную перекрестную проверку, чтобы рассчитать показатель производительности в обучающем наборе данных для всех точек данных в заранее определенной поисковой сетке.
  • В визуализации использовался метод триангуляции-интерполяции, чтобы заполнить пробелы между точками данных сетки поиска и отобразить сглаженную поверхность ландшафта производительности.

а) k-кратная перекрестная проверка

Чтобы запустить к-кратную перекрестную проверку, мы используем встроенную функцию перекрестной проверки xgb.cv(). В качестве меры предосторожности k-кратная перекрестная проверка выполняется только для набора данных поезда (из которого выделяется набор данных проверки): не передавайте тестовый набор данных в функцию перекрестной проверки: xgb.cv().

Мы можем повторить k-кратную перекрестную проверку по всем точкам данных в заранее определенной поисковой сетке для каждой пары гиперпараметров, чтобы найти глобальный минимум показателей производительности регрессии, означающих абсолютные ошибки.

Пользовательская функция k-кратной перекрестной проверки: (необязательно)

Чтобы облегчить итерацию настройки, мы можем настроить функцию перекрестной проверки k-fold, используя встроенную функцию перекрестной проверки XGBoost API, xgb.cv(). Для нашего случая мы установили 5-кратный для нашего анализа. В качестве альтернативы, другое значение, например. 10, можно изучить.

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

def cross_validation(param_dict, DM_train, metrics, num_boost_round, early_stopping_rounds): 
    
    cv_results = xgb.cv(
        params=param_dict,
        dtrain=DM_train, 
        num_boost_round=num_boost_round,
        seed=42, # seed for randomization
        nfold=5, # k of k-fold cross-validation
        metrics=metrics,
        early_stopping_rounds=early_stopping_rounds   
    )
    
    return cv_results

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

Теперь, чтобы определить поиск по парной сетке, мы можем определить функцию для итерации k-кратной пользовательской функции перекрестной проверки, cross_validation(), по всем точкам данных поисковой сетки пары гиперпараметров. Следующая функция, pair_wise_gridsearch_CV, принимает 3 переменные:

  • param1_name и param1_name: имена пары гиперпараметров, которые необходимо настроить.
  • gridsearch_params: поисковая сетка пары гиперпараметров, которую необходимо настроить.
def pair_wise_gridsearch_CV(param1_name, param2_name, gridsearch_params):
min_mae = float("Inf")
    best_params = None
x = []
    y = []
    z = []
    for param1, param2 in gridsearch_params:
        # Update our parameter dictionary for the tuning
        param_dict[param1_name] = param1
        param_dict[param2_name] = param2
        print("CV with {}={}, {}={}".format(param1_name, param1,
                             param2_name,
                             param2))
        # calculate cross_validation
        cv_results = cross_validation(param_dict, DM_train, metrics={'mae'}, num_boost_round=1000, early_stopping_rounds=10)
        mean_mae = cv_results['test-mae-mean'].min()
        boost_rounds = cv_results['test-mae-mean'].argmin()
        
        x.append(param1)
        y.append(param2)
        z.append(mean_mae)
        
        print("\tMAE {} for {} rounds".format(mean_mae, boost_rounds))
        
        if mean_mae < min_mae:
            min_mae = mean_mae
            best_params = (param1, param2)
     
return x, y, z, min_mae, best_params

Функция pair_wise_gridsearch_CV повторяет пользовательскую функцию перекрестной проверки cross_validation по всем точкам данных в поисковой сетке пары гиперпараметров, определенной в gridsearch_params, для поиска глобального минимума ландшафта производительности.

gridsearch_params необходимо предварительно определить перед каждой попарной настройкой гиперпараметров. Это должно быть показано позже.

b) 3D-визуализация ландшафта производительности для пары гиперпараметров

Теперь мы можем определить вспомогательную функцию визуализации Trisurf() для визуализации трехмерной визуализации ландшафта производительности гиперпараметров. Мы будем использовать plot_trisurf() из matplotlib.

plot_trisurf()использует метод интерполяции триангуляции, чтобы заполнить пробел между точками данных в сетке поиска, чтобы отобразить сглаженную поверхность ландшафта производительности.

import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
def Trisurf(xname, yname, x, y, z, min_mae, best_params):
    # (xname, yname): the name of variables to be displayed for visualization
    # (`x`,`y`): all the hyperparamters' datapoints on the search grid 
    # (`z`): the results of the evaluation metric the results of the evaluation metric over the datapoints
    # (`min_mae`, `best_params`): the Native XGBoost API's `k-fold cross-validation` function's outputs the minimum mae result and the corresponding datapoint of the hyperparameters
    fig = plt.figure(figsize=(12, 12))
    ax = fig.add_subplot(111, projection="3d")
    # Creating color map
    my_cmap = plt.get_cmap('RdPu')
    
    # Creating dot plot of the minimum
    ## min_mae*1.01 to float it for the visualization purpose.
    ax.scatter(best_params[0], best_params[1], min_mae, color='red')
    # Tri-Surface Plot
    ax.plot_trisurf(x,y,z,cmap = my_cmap,
                         linewidth = 0.2,
                         antialiased = True,
                         edgecolor = 'grey')
    ax.set_xlabel(xname)
    ax.set_ylabel(yname)
    ax.set_zlabel('mae')
    
    # Write the Title
    ax.set_title("Hyperparameters Performance Landscape ("+str(xname) + ' & '+str(yname)+")") 
    
    # Download the figure as jpeg file.
    figname = str(xname) + '_'+str(yname)
    fig.savefig(str(figname) + '.jpg')

Для получения дополнительной информации о коде посетите мой репозиторий Github.

F. Реализация настройки

На данный момент мы подготовили все те пользовательские служебные функции, которые нам нужны для настройки.

Теперь мы готовы реализовать процесс настройки.

Мы будем выполнять попарную настройку гиперпараметров для каждой пары за раз. После каждой попарной настройки мы будем обновлять значения каждой пары гиперпараметров с лучшим результатом (который дает наименьшее значение функции потерь). И мы переходим к следующей паре гиперпараметров, чтобы повторить процесс. Таким образом, мы можем постепенно улучшать производительность настраиваемой модели.

Теперь мы рассмотрим этот процесс для 4 пар гиперпараметров.

а) 1-я пара: max_depthи eta

Теперь, чтобы настроить первую пару гиперпараметров, max_depth и eta, мы устанавливаем для них сетку поиска следующим образом.

pair_wise_gridsearch_params1 = [
    (max_depth, eta)
    for max_depth in range(5,15)
    for eta in [i/10. for i in range(1, 10)]
]

Теперь давайте передадим эту сетку поиска в пользовательскую функцию pair_wise_gridsearch_CV(), чтобы настроить модель по паре гиперпараметров. Это код.

x1, y1, z1, min_mae1, best_params1 = pair_wise_gridsearch_CV('max_depth', 'eta', pair_wise_gridsearch_params1)

Вот описание выходных переменных в левой части уравнения.

  • x1 и y1 хранят все точки данных пары гиперпараметров в сетке поиска;
  • z1 сохраняет значение производительности в каждой точке данных сетки поиска (x1, y1);
  • min_mae1 хранит лучшее значение производительности, минимальное значение функции потерь.
  • best_params1 хранит точку данных поисковой сетки для пары гиперпараметров, которая обеспечивает наилучшую производительность.

min_mae1 и best_params1 являются результатом попарной настройки.

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

Вот результат.

Best params: 7, 0.1, MAE: 0.2988302932498683

В выводе говорится, что наилучшая производительность на уровне 0,2988 была получена при сетке поиска с max_depth = 7 и eta = 0,1.

Теперь для целей визуализации мы передадим все выходные данные настройки — x1, y1, z1, min_mae1 и best_params1 — вместе с именами пары гиперпараметров в пользовательскую функцию визуализации.

Trisurf("max_depth", 'eta',x1,y1,z1, min_mae1, best_params1)

Вот визуализация ландшафта производительности по всем точкам данных пары гиперпараметров в сетке поиска.

Ландшафт производительности первой пары, max_depth и eta, продемонстрировал разумную согласованность формы ландшафта производительности без многочисленных провалов и скачков. По-видимому, это указывает на разумную предсказуемость производительности модели вблизи лучших значений этих двух гиперпараметров.

Теперь давайте обновим значения пары гиперпараметров, указав лучший результат попарной настройки: max_depth = 7 и eta = 0,1. Поскольку эти значения были сохранены в переменной best_params1, мы можем обновить словарь параметров относительно пары гиперпараметров max_depth и eta следующим образом.

param_dict["max_depth"] = best_params1[0]
param_dict["eta"]= best_params1[1]

Это постепенно улучшает производительность настраиваемой модели.

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

Для следующих трех других пар гиперпараметров я пропущу детали процесса и покажу только соответствующие процессы.

b) 2-я пара:subsample и colsample_bytree

Далее у нас есть два гиперпараметра, связанных с подвыборкой, subsample и colsample_bytree. Поскольку оба связаны с подвыборкой, они могут демонстрировать некоторое взаимодействие друг с другом. По этой причине мы настраиваем пару вместе, чтобы увидеть взаимодействие.

Во-первых, давайте установим сетку поиска для пары следующим образом.

pair_wise_gridsearch_params2 = [
    (subsample, colsample_bytree)
    for subsample in [i/10. for i in range(1, 10)]
    for colsample_bytree in [i/10. for i in range(1, 10)]
]

Теперь давайте передадим эту сетку поиска в пользовательскую функцию pair_wise_gridsearch_CV(), чтобы настроить модель по второй паре гиперпараметров.

x2, y2, z2, min_mae2, best_params2= pair_wise_gridsearch_CV('subsample', 'colsample_bytree', pair_wise_gridsearch_params2)

Вот результат.

Best params: 0.9, 0.8, MAE: 0.2960672089507568

В выводе говорится, что наилучшая производительность 0,296 была получена при сетке поиска подвыборки = 0,9 и colsample_bytree = 0,8. Как и предполагалось, производительность была постепенно улучшена по сравнению с последней настройкой, в результате чего производительность составила 0,2988.

Вот визуализация ландшафта производительности по всем точкам данных поисковой сетки пары гиперпараметров.

Ландшафт производительности второй пары, subsample и colsample_bytree, продемонстрировал разумную согласованность формы ландшафта производительности без многочисленных провалов и скачков. По-видимому, это указывает на разумную предсказуемость производительности модели вблизи лучших значений этих двух гиперпараметров.

Теперь давайте обновим значения пары гиперпараметров, указав лучший результат попарной настройки: subsample = 0,9 и colsample_bytree = 0,8.

param_dict["subsample"] = best_params2[0]
param_dict["colsample_bytree"]= best_params2[1]

Это снова постепенно улучшает производительность модели.

в) 3-я пара: min_child_weight и gamma

Затем третья пара гиперпараметров, min_child_weight и gamma, связана с разделением деревьев. Итак, давайте настроим их вместе, чтобы увидеть взаимодействие между ними.

Во-первых, давайте установим сетку поиска для пары следующим образом.

pair_wise_gridsearch_params3 = [
    (min_child_weight, gamma)
    for min_child_weight in range(0, 10)
    for gamma in range(0, 10)
]

Теперь давайте передадим эту сетку поиска в пользовательскую функцию pair_wise_gridsearch_CV(), чтобы настроить модель по всем точкам данных в сетке поиска пары гиперпараметров.

x3, y3, z3, min_mae3, best_params3 = pair_wise_gridsearch_CV('min_child_weight', 'gamma', pair_wise_gridsearch_params3)

Вот результат.

Best params: 3, 0, MAE: 0.29524631108655486

В выводе говорится, что наилучшая производительность на уровне 0,2952 была получена при сетке поиска min_child_weight = 3 и gamma = 0. Как и предполагалось, производительность была постепенно улучшена по сравнению с последней настройкой, в результате чего производительность составила 0,296.

Вот визуализация ландшафта производительности при различных значениях пары гиперпараметров.

Ландшафт производительности этих двух гиперпараметров, связанных с разделами, min_child_weight и gamma, продемонстрировал разумную согласованность формы ландшафта производительности без многочисленных провалов и скачков. По-видимому, это указывает на разумную предсказуемость производительности модели вблизи лучших значений этих двух гиперпараметров.

Теперь давайте обновим значения пары гиперпараметров лучшим результатом попарной настройки, который равен min_child_weight = 3 и gamma = 0.

param_dict["min_child_weight"] = best_params3[0]
param_dict["gamma"]= best_params3[1]

г) 4-я пара: reg_alpha и reg_lambda

Наконец, мы проведем последнюю попарную настройку гиперпараметров для следующих двух гиперпараметров регуляризации, reg_alpha и reg_lambda.

Во-первых, давайте установим сетку поиска для пары следующим образом.

pair_wise_gridsearch_params4 = [
    (reg_alpha, reg_lambda)
    for reg_alpha in [0, 1e-2, 0.1, 1, 2, 3, 4, 8, 10, 12, 14]
    for reg_lambda in [0, 1e-2, 0.1, 1, 2, 3, 4, 8, 10, 12, 14]
]

Теперь давайте передадим эту сетку поиска в пользовательскую функцию pair_wise_gridsearch_CV(), чтобы настроить модель по паре гиперпараметров.

x4, y4, z4, min_mae4, best_params4 = pair_wise_gridsearch_CV('reg_alpha', 'reg_lambda', pair_wise_gridsearch_params4)

Вот результат.

Best params: 0.1000, 8.0000, MAE: 0.2923583947526392

В выводе говорится, что наилучшая производительность при 0,292358 была получена при сетке поиска reg_alpha = 0,1 и reg_lambda = 8,0. Как и предполагалось, производительность была постепенно улучшена по сравнению с последней настройкой, в результате чего производительность составила 0,2952.

Вот визуализация ландшафта производительности при различных значениях пары гиперпараметров.

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

Другими словами, незначительное изменение их значений может сильно повлиять на результат их работы. Это вполне может привести к нестабильности модели, когда мы передаем набор данных нового типа в настроенную модель в домене развертывания.

Прежде чем делать окончательный вывод, это необходимо тщательно изучить.

На данный момент мы обновляем словарь параметров текущими лучшими значениями для reg_alpha и reg_lambdaи вычисляем производительность настроенной модели на тестовом наборе данных.

param_dict["reg_alpha"] = best_params4[0]
param_dict["reg_lambda"]= best_params4[1]

G. Результат 1-го парного теста настройки

Поскольку мы обновили словарь параметров param_dict по частям, его текущие значения уже обновлены для всех 8 гиперпараметров. Давайте напечатаем его, чтобы подтвердить обновленные значения гиперпараметров после настройки.

print("Parameters after the Pair Wise Tuning:", param_dict)

Вот результат.

Parameters after the Pair Wise Tuning: {'objective': 'reg:squarederror', 'max_depth': 7, 'subsample': 0.9, 'eta': 0.1, 'min_child_weight': 3, 'colsample_bytree': 0.8, 'gamma': 0, 'reg_alpha': 0.1, 'reg_lambda': 8, 'eval_metric': 'mae', 'gpu_id': 0, 'tree_method': 'gpu_hist'}

Теперь мы можем поместить в тестовый набор данных настроенную модель с обновленными значениями этих гиперпараметров, чтобы оценить улучшение производительности теста. Давайте передадим обновленный словарь параметров param_dict в пользовательскую функциюbias_variance_performance().

pw_model_1, pw_evals_result_1=bias_variance_performance(param_dict)

Вот результат.

Best MAE after the Pair-Wise Tuning: 0.2903 with 315 rounds

Посмотрим на результаты 315-го тура.

[314]	Train-mae:0.15790	Test-mae:0.29034

Постнастроенная модель (с настроенной настройкой гиперпараметра) была определена в 315 раундах итераций. И его производительность на обучающем наборе данных составляет 0,1579, а на тестовом наборе данных — 0,29034.

По сравнению с предварительно настроенной производительностью модели, которая составляет 0,17322 в обучающем наборе данных и 0,3103 в тестовом наборе данных, было улучшение.

Вот визуализация кривых производительности как для обучающего набора данных, так и для тестового набора данных.

Результат привел к небольшому улучшению соотношения смещения и дисперсии.

H. Множественные локальные минимумы и нестабильность модели:высокочувствительная производительность модели в отношении reg_alpha и reg_lambda

Неоднократно процесс настройки этих двух параметров регуляризации, reg_alpha и reg_lambda, приводил к неблагоприятному ландшафту производительности с различными провалами и скачками и несколькими локальными минимумами. Это свидетельствует о том, что производительность в процессе настройки была очень чувствительна к небольшим изменениям значений этих двух гиперпараметров регуляризации. Незначительное изменение их значений может кардинально повлиять на результат их работы, на значение целевой функции (функции потерь).

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

  • Во-первых, мы можем ранжировать 10 лучших результатов настройки в соответствии с их показателями производительности и определить 10 лучших точек данных.
  • Во-вторых, основываясь на наблюдении за 10 лучшими результатами настройки, мы можем разделить ландшафт производительности, чтобы более внимательно изучить его согласованность или стабильность производительности.

а) Проверьте 10 самых низких значений производительности, mae

Следующий отсортированный кадр данных ранжирует 10 лучших точек данных производительности в порядке возрастания значений показателей оценки mae.

Теперь, когда мы видим reg_alpha, первые 10 точек данных результатов настройки распределяются в пределах (0,1, 4,0) вдоль reg_alpha.

Для reg_lambda его первые 10 значений ранжирования разбросаны по широкому диапазону (от 0,00 до 12).

Чтобы получить лучшее представление, мы можем разделить ландшафт производительности 3D на следующие разделы:

Все эти значения отображаются в первых двух точках данных производительности в списке. А вот их срезанные кривые производительности:

Например, 2-й срез ландшафта производительности при (reg_alpha = 3,0) определяет острую пропасть, образовавшуюся между (reg_lambda = 0,01) и (reg_lambda = 1,0).

Интенсивная неровность в форме пропасти была зафиксирована более мелкой локальной поисковой сеткой вдоль (reg_lambda = 0,01), (reg_lambda = 0,1) и (reg_lambda = 1), чем любая другая часть поисковой сетки. Другими словами, если бы мы пропустили единственную точку данных (reg_lambda = 0,1) в нашей поисковой сетке, мы бы не смогли зафиксировать наличие локального минимума между (reg_lambda = 0,01) и (reg_lambda = 1,0).

Гораздо более точная детализация в настройках сетки поиска может выявить гораздо более интенсивную шероховатость жесткого ландшафта производительности. Другими словами, мы могли бы обнаружить больше провалов и неровностей с более детальной настройкой сетки поиска. Это может выявить наличие многих других скрытых локальных минимумов, которые невидимы в текущем ландшафте производительности. И даже он может найти лучшую точку данных производительности там, где текущая поисковая сетка не может зафиксировать.

б) 2-й раунд попарной настройки на reg_alpha и reg_lambda

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

pair_wise_gridsearch_params4 = [
    (reg_alpha, reg_lambda)
    for reg_alpha in [0, 1e-2, 2e-2, 3e-2, 0.1, 0.5, 1, 1.5, 1.8, 1.9, 2, 2.1, 2.2, 2.5, 3, 3.5, 4]
    for reg_lambda in [0, 1e-2, 2e-2, 3e-2, 0.1, 0.5, 1, 1.5, 1.8, 1.9, 2, 2.1, 2.2, 2.5, 3, 4, 5, 6, 
                       7, 7.5, 8, 8.5, 9, 9.5, 10, 10.5, 11, 11.5, 12, 12.5, 13, 13.5, 14, 14.5, 15, 15.5]
]

Мы можем снова запустить парную настройку для пары reg_alpha и reg_lambda с новой настройкой сетки поиска, указанной выше.

Вот результат 2-го тюнинга:

Best params: 0.5000, 13.5000, MAE: 0.29122008437950175

В выводе говорится, что наилучшая производительность при 0,29122 была получена при сетке поиска reg_alpha = 0,5 и reg_lambda = 13,5. Как и предполагалось, гораздо более точная детализация search-grid определила лучшую точку данных о производительности в совершенно другом месте, чем первый результат, который равен reg_alpha = 0,1 и reg_lambda = 8,0, что дало производительность 0,292358.

Вот визуализация ландшафта производительности с новой настройкой сетки поиска.

Как и предполагалось, вторая настройка зафиксировала более суровый ландшафт производительности с большим количеством провалов и ударов. Как предполагалось, гораздо более точная детализация сетки поиска определила лучшую точку данных о производительности, reg_alpha = 0,5 и reg_lambda = 13,5, в совершенно другом месте по сравнению с первым результатом, то есть reg_alpha = 0,1 и reg_lambda = 8,0, что дало производительность 0,292358. Вторая настройка также дала лучшую производительность на уровне 0,29122.

Я. Выбор модели

Теперь можем ли мы сказать, что вторая настроенная модель лучше, чем первая настроенная модель?

Мы до сих пор еще не знаем.

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

а) Компромисс смещения и дисперсии, риск чрезмерной подгонки

Теперь давайте запустим недавно настроенную модель на тестовом наборе данных. Мы можем передать последнее обновление словаря параметров param_dict пользовательской функцииbias_variance_performance().

pw_model_2, pw_evals_result_2=bias_variance_performance(param_dict)

Вот результат.

Best MAE after the Pair-Wise Tuning: 0.2922 with 319 rounds

Это говорит о том, что наилучшие показатели теста, 0,2922, были обнаружены на 319-м раунде.

[318]	Train-mae:0.17208	Test-mae:0.29225

Теперь давайте сравним результат 2-й модели после настройки с моделью до настройки и 1-й моделью после настройки.

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

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

По этой причине нам лучше выбрать результат 1-й настройки, а не 2-й.

б) Нарисуйте важность функции

Теперь мы хотим знать, какой вклад внесла каждая функция в определение настроенной модели. Мы можем построить график важности функции, используя первую настроенную модель.

from xgboost import plot_importance
plot_importance(pw_model_1)
pyplot.show()

Вот результат.

ЗАКЛЮЧЕНИЕ

В этом посте вы познакомились с шагами реализации кода для настройки гиперпараметров собственного API XGBoost.

Собственный API-интерфейс XGBoost позволяет пользователям настраивать гиперпараметры для применения различных методов регуляризации для устранения компромисса между смещением и дисперсией. И этот анализ повторил встроенную функцию перекрестной проверки для настройки гиперпараметров.

Теперь вы можете воспроизвести или изменить процесс для своих собственных проектов.

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

Кроме того, если вас интересует краткий обзор XGBoost, вы можете прочитать мой другой пост: XGBoost: его генеалогия, его архитектурные особенности и его инновации.

Спасибо, что прочитали этот длинный пост.

ПОДТВЕРЖДЕНИЕ

Я хотел бы выразить благодарность команде редакторов TDS, особенно Katherine Prairie, за их бесценные советы по редактированию на этапе редактирования.

Рекомендации

Браунли, Дж. Нежное введение в алгоритм повышения градиента для машинного обучения (2016). Получено из Мастерства машинного обучения: https://machinelearningmastery.com/gentle-introduction-gradient-boosting-algorithm-machine-learning/

блоки данных. xgboost-linux64. (2017). . Получено с github: https://github.com/databricks/xgboost-linux64/blob/master/doc/model.md

Хантер Дж., Дейл Д., Файринг Э., Друттбум М. и команда разработчиков Matplotlib. Набор инструментов mplot3d. (2019). Получено с сайта matplotlib.org: https://matplotlib.org/3.1.0/tutorials/toolkits/mplot3d.html#mpl_toolkits.mplot3d.Axes3D.plot_trisurf

Джитешгаванде30, Сингхакшай и Аникакапур. Tri-Surface Plot в Python с использованием Matplotlib. (2021). Получено с geeksforgeeks: https://www.geeksforgeeks.org/tri-surface-plot-in-python-using-matplotlib/

Леон, Д. М. _california_housing.py. (2022). Получено с https://github.com: https://github.com/scikit- учиться/scikit-learn/blob/36958fb24/sklearn/datasets/_california_housing.py#L53

Пейс, Р.К. и Рональд Б. (1997). Разреженные пространственные авторегрессии, письма о статистике и вероятностях, 33 291–297. Архив наборов данных StatLib: http://lib.stat.cmu.edu/datasets/

scikit-learn разработчики. sklearn.datasets.fetch_california_housing. (n.d.) Получено с https://scikit-learn.org/stable/modules/generated/sklearn.datasets.fetch_california_housing.html

Википедия. Компромисс смещения и дисперсии. (2022). Получено из Википедии: https://en.wikipedia.org/wiki/Bias%E2%80%93variance_tradeoff# :~:text=В%20статистике%20и%20машине%20обучения, смещение%20в%20%20расчетных%20параметров.

Википедия. Перекрестная проверка (статистика). (2022). Получено из Википедии: https://en.wikipedia.org/wiki/Cross-validation_%28statistics% 29#k-кратная_перекрестная проверка

Википедия. Поверхностная триангуляция. (2022). Получено из Википедии: https://en.wikipedia.org/wiki/Surface_triangulation

Разработчики xgboost. Документация XGBoost. (без даты). Получено с https://xgboost.readthedocs.io/: https://xgboost.readthedocs.io/en/stable/