MLOps. Зачем он нужен и как с ним работать? Обзор полезных инструментов
Когда впервые сталкиваешься с понятием MLOps, нет абсолютно никакого понимания, а зачем это вообще нужно. В разного рода выступлениях, посвященных этой теме, рассказывают о важности воспроизводимости результатов, хранения зависимостей проекта, а зачем это нужно — обычно никто не объясняет. Все эти вещи становятся очевидными только после того, как пройдешь через весь ад создания и поддержания действительно крупного проекта.
В первой части этой статьи я расскажу о проблемах, с которыми можно столкнуться при работе над проектами, а во второй — об инструментах, которые помогут с ними справиться. Это будет интересно в первую очередь начинающим специалистам в области ML, которые еще не столкнулись с подобными проблемами в своей практике. Я не буду рассказывать об инструментах, которые и так пользуются популярностью в DevOps, а затрону специфичные для области вещи.
Интересно? Поехали!
Зачем все это нужно?
Если вы знакомы с термином DevOps, то вам нетрудно будет понять, зачем нужен MLOps. Если упрощать, DevOps служит для оптимизации производственных процессов, помогает автоматизировать процессы, существующие в цикле разработки.
MLOps — это ответвление от DevOps, ряд практик и инструментов, характерных для ML-сферы.
Разработку программного продукта можно описать в виде цикла, каждая итерация в котором служит для улучшения качества итогового продукта. Отличительной чертой ML является существование дополнительного цикла внутри основного — моделирования. MLOps помогает автоматизировать часть процессов внутри этого цикла. Сосредоточимся на инструментах, которые помогут в характерных для ML задачах.
Но для начала попробуем разобраться, что же такого особенного есть в ML, что для него придумывают уникальные инструменты автоматизации.
Одной из ключевых особенностей разработки в ML является высокая неопределенность в конечном результате. Зачастую невозможно с ходу сказать, заведется ML на этой задаче или нет. Например, классической задачей в ML является попытка прогнозирования одной переменной по другим. Однако одни данные могут вовсе не отражать причины изменения других, в них банально может не оказаться сигнала для прогнозирования искомой переменной. По этой причине ML-проекты обычно разбиваются на несколько этапов:
1. Проверка гипотезы. Грубо гипотеза звучит следующим образом: «А ваш ML здесь вообще работать-то будет?» Здесь мы стараемся проанализировать данные, построить пару простых моделей и понять, можем ли мы решить эту задачу ML-методами или лучше выбрать другой подход?
2. Минимальный жизнеспособный продукт (MVP). Заходим на второй виток исследований, подчищаем данные, достаем новые, проводим более основательную работу по улучшению моделей, пробуем разные подходы к решению задачи. Обычно в MVP стараются решить не всю задачу целиком, а большую ее часть (80% результата за 20% усилий). На этом этапе мы часто все еще находимся в лабораторных условиях, нет никакой интеграции в реальные системы.
3. Проект. Если нас устраивают итоги MVP и решение нам нравится, мы приступаем к полноценному проекту. От статичных данных переходим к реальным, интегрируемся в систему заказчика, начинаем итеративно улучшать систему: разбираемся с проблемами в данных (всегда есть), с особыми случаями в процессе, дорабатываем модели (возможно, меняем подход).
С каждым последующим этапом появляются разные сложности, потихоньку нарастает объем данных, объем кода и появляются факторы, которые нужно учитывать. С точки зрения сложности проекта этапы можно характеризовать так:
1. Проверка гипотезы
a. Зачастую один фиксированный набор данных от заказчика
b. Пара ML-моделей
c. Минимум кода (обычно пара скриптов обработки данных и скрипт обучения)
d. Не нужна интеграция
e. Неполная итерация разработки
2. MVP
a. Больше данных, не один датасет (под разные модели/с различными исправлениями данных)
b. Множество экспериментов и моделей
c. Более сложная структура кода
d. Не нужна интеграция / Простая интеграция
e. Одна/две итерации разработки
3. Проект
a. Различные источники данных (статичные — для обучения, боевые — для проверки)
b. Больше итераций → больше экспериментов
c. Постоянно изменяющийся код, более сложная система
d. Полноценная интеграция, необходимость поддерживать работу системы при изменении моделей
e. Множество итераций разработки
Нарастание сложности заставит вас задуматься о следующих вещах:
Версионирование данных. Данные меняются: то добавляются новые, то изменяются старые (находим баги в данных, вызванные системой заказчика, правим их перед обучением). В процессе может оказаться, что модель, обученная на старых данных, выдает в проде лучшее качество, чем на новых, и вы, естественно, захотите разобраться, в чем причина. Кроме того, при работе в команде разные люди могут по разным причинам работать с разными версиями датасетов. По этой причине (чтобы избежать танцев с бубном, когда вам потребуется доступ к старой версии датасета) стоит задуматься о способах версионирования ваших данных.
Версионирование кода. Совершенно не уникальная для ML проблема. Код — это самая изменчивая часть вашего проекта. Классический пример, зачем версионировать код в ML: построили модель на одной версии кода, изменили несколько вещей в коде, переобучили модель, и старая модель оказалось точнее — как откатить изменения? Еще больше проблем получаем, когда над кодом работает не один человек.
Отслеживание результатов экспериментов. Чем дольше длится ваш проект, тем больше различных экспериментов вы проводите, пробуете разные подходы, разные фичи. Уже через пару дней вы забудете, как была получена та или иная модель, какие были особенности в ее построении, какие фичи вы использовали, какие параметры задавали. Вы можете захотеть сравнить, в чем отличия при обучении двух различных моделей — которую вы построили сегодня и которую собрали месяц назад.
Организация общего доступа ко всему описанному выше. Работа в команде подразумевает, что к данным нужен доступ не одному человеку. Вряд ли вы будете перекидывать файлик с локального компьютера на компьютер коллеги. Также усложняется версионирование данных, т.к. разные люди по-разному будут готовить свои датасеты. Аналогичная ситуация с кодом, однако тут на деле все еще сложнее. Результаты экспериментов также неплохо иметь в общем доступе, чтобы иметь возможность сравнить результаты, полученные при разных подходах моделирования.
Деплой. Проблемы, связанные с деплоем, возникают в самом конце производственного цикла: когда весь разработанный вами код и полученную модель необходимо запустить не на вашем локальном устройстве, а на боевой машине, когда нужно как-то организовать интерфейс взаимодействия с вашей моделью. При этом не стоит забывать, что, скорее всего, деплоить придется далеко не один раз, ведь с каждой итерацией разработки вы будете получать новую версию системы.
Для решения описанных выше проблем существуют инструменты MLOps (и DevOps), которые помогают упростить работу в тех или иных аспектах и не задумываться постоянно об одних и тех же вещах.
MLOps. Полезные инструменты
Jupyter Notebook
Нет, я не буду рассказывать о Jupyter Notebook. Думаю, все, кто работает в этой или смежной области, и так о них прекрасно знают. Здесь я бы хотел отметить, когда стоит, а когда не стоит использовать ноутбуки. Я знаю и тех, кто чуть ли не всю свою работу делал в ноутбуках (сам таким грешил), и тех, кто считает, что ноутбуки вообще нельзя использовать. Однако, как обычно, истина где-то посередине. У Jupyter Notebook есть ряд плюсов и минусов. Начнем с плюсов:
В ноутбуках удобно оформлять код с комментариями к нему.
Отлично подходит для интерактивных туториалов или презентаций.
Удобно использовать при анализе данных (EDA).
Можно легко и быстро проводить эксперименты.
Все это делает ноутбук отличным инструментом, который поможет на первых порах проекта, когда скорость получения результата стоит на первом месте. В чем же недостатки ноутбуков:
Воспроизводимость результата. Не то, чтобы ее нет — казалось бы, запусти все ячейки с нуля, и все заработает, так ведь? К сожалению, далеко не всегда. Типичная история, когда в пылу продуктивной работы код, описанный в ячейке, удаляется (или сама ячейка удаляется), и вот мы имеем результаты, но не имеем кода, который его породил.
Версионирование кода. Вы когда-нибудь пробовали сравнивать версии ноутбука в git?
Отслеживание результатов экспериментов. Чем дольше длится проект, тем больше вы проводите экспериментов. Новый эксперимент — новый ноутбук, и уже через пару месяцев структура проекта разрастется до огромных масштабов с кучей ноутбуков под эксперименты. И вряд ли кто-то будет помнить, в каком ноутбуке что лежит и где та моделька, которую мы месяц назад делали.
На более поздних этапах проекта ноутбуки превращаются из удобного инструмента в неудобный костыль. Стоит ли от них вовсе отказываться? Скорее, нет — в проекте всегда возникают небольшие задачки и гипотезы, которые можно быстро проверить в ноутбуке, а не писать под них уникальные скрипты. Главное, этим не злоупотреблять.
Когда стоит использовать Jupyter Notebook: на начальных этапах проекта или для решения мелких задач.
Hydra
Hydra — это инструмент, который упростит конфигурирование вашего кода и экспериментов. Он позволяет делать модульные конфиги, это удобно. Когда у вас есть несколько источников данных (локальные для обучения и продуктивные системы) или несколько моделей, которые вы хотите использовать, Hydra позволяет написать конфиги под каждый отдельный модуль, а затем быстро переключаться между ними. Кроме того, Hydra позволяет запускать скрипты, изменяя параметры сразу в консоли, а не в конфигурационных файлах, что может быть очень удобно для быстрой проверки гипотез и экспериментов.
Конфиги — это здорово, но для ML-специалистов у Hydra есть еще одна фишка: результаты работы скрипта, запущенного с помощью гидры, будут автоматически сохранены в отдельную директорию. Вы можете сохранять модель, метрики и прочие артефакты прямо в текущей директории. Все это вместе с параметрами конфига будет перенесено в отдельную директорию и ни в коем случае не перезатрет результаты предыдущих запусков. Эта фишка позволяет использовать Hydra как простую версию трекера экспериментов.
Когда стоит использовать Hydra: на всех этапах проекта, на начальных этапах заменит трекер экспериментов.
DVC (Data Version Control)
DVC — это инструмент версионирования данных. Он позволяет хранить версии данных как обычный код в git. Сами данные хранятся отдельно и не заносятся в git — вместо них туда попадут метаданные, с которыми умеет работать DVC. С данными, отслеживаемыми DVC, можно работать как с обычным кодом git: сохранять, отправлять в репозиторий, изменять, переключаться между версиями. В DVC вы можете хранить абсолютно все данные, которые получаются в результате работы ваших скриптов (обработанные данные, модели и т.д.).
DVC обладает еще одной фишкой — пайплайны. Пайплайны DVC очень удобны в использовании. В конфигурационном файле пайплайна описывается порядок запуска скриптов и зависимые файлы (данные), необходимые для работы скрипта. При этом при повторном запуске пайплайна будут выполняться только те скрипты, входные данные к которым поменялись. Это удобно, если, например, у вас есть скрипт подготовки данных и скрипт обучения модели, вы не поменяли данные, но поменяли параметры обучения. В этом случае шаг с подготовкой данных будет автоматически пропущен.
Недостатком DVC является сложность при работе с разными версиями данных. Нередко встречаются ситуации, когда нужен одновременный доступ к старой и новой версии данных, или специалисты работают с одной и той же версией кода, но с разными версиями данных. В случае DVC придется танцевать с бубном, чтобы достать несколько версий данных.
Когда стоит использовать DVC: на первых этапах проекта зачастую можно обойтись без DVC, но как только структура ваших данных становится сложнее, чем один датасет, одна модель, стоит задуматься об использовании систем контроля данных, таких как DVC. А вот пайплайны DVC можно использовать с самого начала.
ClearML
ClearML — это огромный фреймворк, который помогает в решении большинства проблем, описанных в первой части статьи. В первую очередь это трекер экспериментов, но также он предлагает решения для контроля данных, помогает организовать работу над экспериментами в команде и содержит ряд полезных фишек.
Как уже сказано ранее, в первую очередь — это трекер экспериментов. Любой скрипт в вашем пайплайне может быть отслежен при помощи ClearML. При этом он автоматически сохранит всю информацию о запуске скрипта: аргументы командной строки, конфиг Hydra, разницу с текущим коммитом в git, лог скрипта и весь вывод в консоль, зависимости для запущенного скрипта. Внутри скрипта вы можете воспользоваться логированием и сохранять артефакты, метрики, графики. Все это будет доступно в веб-интерфейсе для последующего анализа, также доступ ко всем данным и моделям можно получить напрямую из кода.
Информации более чем достаточно для того, чтобы воспроизвести любой запущенный эксперимент. Более того, можно использовать интерфейс как дэшборд, на котором вы можете следить за ходом обучения модели и выводить интересующую вас аналитику.
Следующей фишкой ClearML является работа с данными. ClearML содержит инструмент для контроля данных, позволяет создавать датасеты, которые могут храниться удаленно, вы же будете иметь дело лишь с локальной копией этих данных и никак не сможете их испортить. На основе датасета вы можете создавать новый, дополнив или изменив его, и точно также сохранив его удаленно. ClearML позволяет отслеживать эволюцию датасета: какие скрипты при этом запускались, что получали на вход и т.д. Вы можете получить одновременный доступ ко всем данным, хранящимся в ClearML.
ClearML работает в клиент-серверной архитектуре, что позволяет получить доступ к экспериментам всей команде. Но самой интересной, на мой взгляд, фишкой ClearML является удаленный запуск: ClearML позволяет автоматически запускать код на машине, на которой развернут, а не на вашем локальном устройстве, что полезно при обучении тяжелых моделей. Более того, все эксперименты, которые были запущены таким образом, можно запускать повторно прямо в веб-интерфейсе, изменив конфигурации эксперимента (также через интерфейс).
Кроме того, ClearML отлично дружит с той же Hydra и прочими популярными инструментами.
Когда стоит использовать ClearML: это тяжеловесная система, которая требует поддержки с вашей стороны. Она, безусловно, полезна, но я бы не советовал использовать ее на начальных этапах проекта. На полную она раскрывается только при переходе в полноценный проект.
BentoML
BentoML — это фреймворк для облегчения деплоя ваших моделей. Он помогает обеспечить интерфейс для работы с ML-моделью и упаковать ее в контейнер. Для подготовки модели необходимо лишь написать скрипт, определить, как обрабатывать входящие данные и как подавать их в модель. BentoML сам определит необходимые зависимости и обернет вашу модель в контейнер.
Когда стоит использовать BentoML: нет смысла писать скрипт-обертку до того, как вам действительно потребуется деплой. Скорее всего, вы воспользуйтесь этим инструментом только при переходе в полноценный проект.
Что имеем?
Описанные ранее системы покрывают практически все, о чем говорится в первой части статьи:
Версионирование данных — DVC, ClearML
Версионирование кода — подробно не рассмотрено, т.к. есть Git, но также помогает ClearML
Отслеживание результатов экспериментов — Hydra, ClearML
Организация общего доступа ко всему описанному выше — ClearML
Деплой — BentoML
Все эти инструменты позволяют автоматизировать и упростить некоторые аспекты работы ML-специалиста, однако это не все существующие инструменты.
Какие еще инструменты есть:
MLFlow — умеет практически все то же самое, что и ClearML (в чем-то больше, в чем-то меньше). Инструмент даже более популярный, чем ClearML, из-за своей простоты. Я не стал его подробно описывать в этой статье, т.к. многие с ним и так знакомы, мне же больше в работе понравился именно ClearML — во многом из-за более приятного интерфейса.
KubeFlow — аналог MLFlow и ClearML в мире Kubernetes. Если вы активно используете Kubernetes, то присмотритесь к этому решению.
Заключение
Стоит помнить, что инструменты — это то, что должно облегчить вашу работу, а не усложнить ее. Не стоит использовать очередной модный фреймворк, если он решает проблемы, которых у вас нет. Вам, скорее всего, не нужно версионирование данных, если проект находится на ранних этапах. Вам не нужно трекать эксперименты, если ваша цель — проверить одну/две гипотезы. Нет смысла задумываться о проблемах деплоя, если никакого деплоя не предусмотрено. Используйте те инструменты, которые вам действительно нужны.
Автор: Антон Головко, специалист по машинному обучению «Инфосистемы Джет»