"Секреты и уловки"

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

Введение в передовую практику сохранения лучшей модели при обучении нейронной сети и практическая реализация с использованием fastai и Weights & Biases.

Эта статья изначально была размещена в моем личном блоге

В этом посте мы собираемся:

  • Познакомить с понятием лучшая модель
  • Обсудите, как во время обучения можно определить, сохранить и задокументировать лучшую модель.
  • Узнайте, как использовать fastai и Weights & Biases, чтобы делать все это (почти) автоматически и без усилий.

Что такое «лучшая модель» и почему меня это должно волновать?

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

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

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

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

Определение и сохранение лучшей модели во время обучения

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

  • Место для хранения: большие модели, как правило, занимают значительный объем памяти при сохранении, а размер файлов достигает от сотен МБ до ГБ. Умножьте это на количество эпох, и вы получите довольно значительный объем памяти, предназначенный для хранения всех версий модели. Это может быстро стать проблемой, особенно при удаленном обучении моделей.
  • Влияние на вычисления: сохранение модели после каждой эпохи повлияет на общее время обучения — сериализация/экспорт некоторых моделей может требовать значительных вычислительных ресурсов и быть медленным.

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

if current validation loss lower than candidate validation loss:
    save model to disk overwriting previous candidate
    set candidate validation loss to current validation loss

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

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

Примечание о потерях проверки, альтернативных метриках и документации модели.

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

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

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

Легко сохраняйте лучшую модель во время тренировки с Fastai

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

Если вы не знаете, что такое фастай, его официальное описание::

fastai упрощает обучение быстрых и точных нейронных сетей с использованием лучших современных практик

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

Использование обратного вызова не может быть проще:```python

learner.fit_one_cycle(... ,cbs=[..., SaveModelCallback(monitor='valid_loss')])

где learner — стандартный фастай Learner object. По умолчанию обратный вызов отслеживает потерю проверки, чтобы определить, когда следует сохранить новую лучшую модель. Используйте аргумент monitor, чтобы установить любую другую метрику, отслеживаемую вашим объектом learner. После каждой эпохи во время обучения текущее значение целевой метрики сравнивается с предыдущим лучшим значением — если это улучшение, модель сохраняется в каталоге models (и перезаписывает предыдущий лучший кандидат, если он есть).

За кулисами обратный вызов пытается выяснить, является ли улучшение меньшим значением (если целевая метрика содержит loss или error) или большим значением (все остальное). Это поведение можно переопределить с помощью аргумента comp. Модель сохраняется с помощью функции Fastai save_model, которая является оболочкой для родной Pytorch torch.save.

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

Эту пользовательскую версию обратного вызова можно использовать в качестве замены. Все, что он на самом деле делает, — это внутренне отслеживает словарь показателей (last_saved_metadata), связанных с лучшей моделью. Как это использовать? Все будет раскрыто в следующем разделе!

Автоматически документируйте лучшую модель с помощью Weights & Biases

Сохранение лучшей модели локально — хорошее начало, но оно может быстро стать громоздким, если вы работаете удаленно или проводите большое количество экспериментов. Так как же отслеживать созданные модели и связанные с ними показатели? Вот тут-то и появляются Веса и смещения. W&B — один из тех инструментов, которые заставляют задуматься, как вы когда-либо могли нормально функционировать без них. Хотя официально она описывается как Платформа MLOps для разработчиков, я предпочитаю называть ее швейцарским армейским ножом MLOps.

W&B очень удобен для отслеживания и сравнения экспериментов. Однако для целей этой статьи нас в основном интересуют его почти универсальные возможности управления версиями. В экосистеме W&B артефакты — это компоненты, которым можно управлять версиями, возможно, вместе с их происхождением. Модели могут быть версионированы как артефакты.

Удобно, что fastai имеет встроенный обратный вызов для интеграции с W&B, удачно названный WandbCallback. Чтобы использовать его, нужно инициализировать прогон W&B и добавить обратный вызов к объекту учащегося следующим образом:

# Import W&B package
import wandb
# Initialize W&B run (can potentially set project name, run name, etc...)
wandb.init()
# Add Callback to learner to track training metrics and log best models
learn = learner(..., cbs=WandbCallback())

Основной целью обратного вызова является регистрация полезной телеметрии, касающейся процесса обучения, в вашей учетной записи W&B, включая информацию о среде и показатели. Волшебство происходит, когда он используется в сочетании с SaveModelCallback — в конце процесса обучения самая эффективная модель будет автоматически зарегистрирована как артефакт прогона W&B.

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

Именно здесь вступает в действие пользовательский SaveModelCallback, который обсуждался в предыдущем разделе. Он сохранит всю информацию, необходимую для связывания модели с ее фактичными метаданными. Чтобы воспользоваться этим, также необходимо использовать пользовательскую версию WandbCallback, которую можно найти здесь.

Изменения, сделанные в пользовательском обратном вызове, выделены здесь:

def after_fit(self):
    if self.log_model:
        if self.save_model.last_saved_path is None:
        print('WandbCallback could not retrieve a model to upload')
    else:
        log_model(self.save_model.last_saved_path, metadata=self.save_model.last_saved_metadata)
        for metadata_key in self.save_model.last_saved_metadata:
            wandb.run.summary[f'best_{metadata_key}'] = self.save_model.last_saved_metadata[metadata_key]

В результате автоматически произойдет следующее:

  • Модель, зарегистрированная в прогоне W&B, связана с метаданными, содержащими правильные значения метрик.
  • Значения всех показателей для лучшей модели добавляются в сводку выполнения с префиксом best_. Это позволяет сортировать и сравнивать прогоны на основе производительности соответствующей лучшей модели.

Подведение итогов

Итак, что мы узнали из этой статьи?

  • Только сохранение лучшей модели во время обучения является эффективным и поощряет передовой опыт.
  • Метаданные, в том числе ключевые показатели, связанные с лучшей моделью, почти так же важны, как и сам артефакт модели.
  • С помощью fastai и Weights & Biases сохранение и документирование лучшей модели может выполняться автоматически. Были описаны две пользовательские функции обратного вызова, чтобы сделать этот процесс еще лучше (SaveModelCallback и WandbCallback).