Развертывание моделей машинного обучения на основе встраивания: часть 2

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

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

Это сообщение в блоге является продолжением статьи об Общем шаблоне для развертывания моделей машинного обучения на основе встраивания. Модели на основе встраивания сложно развернуть, поскольку необходимо пересчитать все вложения, при этом текущий трафик не прерывается и плавно переключается на новую модель. В этой статье мы представляем набор инструментов и фреймворков - Kubernetes, Istio и Kubeflow Pipelines - которые позволяют реализовать этот общий шаблон. Следует отметить, что это всего лишь один из способов сделать это. Существует множество жизнеспособных практических реализаций, вам просто нужно выяснить, что лучше всего подходит для вашей команды и приложения.

Исходя из системы обобщенных вложений

Мы начнем с обобщенной системы встраивания, которая была представлена ​​в сообщении блога Общий шаблон. По сути, обобщенная система встраивания - это обобщение поисковой системы и рекомендательной системы.

Обобщенная система вложений состоит из трех функциональных компонентов:

  • Генератор встраивания, возвращающий вложения на основе его ввода. В поисковой системе это модель, переводящая поисковый запрос во вложение. В системе рекомендаций это хранилище встраиваемых данных пользователя, возвращающее вложение пользователя на основе его идентификатора.
  • Сервер внедрения, на котором размещены предварительно рассчитанные вложения для поиска сходства.
  • Приложение, которое извлекает вложение из генератора встраивания и отправляет его на сервер встраивания для выполнения поиска по сходству.

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

Kubernetes как фреймворк для оркестрации контейнеров

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

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

Встраивание генератора с обслуживанием TensorFlow

Компоненту генератора встраивания потребуется преобразовать поисковый запрос во встраивание. Поскольку TensorFlow является одной из стандартных библиотек для выполнения рабочих нагрузок машинного обучения, мы используем TensorFlow Serving для обслуживания нашей модели. Единственное требование для рабочей нагрузки TensorFlow Serving - наличие файла SavedModel и указание местоположения этого файла при запуске образа докера tenorflow / serve. Для получения дополнительных сведений о реализации ознакомьтесь с Руководством по обслуживанию TensorFlow для Kubernetes.

Размещение сервера внедрения на ElasticSearch

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

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

Размещение приложения с Connexion / Flask

Наше приложение реализовано на фреймворке zalando / connexion. Connexion - это фреймворк Swagger / OpenAPI First для Python поверх Flask с автоматической проверкой конечных точек и поддержкой OAuth2.

До сих пор мы показали, как система обобщенных вложений может быть реализована автономно.

Две версии генератора встраивания и сервера встраивания

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

Что касается генератора внедрения, который реализован с помощью TensorFlow Serving, мы будем использовать отдельное развертывание для каждой модели. Ярлыки kubernetes для развертывания используют одну и ту же app: embedding-generator метку, но имеют разные version метки в зависимости от версии модели. Это будет важным параметром для определения логики маршрутизации позже.

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

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

Расширенная маршрутизация трафика с Istio

Давайте подробно перефразируем требования к маршрутизации трафика:

  • На границе системы каждому запросу присваивается версия модели в соответствии с целевыми весовыми процентами. Например, 80% входящих запросов должны переходить в версию 1, а оставшиеся 20% - в версию 2. Эти целевые весовые проценты должны легко настраиваться, чтобы у нас был точный контроль того, как трафик переключается с одной версии модели. к другому со временем.
  • Когда запрос распространяется на встраиваемые компоненты ниже по потоку, запрос должен обрабатываться должным образом, чтобы получить согласованные результаты. После того, как версия модели была назначена запросу, он должен получить вложение от генератора встраивания этой версии модели и впоследствии выполнить поиск встраивания в правильном индексе данных нашего сервера встраивания.

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

Istio

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

В этом случае нас особенно интересует Istio из-за функций маршрутизации трафика.

Маршрутизация трафика на основе заголовков с Istio

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

  • На границе системы, на шлюзе API, мы попросим прокси-сервер sidecar назначить версию модели в запросе заголовка на основе настраиваемого процента разделения между моделями. Затем этот заголовок можно использовать в последующих операциях.
  • Мы будем использовать маршрутизацию на основе заголовков Istio, чтобы нисходящий запрос для получения встраивания собирался из генератора встраивания, который соответствует версии модели, указанной в запросе заголовка. Логика маршрутизации на самом деле является отображением между заголовком версии модели и меткой kubernetes version.
  • Для поиска подобия на сервере внедрения версия модели в заголовке запроса используется для выполнения поиска по правильному индексу.

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

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

Оркестровка развертывания модели с помощью Kubeflow Pipelines

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

  1. Разверните новую версию модели рядом с текущей.
  2. Прямая потоковая передача обновлений для обеих версий модели.
  3. Начните массовую загрузку, чтобы заполнить новую версию модели всеми пересчитанными историческими записями.
  4. После того, как объемная загрузка обработана новой версией модели, она готова к приему трафика, и мы можем постепенно переключать трафик со старой модели на новую.
  5. Удалите старую версию модели

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

Развертывание модели с ускорением

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

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

На этапе «рампы» целевые весовые проценты обновляются, так что трафик постепенно увеличивается до другой версии модели, как показано на рисунке 10.

Развертывание модели A / B

Шаги 4 и 5 немного отличаются для сценария развертывания модели A / B, поскольку продвигаемая версия модели является переменной. В этом сценарии во время линейного изменения вводится шаг паузы. На основе характеристик модели определяются новые целевые весовые проценты, и линейное изменение в интерактивном режиме продолжается до тех пор, пока модель не будет продвинута. Традиционно при A / B-тестировании новая версия модели сначала получает только небольшую часть трафика, и будет проверяться, как новая версия модели реагирует на реальный трафик. В зависимости от этих результатов трафик может постепенно увеличиваться, если новая модель окажется лучше. Например, это сценарий, в котором после разделения трафика 50/50% было решено вернуться к версии модели 1:

Простым инструментом для ввода этих целевых весовых процентов может быть очередь сообщений, например Google Cloud Pub / Sub. Конвейер просто считывает сообщения из очереди сообщений и развертывает целевые весовые проценты. В этом случае на графике выполнения будут ветви «продвижение» и «откат», в зависимости от результатов A / B-тестирования.

Заключение

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

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

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

О ML6

Мы - команда экспертов по ИИ и самая быстрорастущая компания в области ИИ в Бельгии. Имея офисы в Генте, Амстердаме, Берлине и Лондоне, мы создаем и внедряем системы самообучения в различных секторах, чтобы помочь нашим клиентам работать более эффективно. Мы делаем это, оставаясь на вершине исследований, инноваций и применяя наш опыт на практике. Чтобы узнать больше, посетите www.ml6.eu.