В этом руководстве мы обучаем модель нейронной сети PyTorch, используя MLflow для отслеживания экспериментов и Optuna для оптимизации гиперпараметров. В руководстве предполагается, что у вас есть некоторый опыт работы с Python и наукой о данных, в частности с обучением модели (нейронной сети).

TL;DR

  • Если вы хотите пропустить руководство и сразу перейти к коду: вот он.
  • MLflow - это платформа, позволяющая осуществлять сквозное управление проектами Data Science. В этом руководстве мы рассмотрим некоторые из его экспериментальных компонентов отслеживания.
  • Optuna - это модульный фреймворк для оптимизации гиперпараметров, созданный специально для проектов машинного обучения. Мы будем использовать его в сочетании с MLflow, чтобы найти и отслеживать хорошие гиперпараметры для нашей модели нейронной сети.
  • PyTorch - это популярный фреймворк глубокого обучения, который мы будем использовать для создания простой сверточной нейронной сети (CNN) и обучения ее классификации чисел в наборе данных рукописных цифр MNIST.

Концепции MLflow

  • Выполнить. Запуск MLflow - это среда выполнения для фрагмента кода машинного обучения. Это позволяет нам регистрировать информацию о наших моделях и экспериментах, такую ​​как параметры, показатели и артефакты.
  • Эксперимент :. Эксперименты являются частью компонента отслеживания MLflow, который позволяет нам группировать запуски вместе, следуя некоторым настраиваемым критериям. Например, мы могли бы создать новый эксперимент для каждой архитектуры модели, которую хотим оценить.
  • Параметры: представляют входные параметры, используемые для обучения, например начальную скорость обучения.
  • Показатели. Показатели используются для отслеживания прогресса тренировки и обычно обновляются в ходе пробежки. Таким образом, вы можете, например, отслеживать потери вашей модели при обучении и проверке, а также визуализировать их развитие в процессе обучения.
  • Артефакты. Они могут представлять любой файл, который вы можете сохранить во время обучения, например графики и веса моделей.

Для более глубокого знакомства с концепциями отслеживания MLflow ознакомьтесь с их документацией.

Концепции Optuna

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

Импорт

Для начала нам нужно импортировать необходимые зависимости:

Определение архитектуры CNN

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

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

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

Функции обучения и проверки

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

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

Создание исследования Optuna

Внутри функции main мы сначала создаем исследование Optuna, указав study_name и direction для оптимизации. После этого мы начинаем процесс оптимизации гиперпараметров, передавая целевую функцию и количество испытаний, для которых мы хотим запустить наше исследование:

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

  • Мы загружаем в сеть изображение, содержащее цифру 7, и оно присваивает выходному классу 7 высокую вероятность 0,97 = ›результирующая потеря вероятности отрицательного журнала будет низкой, что означает, что сеть уже хорошо поработала над правильной классификацией этого изображения.
  • Когда мы даем сети изображение, содержащее цифру 7, и ему присваивается выходной класс 7, низкая вероятность 0,24 = ›потери будут высокими, и веса сети необходимо обновить, чтобы улучшить результаты классификации в будущем.

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

При вызове Optuna’sstudy.optimize() мы передаем так называемую objective функцию в качестве первого аргумента, который является просто функцией, которую мы хотим оптимизировать. Мы рассмотрим содержимое этой функции через секунду.

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

Optuna: целевая функция

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

MLflow: запуск запуска

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

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

Обратите внимание, что MLflow автоматически создает для нас эксперимент с id = 0, если мы не передаем experiment_id вызову mlflow.start_run(). Это означает, что текущие и все будущие запуски будут сгруппированы вместе в рамках этого эксперимента, что вы можете видеть на снимке экрана выше, где каталог эксперимента с именем 0 содержит разные каталоги выполнения, названные по соответствующим идентификаторам запуска.

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

Optuna: получение гиперпараметров

Затем мы используем Optuna для получения гиперпараметров и MLflow, чтобы регистрировать их как значения параметров для текущего прогона:

Давайте посмотрим на пользовательскую функцию suggest_hyperparameters:

Здесь мы видим три разных значения гиперпараметров, созданных с помощью пробной версии Optuna:

  • скорость обучения: определяется как значение с плавающей запятой в логарифмической шкале от 0,0001 до 0,1.
  • dropout: также значение с плавающей запятой от 0,0 до 0,9 с размером шага 0,1.
  • имя оптимизатора: категориальное значение с вариантами «Адам» и «Ададелта».

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

Использование гиперпараметров

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

Сначала мы проверяем, доступен ли графический процессор для обучения или мы останемся на CPU. Мы регистрируем выбор устройства как параметр запуска MLflow.

Затем мы инициализируем нашу сеть, используя гиперпараметр выпадения, предложенный Optuna.

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

Цикл обучения и проверки

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

Сеть обучается для 5 эпох, вызывая функции train и validate поочередно в течение каждой эпохи. Если средняя потеря проверки, возвращаемая функцией validate, меньше, чем предыдущая best_val_loss, она обновляется, чтобы отразить это улучшение.

Затем средние потери при обучении и проверке регистрируются как метрики MLflow для этого прогона. Мы используем индекс эпохи для параметра step, чтобы мы могли отслеживать, как убытки развивались в ходе нашего эксперимента.

Наконец, мы обновляем скорость обучения, вызывая scheduler.step().

Полная целевая функция

Давайте теперь посмотрим на всю целевую функцию:

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

Полная основная функция

Наша последняя основная функция выглядит следующим образом:

Как описано ранее, создается исследование Optuna, и целевая функция вызывается 5 раз с использованием разных гиперпараметров.

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

Заворачивать

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

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

Вы можете найти Jupyter Notebook, содержащий весь код, в этом репозитории GitHub. Помните, что ветвь tutorial-basics содержит код, описанный здесь, а ветвь advanced включает немного больше, например дополнительный гиперпараметр для управления размером пакета, несколько строк кода для сохранения модели PyTorch и еще одну полезную функцию пробное сокращение. который поставляется с Optuna.

❤ Спасибо за чтение и дайте мне знать, понравился ли вам урок! ❤