"Начиная"

Как я научился не беспокоиться и отслеживать свои эксперименты с машинным обучением

Держите свои проекты машинного обучения под контролем

Отслеживать и воспроизводить

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

Рассмотрим эти ситуации:

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

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

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

Поставленная задача

Во-первых, нам нужно отслеживать эксперимент. Для этого я решил обучить модель классификатора фейковых новостей, используя набор данных Kaggle, который вы можете найти здесь. В нем у вас есть CSV-файлы как для фальшивых, так и для реальных новостных статей, содержащие такую ​​информацию, как заголовок, текст, тема и дата каждой статьи. Все статьи были опубликованы в период с 2015 по 2018 год.

Следовательно, это задача классификации текста.

За чем следить

Давайте сначала определим, что важно отслеживать. Мы должны спросить себя: какая информация должна быть доступна, чтобы в будущем у меня было все необходимое для отладки и / или воспроизведения этой модели классификации текста?

Ответ, который я дал себе, был такой:

  • Код: это включает в себя весь конвейер обучения, связанный с вашим экспериментом: от получения данных, функций предварительной обработки, разделения данных, настройки вашей модели и т. Д. Вы также должны знать точную среду, которую вы использовали при обучении своей модели: операционная система, Python версия и все установленные пакеты, включая версию каждого пакета.
  • Данные: набор данных, используемый для обучения и тестирования вашей модели. Если он еще не разделен на соответствующие группы (например, train-test или train-eval-test), тогда ваш код должен содержать информацию о том, как вы его разбить, и он должен быть детерминированным (исправьте свои семена!).
  • Модель: любой файл, который определяет вашу окончательную модель: это может быть файл pickle или joblib, или, возможно, файлы весов и архитектуры для нейронных сетей. Вы также можете сохранять промежуточные модели, например, при поиске по сетке, но последняя модель, которую вы в конечном итоге будете использовать в производстве, является критически важной.
  • Метрики: все виды метрик, которые, по вашему мнению, имеют отношение к вашей задаче: точность, f-оценка, матрицы путаницы, отчеты о классификации в целом. Сюда также могут входить графики, графики, использование CPU / GPU / сети и т. Д. Вы должны отслеживать их для каждой модели, которую вы обучаете, на каждом этапе проверки и тестирования.
  • Метаданные: любые дополнительные метаданные, такие как дата, идентификаторы версии, теги и многое другое.

Обзор

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

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

Загрузка набора данных в S3

Первое, что нам нужно сделать, это подготовить наш набор данных. Изначально у нас есть от Kaggle один файл для фейковых новостей, а другой - для реальных новостей (True.csv и Fake.csv). Следующим шагом будет предварительный анализ данных, но я пропущу его в этой статье. Не потому, что это не важно (это так!), А потому, что в этой записной книжке Kaggle это уже сделано досконально.

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

На данный момент у нас есть разделение на поезд / тест в нашей локальной папке. Каждый запуск с возможными вариациями будет перезаписывать существующие файлы, поэтому нам нужно загрузить их в S3. Для этого я использовал SDK AWS для Python - Boto3. Помимо того, что я следил за разделом документации Quickstart, я также создал корзину на консоли AWS. Затем я создал пользователя IAM и дал ему разрешение на доступ к корзине. Дополнительную информацию об этом можно найти в документации AWS здесь. При создании сегмента обязательно включите управление версиями сегмента!

Следующий фрагмент кода загружает файлы тренировочного теста в корзину. Кроме того, он хранит информацию об идентификаторе версии файла и URL-адресе доступа, которые будут использоваться на следующем шаге при регистрации артефактов в W&B.

В нашей корзине вы можете проверить, были ли файлы загружены и правильно ли версируются:

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

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

Архивация артефактов в W&B

Теперь мы настроены регистрировать эти объекты как артефакты в W&B. Если у вас еще нет учетной записи, команда wandb.login() предложит вам ее создать. Затем запускается запуск выбранного вами проекта, который будет создан для вас, если он еще не существует.

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

На панели инструментов нашего проекта мы можем проверить артефакт и его версии:

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

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

На вкладке Представление графика есть график, обозначающий взаимосвязь между артефактами и прогонами. В этом примере вы можете видеть, что один прогон типа dataset_producer выводит артефакт типа dataset, который, в свою очередь, используется в качестве входных данных для нескольких заданий типов grid_search и final_model_trainer. Вы также можете разложить этот вид, чтобы видеть названия каждого прогона.

Настройка параметров

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

В этом эксперименте я выбрал для оценки два параметра: тип модели и этап предварительной обработки текста. Предварительная обработка текста может выполняться несколькими способами, поэтому я подумал, что было бы неплохо включить ее в качестве переменного параметра. Но здесь я просто протестировал с или без, в демонстрационных целях. Я не включил код для предварительной обработки в эту статью, но вы можете проверить его в репозитории проекта в src/features/denoise, и он в основном был скопирован отсюда.

Я тестирую следующие модели:

  • sgd: регуляризованная линейная модель со стохастическим градиентным спуском.
  • nb: полиномиальный наивно-байесовский
  • svc: поддержка векторной классификации.
  • rf: случайный лес

Набор данных достаточно сбалансирован, поэтому я принял точность в качестве показателя производительности, чтобы войти в W&B и сравнить различные комбинации. Я исключил набор тестов, который будет использоваться только для окончательной модели, поэтому на этапе настройки я провел k-кратную (k = 5) перекрестную проверку, используя только разделение поездов. Регистрируемая точность - это среднее значение k итераций.

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

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

python -m src.models.grid_search --model svc --denoise True

grid_search.py затем извлечет набор данных train-test для доступа к его метаданным, получит требуемый URL-адрес из корзины и перейдет к вызову функции обучения.

При прямом вызове grid_search будет запущена только одна комбинация. Чтобы запустить поиск по сетке, мы используем W&B Sweeps. Мы определяем параметры развертки с помощью файла конфигурации .yaml, например:

Это говорит нам о том, что мы будем выполнять развертку, используя стратегию поиска по сетке, вызывая grid_search, изменяя параметры model и denoise, как определено выше. Цель состоит в том, чтобы максимизировать accuracy_score, и развертка должна быть связана с проектом fn_experiments.

Теперь мы можем запустить следующую команду:

wandb sweep src/models/sweep.yaml

Это запустит поисковый сервер в W&B. Это даст вам sweep_id, который вы будете использовать для запуска агента в локальном блокноте. Этот агент будет взаимодействовать с сервером, запрашивая набор параметров для следующей попытки. В моем случае для запуска агента использовалась следующая команда:

wandb agent felipeadachi/fn_experiments/<sweep_id>

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

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

Еще несколько примеров сюжетов:

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

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

Это лишь некоторые примеры графиков, доступных в W&B. Вы можете построить кривые обучения, калибровочные кривые и многое другое.

Обучайте финальные модели

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

Для окончательной модели я построил матрицу путаницы и отчеты о классификации, предоставленные sklearn. Есть и другие варианты, но мне их достаточно.

Затем я извлекаю данные, как и раньше, и вызываю описанную выше функцию обучения. Я могу получить имя текущего прогона с помощью wandb.run.name, которое я буду использовать, чтобы назвать сгенерированную модель, и сохранить ее как файл joblib.

Как и в случае с набором данных, я могу загрузить модель в свою корзину и сослаться на нее в W&B:

Посмотрим результаты на нашей панели инструментов. Вот пример управления версиями модели:

И матрица путаницы согласно метке category:

Еще одна важная особенность W&B - это то, что он хранит журналы ваших пробежек. Итак, я просто распечатал отчеты о классификации во время прогона, и они остались на моей панели инструментов:

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

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

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

Следующие шаги

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

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

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

На этом пока все! Я намерен продолжить этот проект, чтобы узнать больше о развертывании и мониторинге, и когда я это сделаю, я обязательно поделюсь своими попытками!