Как настроить гиперпараметры в Python и почему вам это должно быть небезразлично

Наброски

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

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

Что такое гиперпараметры?

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

  • Параметры находятся путем обучения модели
  • Гиперпараметры устанавливаются специалистом по данным перед обучением.

Я считаю 3 основных аспекта создания хорошей модели. Первый - какой тип модели использовать - будет ли это линейная регрессия, SVM или случайный лес? Второй - какие независимые переменные включить в эту модель (также известный как выбор функций). После того, как эти задачи будут выполнены, следует рассмотреть третий аспект - настройку гиперпараметров, которая заключается в поиске лучших гиперпараметров для использования. Вот почему вам следует позаботиться о настройке гиперпараметров: она может значительно повысить точность вашей модели, точно так же, как выбор модели или выбор функции.

Вводный пример

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

Итак, какие значения гиперпараметров обычно проверяются? Другими словами, каковы значения a, b, c и d на изображении выше? Обычно эти значения попадают в диапазон, установленный специалистом по данным. Это потому, что мы хотим избежать переобучения и найти золотую середину (а также сократить время выполнения). Если мы решили, что диапазон гиперпараметра в приведенном выше примере был от 1 до 10, то вместо тестирования 1,1.01, 1.02 до 10 мы используем 1, 5 и 10.

Поиск по сетке и случайный поиск

В большинстве случаев у нас есть более одного гиперпараметра. Поскольку мы уже визуализировали один гиперпараметр, давайте визуализируем два. Для этого мы нанесем два гиперпараметра на оси x и y. В этой плоскости диапазон каждой оси - это диапазон гиперпараметров, которые мы хотим рассмотреть. Очевидно, что из-за вычислительной мощности мы не можем учесть все значения между максимальным и минимальным, так как же нам выбрать значения для проверки? Для этого есть два разных метода: поиск по сетке и случайный поиск.

При поиске по сетке вы выбираете x количество значений, равномерно распределенных по каждой оси (аналогично нашему вводному примеру). Это формирует сетку - отсюда и название. Случайный поиск - это случайный выбор x-квадрата числа значений. В обоих случаях набирается x-квадрат количества очков. Это можно визуализировать ниже (x = 3):

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

Помните, что это два произвольных гиперпараметра, которые не обязательно равны по важности. Что, если гиперпараметр 1 важнее гиперпараметра 2? Это означает, что небольшое изменение гиперпараметра 1 более важно, чем изменение гиперпараметра два. Это похоже на то, как гиперпараметр 2 не имеет значения: пока гиперпараметр 1 имеет правильные значения, модель будет точной, независимо от того, какое значение имеет гиперпараметр 2. Это показано ниже:

Здесь мы видим, что случайный поиск лучше из-за способа выбора значений. В этом примере поиск по сетке проверял только три уникальных значения для каждого гипероператора, тогда как случайный поиск проверял 9 уникальных значений для каждого. Это означает, что если один гиперпараметр важнее других, случайный поиск будет лучше. Подумайте об этом так: если гиперпараметр 2 на самом деле не имеет значения, тогда нам нужно будет тестировать 9 различных значений гиперпараметра 1 вместо 3. То же самое верно и для более высоких измерений (больше гиперпараметров).

Реализация на Python

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

  • Значение C
  • Штраф (L1 или L2)
  • Тип решателя, используемый для обучения логистической регрессии.

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

import numpy as np
from sklearn import linear_model, datasets
from sklearn.model_selection import GridSearchCV
iris = datasets.load_iris()
features = iris.data
target = iris.target

Теперь, когда у нас есть это, нам нужно сгенерировать различные значения гиперпараметров. Для C мы можем использовать np.logspace, который берет конечные точки диапазона, генерирует числа num, равномерно распределенные в этом диапазоне, а затем берет другое число (10 по умолчанию ) и увеличивает его до каждого сгенерированного числа.

  • чтобы генерировать различные типы штрафов, мы просто составляем их список
  • Для решателей, поскольку мы используем оба наказания, мы можем использовать только liblinear и saga. Они тоже есть в списке
C = np.logspace(0, 4, num=10)
penalty = ['l1', 'l2']
solver = ['liblinear', 'saga']

Затем мы помещаем эти гиперпараметры в словарь. Для простоты ключи имеют то же имя, что и переменные.

hyperparameters = dict(C=C, penalty=penalty, solver=solver)

Затем нам нужно создать объект логистической регрессии sklearn, потому что поиск по сетке будет выполнять множество логистических регрессий с разными гиперпараметрами. Затем мы передаем функции GridSearchCV (CV означает перекрестную проверку) объект логистической регрессии и словарь гиперпараметров. Как только это будет сделано, нам нужно подогнать GridSearchCV к нашим функциональным переменным и целевой переменной. Затем мы можем распечатать лучшие оценщики.

logistic = linear_model.LogisticRegression()
gridsearch = GridSearchCV(logistic, hyperparameters)
best_model = gridsearch.fit(features, target)
print(best_model.best_estimator_)

Мой код распечатал лучшие гиперпараметры (наряду с другими, которые я не проверял):

  • C = 166.81005372000593
  • штраф = l2
  • solver = liblinear

Вот полный фрагмент кода:

import numpy as np
from sklearn import linear_model, datasets
from sklearn.model_selection import GridSearchCV
iris = datasets.load_iris()
features = iris.data
target = iris.target
C = np.logspace(0, 4, num=10)
penalty = ['l1', 'l2']
solver = ['liblinear', 'saga']
hyperparameters = dict(C=C, penalty=penalty, solver=solver)
logistic = linear_model.LogisticRegression()
gridsearch = GridSearchCV(logistic, hyperparameters)
best_model_grid = gridsearch.fit(features, target)
print(best_model_grid.best_estimator_)

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

from sklearn.model_selection import RandomizedSearchCV
randomizedsearch = RandomizedSearchCV(logistic, hyperparameters)
best_model_random = randomizedsearch.fit(features, target)
print(best_model_random.best_estimator_)

Резюме

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