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

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

В этом посте мы рассмотрим три метода, используемых для поиска оптимальных гиперпараметров, с примерами того, как их реализовать на моделях в Scikit-Learn, а затем, наконец, на нейронной сети в Керасе. Мы обсудим следующие три техники:

  • Поиск по сетке
  • Рандомизированный поиск
  • Байесовская оптимизация

Вы можете просмотреть блокнот jupyter здесь.

Поиск по сетке

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

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

Давайте рассмотрим пример, в котором мы используем GridSearchCV для поиска наилучшей комбинации значений гиперпараметров для RandomForestClassifier, обученного с использованием популярного набора данных MNIST.

Чтобы вы почувствовали сложность задачи классификации, на рисунке ниже показаны несколько изображений из набора данных MNIST:

Для реализации GridSearchCV нам нужно определить несколько вещей. Во-первых, это гиперпараметры, с которыми мы хотим поэкспериментировать, и значения, которые мы хотим опробовать. Ниже мы указываем это в словаре под названием param_grid.

param_grid сообщает Scikit-Learn оценить 1 x 2 x 2 x 2 x 2 x 2 = 32 комбинации указанных гиперпараметров bootstrap, max_depth, max_features, min_samples_leaf, min_samples_split и n_estimators. Поиск по сетке будет исследовать 32 комбинации значений гиперпараметров RandomForestClassifier и будет обучать каждую модель 5 раз (поскольку мы используем пятикратную перекрестную проверку). Другими словами, всего будет 32 х 5 = 160 раундов! Это может занять много времени, но когда это будет сделано, вы сможете получить наилучшую комбинацию таких гиперпараметров:

forest_grid_search.best_params_

Поскольку n_estimators = 350 и max_depth = 10 являются максимальными оцененными значениями, вам, вероятно, следует попробовать еще раз поиск с более высокими значениями; оценка может продолжать улучшаться.

Вы также можете напрямую получить лучший оценщик:

forest_grid_search.best_estimator_

И, конечно, также доступна оценка:

forest_grid_search.best_score_

Наш лучший результат здесь - точность 94,59%, что неплохо для такой маленькой сетки параметров.

Рандомизированный поиск

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

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

Давайте рассмотрим тот же пример, что и раньше, но вместо этого воспользуемся RandomizedSearchCV. Поскольку мы используем RandomizedSearchCV, мы можем искать в большем пространстве параметров, чем в GridSearchCV:

Как и выше, мы можем увидеть лучшие гиперпараметры, которые были исследованы:

forest_rand_search.best_params_

Также лучший оценщик:

forest_rand_search.best_estimator_

И проверьте лучший результат:

forest_rand_search.best_score_

Наш лучший результат был с точностью 96,21%, превзойдя GridSearchCV на 1,5%. Как видите, RandomizedSearchCV позволяет нам исследовать большее пространство гиперпараметров за относительно то же время и обычно дает лучшие результаты, чем GridSearchCV.

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

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

Байесовская оптимизация

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

Один из таких методов называется байесовской оптимизацией, и мы будем использовать Scikit-Optimize (Skopt) https://scikit-optimize.github.io/ для выполнения байесовской оптимизации. Skopt - это универсальная оптимизационная библиотека, которая выполняет байесовскую оптимизацию со своим классом BayesSearchCV с использованием интерфейса, аналогичного GridSearchCV.

Если у вас еще не установлен Skopt, запустите следующую строку кода в своей виртуальной среде:

! pip install scikit-optimize

Есть два основных отличия при выполнении байесовской оптимизации с использованием BayesSearchCV Скопта. Во-первых, при создании пространства поиска вам необходимо сделать пространство каждого гиперпараметра вероятностным распределением, а не использовать списки likeGridSearchCV. Skopt упрощает это для вас с помощью своей библиотеки skopt.space, которая позволяет нам импортировать вещественные, целые и категориальные значения для создания распределений вероятностей.

  • Реальный: непрерывное пространство гиперпараметров.
  • Целое число: дискретное пространство гиперпараметров.
  • Категориальный: категориальное пространство гиперпараметров.

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

Функция on_step позволяет нам реализовать форму ранней остановки, а также распечатывает счет после каждой итерации. Здесь мы указали, что после каждой итерации мы хотим распечатать лучший результат, и если лучший результат превышает 98%, обучение точности больше не требуется.

Как и в Scikit-Learn, мы можем просматривать лучшие параметры:

forest_bayes_search.best_params_

И лучший оценщик:

forest_bayes_search.best_estimator_

И лучший результат:

forest_bayes_search.best_score_

Байесовская оптимизация позволила нам повысить точность еще на целый процент за то же количество итераций, что и рандомизированный поиск. Я надеюсь, что это убедит вас выйти из зоны комфорта, используя GridSearchCV и RandomizedSearchCV, и попробовать реализовать что-то новое, например BayesSearchCV, в вашем следующем проекте. Поиск по гиперпараметрам может быть утомительным, но есть инструменты, которые могут сделать эту утомительную работу за вас.

Тонкая настройка гиперпараметров нейронной сети

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

Один из вариантов - просто попробовать множество комбинаций гиперпараметров и посмотреть, какая из них лучше всего работает на проверочном наборе (или использовать перекрестную проверку в K-кратном порядке). Например, мы можем использовать GridSearchCV или RandomizedSearchCV для исследования пространства гиперпараметров. Для этого нам нужно обернуть наши модели Keras в объекты, имитирующие обычные классификаторы Scikit-Learn. Первый шаг - создать функцию, которая будет строить и компилировать модель Keras, учитывая набор гиперпараметров:

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

Затем давайте создадим KerasClassifier на основе этой build_model() функции:

keras_clf = keras.wrappers.scikit_learn.KerasClassifier(build_model)

Объект KerasClassifier - это тонкая оболочка вокруг модели Keras, построенной с использованием build_model(). Это позволит нам использовать этот объект как обычный классификатор Scikit-Learn: мы можем обучить его, используя его метод fit(), затем оценить его, используя его метод score(), и использовать его для прогнозирования, используя его метод predict().

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

Теперь мы можем получить доступ к лучшим параметрам, оценке и оценке, как в Scikit-Learn:

keras_rand_search.best_params_
keras_rand_search.best_score_

Наша точность увеличилась еще на 0,5%! Последний шаг - посмотреть, как каждая модель работает на тестовом наборе (см. Ниже).

Выводы

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

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

Как всегда, приветствуются любые отзывы и конструктивная критика.

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

Дополнительные ресурсы



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