Как упаковывать и дистрибутировать модели машинного обучения с помощью MLFlow

49523ad9434c8164267aab10f2384c4a.png

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

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

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

Что такое MLflow?

MLflow — это инструмент с открытым исходным кодом для разработки, сопровождения и взаимодействия на каждом этапе жизненного цикла ML-модели. Более того, MLflow является инструментом, не зависящим от фреймворка, поэтому любой ML/DL-фреймворк  может быстро адаптироваться к экосистеме, которую предлагает MLflow.

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

MLflow также предлагает инструменты для управления версиями модели. Эти инструменты инкапсулированы в ее четырех основных компонентах:

  • MLflow Tracking,

  • MLflow Projects,

  • MLflow Models и 

  • MLflow Registry.

MLflow Tracking

MLflow Tracking — это инструмент на основе API для регистрации метрик, параметров, версий моделей, кода и файлов. MLflow Tracking интегрирован с пользовательским интерфейсом для визуализации и управления артефактами, моделями, файлами и т.д. 

Каждая сессия MLflow Tracking организуется и управляется в соответствии с концепцией прогонов. Прогон означает выполнение кода, в ходе которого осуществляется явное логирование артефактов.

MLflow Tracking позволяет вам генерировать прогоны через Python, R, Java и REST_API от MLflow. По умолчанию прогоны хранятся в каталоге, где выполнена сессия. Однако MLflow также позволяет хранить артефакты на локальном или удаленном сервере.

MLflow Model

MLflow Models позволяют упаковывать модели машинного обучения в стандартный формат для непосредственного использования через различные сервисы, такие как REST API, Microsoft Azure ML, Amazon SageMaker или Apache Spark. Одним из преимуществ стандарта MLflow Models является то, что упаковка может быть осуществлена для нескольких языков (multi-language) или вариантов (вкусов) (multi-flavor).

Для упаковки MLflow создает каталог с двумя файлами — моделью и файлом, в котором указаны детали упаковки и загрузки модели. Для примера, в следующем сниппете кода показан файл MLmodel, где указан загрузчик вкусов, а также файл `conda.yaml`, определяющий окружение.

artifact_path: model
flavors:
  python_function:
    env: conda.yaml
    loader_module: MLflow.sklearn
    model_path: model.pkl
    python_version: 3.8.2
  sklearn:
    pickled_model: model.pkl
    serialization_format: cloudpickle
    sklearn_version: 0.24.2
run_id: 39c46969dc7b4154b8408a8f5d0a97e9
utc_time_created: '2021-05-29 23:24:21.753565'

MLflow Project

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

Проект MLflow определяется манифестом YAML под названием `MLProject`, в котором раскрываются спецификации проекта.

Ключевые характеристики для имплементации модели указаны в файле MLProject. К ним относятся:

  • входные параметры, полученные моделью,  

  • тип данных параметров,  

  • команда для выполнения модели, и 

  • среда, в которой проект запускается. 

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

name: example-decision-tree
conda_env: conda.yaml
entry_points:
  main:
    parameters:
      tree_depth: {type: int, default: 2}
    command: "python main.py {tree_depth}"

Кроме того, MLflow предоставляет CLI (интерфейс командной строки) для запуска проектов, расположенных на локальном сервере или в удаленном репозитории. Приведенный ниже сниппет кода показывает пример запуска проекта с локального сервера или удаленного хранилища:

$ mlflow run model/example-decision-tree -P tree_depth=3
$ mlflow run git@github.com:FernandoLpz/MLflow-example.git -P tree_depth=3

В обоих примерах среда будет сгенерирована на основе спецификации `MLProject file`. Команда, запускающая модель, будет выполнена в соответствии с аргументами, переданными в командной строке. Поскольку модель предусматривает входные параметры, они назначаются с помощью флага `-P`. В обоих примерах параметр модели относится к максимальной глубине дерева решений.

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

Как хранить артефакты на MLflow-сервере?

Одним из наиболее распространенных вариантов применения при имплементации MLflow является использование MLflow -cервер для регистрации метрик и артефактов. MLflow-сервер отвечает за управление артефактами и файлами, создаваемыми MLflow-клиентом. Эти артефакты могут храниться в различных системах, от каталога файлов до удаленной базы данных. Например, чтобы запустить MLflow-сервер локально, наберем:

$ mlflow server

Приведенная выше команда запустит MLflow сервис через IP-адрес http://127.0.0.1:5000/. Для хранения артефактов и метрик URI отслеживания сервера определяется в клиентской сессии. 

В следующем сниппете мы увидим базовую имплементацию хранения артефактов на MLflow-сервере:

import MLflow 
remote_server_uri = "http://127.0.0.1:5000"
MLflow.set_tracking_uri(remote_server_uri)
with MLflow.start_run():
   MLflow.log_param("test-param", 1)
   MLflow.log_metric("test-metric", 2)

Команда `MLflow.set_tracking_uri ()` устанавливает местоположение сервера. 

Как запустить аутентификацию на MLflow-сервере?

Использование сервера без аутентификации может быть рискованным. Поэтому ее необходимо добавить. Аутентификация будет зависеть от экосистемы, в которой вы будете размещать сервер:

  • на локальном сервере достаточно добавить базовую аутентификацию на основе пользователя (user)  и пароля (password),  

  • на удаленном сервере учетные данные должны быть настроены в сочетании с соответствующими прокси.

Для наглядности рассмотрим пример MLflow-сервера, развернутого с использованием базовой аутентификации (имя пользователя (username) и пароль). Мы также увидим, как настроить клиента для работы с этим сервером.

Пример: Аутентификация MLflow-сервера

В этом примере мы применяем базовую аутентификацию пользователя и пароля на MLflow-сервере через обратный прокси Nginx. 

Начнем с инсталляции Nginx, которую можно осуществить следующим образом:

# For darwin based OS
$ brew install nginx

# For debian based OS
$ apt-get install nginx

# For redhat based OS
$ yum install nginx

Для ОС Windows следует использовать встроенный Win32 API. Пожалуйста, следуйте подробным инструкциям здесь.

После инсталляции мы создадим пользователя с соответствующим паролем с помощью команды `htpasswd`, которая выглядит следующим образом:

sudo htpasswd -c /usr/local/etc/nginx/.htpasswd MLflow-user

Приведенная выше команда создает учетные данные для пользователя `mlflow-user` в файле `.htpasswd` службы nginx. Позже, чтобы определить прокси под созданные учетные данные пользователя, модифицируется конфигурационный файл `/usr/local/etc/nginx/nginx.conf`, по умолчанию имеющий такое содержимое:

server {
       listen       8080;
       server_name  localhost;
       # charset koi8-r;
       # access_log  logs/host.access.log  main;
       location / {
           root   html;
           index  index.html index.htm;
       }

которое должно выглядеть так:

server {
       # listen       8080;
       # server_name  localhost;

       # charset koi8-r;

       # access_log  logs/host.access.log  main;

       location / {
           proxy_pass http://localhost:5000;
           auth_basic "Restricted Content";
           auth_basic_user_file /usr/local/etc/nginx/.htpasswd;
       }

Мы определяем прокси аутентификации для локального хоста (localhost) через порт 5000. Это IP-адрес и номер порта, на котором по умолчанию развернут MLflow-сервер. В случае использования облачного провайдера вы должны настроить учетные данные и прокси, необходимые для имплементации. Теперь инициализируйте MLflow-сервер, как показано в следующем сниппете:

$ MLflow server --host localhost

При попытке доступа к http://localhost в браузере будет запрошена аутентификация через созданные имя пользователя и пароль.

Рисунок 1. Вход в системуРисунок 1. Вход в систему

После ввода учетных данных вы будете направлены в пользовательский интерфейс MLflow-сервера.

0f43dafde46ad61fab9e681c4511466e.png

Рисунок 2. Пользовательский интерфейс MLflow-сервера 

Чтобы сохранить клиентские данные на MLflow-сервере, необходимо:

  • определить переменные окружения, которые будут содержать учетные данные для доступа к серверу и

  • задать URI, где будут храниться артефакты. 

Итак, для учетных данных мы экспортируем следующие переменные окружения:

$ export MLflow_TRACKING_USERNAME=MLflow-user
$ export MLflow_TRACKING_PASSWORD=MLflow-password

После того, как вы определили переменные окружения, остается только определить URI сервера для хранения артефактов.

import MLflow

# Define MLflow Server URI
remote_server_uri = "http://localhost"
MLflow.set_tracking_uri(remote_server_uri)


with MLflow.start_run():
   MLflow.log_param("test-param", 2332)
   MLflow.log_metric("test-metric", 1144)

При выполнении приведенного выше сниппета мы видим, как тестовая метрика и параметр отражаются на сервере.

0909ccfa5e44458894da676c90fcdcb6.png

Рисунок 3. Метрики и параметры, сохраняемые из клиентской службы с аутентификацией на сервере.

Как зарегистрировать MLflow-модель?

Одной из повседневных потребностей при разработке моделей машинного обучения является поддержание определенного порядка в версиях моделей. Для этого MLflow предлагает реестр MLflow Registry. 

MLflow Registry — это расширение, которое помогает:

  • управлять версиями каждой MLModel и

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

Существует четыре альтернативы для регистрации модели:

  • через пользовательский интерфейс,  

  • в качестве аргумента для `MLflow. .log_model ()`,

  • с помощью метода `MLflow.register_model ()` или 

  • с помощью клиентского API `create_registered_model ()`. 

В следующем примере модель зарегистрирована с помощью метода `MLflow. .log_model ()`:

with MLflow.start_run():

   model = DecisionTreeModel(max_depth=max_depth)
   model.load_data()
   model.train()
   model.evaluate()

   MLflow.log_param("tree_depth", max_depth)
   MLflow.log_metric("precision", model.precision)
   MLflow.log_metric("recall", model.recall)
   MLflow.log_metric("accuracy", model.accuracy)

   # Register the model
   MLflow.sklearn.log_model(model.tree, "MyModel-dt",      registered_model_name="Decision Tree")

Если это новая модель, MLFlow инициализирует ее как Версия 1. Если модель уже имеет версию, она будет инициализирована как Версия 2 (или последующая версия).

По умолчанию, в процессе регистрации модели назначается статус none (присвоенный статус отсутствует). Чтобы присвоить статус зарегистрированной модели, необходимо действовать следующим образом:

client = MLflowClient()
client.transition_model_version_stage(
    name="Decision Tree",
    version=2,
    stage="Staging"
)

В приведенном выше сниппете версия 2 модели Decision Tree (дерево решений) назначена состоянию Staging (стейджинг). В пользовательском интерфейсе сервера мы можем видеть состояния, как показано на Рисунке 4:

a9c280c09d3deeb37d5ecda656df0cc3.png

Рисунок 4. Зарегистрированные модели

 Чтобы обслуживать модель, мы будем использовать MLflow CLI, для этого нам нужен только URI сервера, имя и статус модели, как показано ниже:

$ export MLflow_TRACKING_URI=http://localhost
$ mlflow models serve -m "models:/MyModel-dt/Production"

Обслуженная модель и POST-запросы

$ curl http://localhost/invocations -H 'Content-Type: application/json' -d '{"inputs": [[0.39797844703998664, 0.6739875109527594, 0.9455601866618499, 0.8668404460733665, 0.1589125298570211]}'
[1]%

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

Однако важно отметить, что MLFlow позволяет определять структуру данных для инференции в файле `MLmodel` через имплементацию сигнатур. Также данные, передаваемые через запрос, могут быть различных типов, узнать о которых можно здесь.

Полную имплементацию предыдущего примера можно найти здесь.

MLflow-плагины 

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

MLflow-плагины позволяют кастомизировать и адаптировать деплой и хранение артефактов для конкретных платформ.

Например, существуют плагины для деплоя на конкретной платформе:  

  • MLflow-redisai: который делает деплои в RedisAI из моделей, созданных и управляемых в MLFlow,

  • MLflow-torchserve: который позволяет осуществлять деплой моделей PyTorch непосредственно на TorchServe,

  • MLflow-algorithmia: позволяет выполнять деплой моделей, созданных и управляемых с помощью MLFlow, в инфраструктуру Algorithmia, и

  • MLflow-ray-serve: поддерживает деплой моделей MLFlow в инфраструктуре Ray. 

С другой стороны, для работы над MLflow Projects у нас есть MLflow-yarn, плагин управления MLProjects в среде Hadoop / Yarn. Для кастомизации MLflow Tracking имеется MLflow-elasticsearchstore, который позволяет управлять расширением MLFlow Tracking в среде Elasticsearch.

Подобным образом, предлагаются специальные плагины для развертывания в AWS и Azure. К ним относятся:

Важно отметить, что MLflow предоставляет возможность создавать и кастомизировать плагины в соответствии с потребностями. 

MLflow в сравнении с Kubeflow

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

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

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

Kubeflow — это платформа, работающая на кластере Kubernetes; то есть KubeFlow использует преимущества контейнеризации, которая присуща Kubernetes. Кроме того, KubeFlow предоставляет такие инструменты, как KubeFlow Pipelines, которые предназначены для создания и автоматизации пайплайнов (DAGs) с помощью расширения SDK.

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

В частности, MLflow — это инструмент, ориентированный на управление и совместную работу для разработки проектов машинного обучения. С другой стороны, Kubeflow — это платформа, ориентированная на разработку, обучение и развертывание моделей с помощью кластера Kubernetes и использования контейнеров.

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

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

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

Перевод статьи подготовлен в преддверии старта курса Machine Learning. Advanced.

© Habrahabr.ru