Автор статьи: Рустем Галиев

IBM Senior DevOps Engineer & Integration Architect

Привет, Хабр! Меня зовут Рустем, IBM Senior DevOps Engineer & Integration Architect

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

Не будем томить, сразу к делу.

Что такое MLflow?

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

В настоящее время он предлагает четыре компонента:

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

  • Проект MLflow — это формат для упаковки кода обработки и анализа данных повторно используемым и воспроизводимым способом, основанным главным образом на соглашениях. Кроме того, компонент «Проекты» включает в себя API и инструменты командной строки для запуска проектов, что позволяет объединять проекты в рабочие процессы.

  • Модель MLflow — это стандартный формат для упаковки моделей машинного обучения, который можно использовать в различных нижестоящих инструментах, например, для обслуживания в режиме реального времени через REST API или пакетного вывода в Apache Spark. Формат определяет соглашение, позволяющее сохранять модель в различных «ароматах», которые могут быть поняты различными последующими инструментами.

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

    Установить MLFlow можно следуя документации, там все просто, не будем тратить на это время: https://www.mlflow.org/docs/latest/quickstart.html

    Когда же все установлено, запустим сервер следующей командой:

nohup mlflow server --host 0.0.0.0 \
                    --port 5000 \
                    --backend-store-uri file:///root/mlflow &

Давайте запустим первый пример MLflow с помощью Tracking API.

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

Вот простой скрипт Python:

import os
from random import random, randint

import mlflow
from mlflow import log_metric, log_param, log_artifacts

tracking_uri='file:///root/mlflow'
mlflow.set_tracking_uri(tracking_uri)

experiment_name = 'hello_world'
mlflow.set_experiment(experiment_name) 

if __name__ == "__main__":
    print("Running mlflow_tracking.py")

    log_param("hyperparam1", randint(0, 100))

    log_metric("accuracy", random())
    log_metric("accuracy", random() + 1)
    log_metric("accuracy", random() + 2)

    if not os.path.exists("outputs"):
        os.makedirs("outputs")
    with open("outputs/model.txt", "w") as f:
        f.write("hello world!")

    log_artifacts("outputs")

Его также можно склонить из https://github.com/PipelineAI/katacoda-notebooks


Что мы и сделаем, и запустим:

cd ~
git clone https://github.com/PipelineAI/katacoda-notebooks
cd ~/katacoda-notebooks/06_mlflow_install/
python mlflow_tracking.py

По умолчанию, где бы мы ни запускали нашу программу, API отслеживания записывает данные в файлы в место, указанное переменной среды MLFLOW_TRACKING_URI.

Обучение MLflow

Отслеживание наших обучающих запусков модели с помощью MLflow довольно просто.

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

...

### Framework imports ###

...

# Import mlflow and framework support

import mlflow
import mlflow.[keras|tensorflow|sklearn]

# Setup Experiment Tracker

tracking_uri='file:///root/mlflow'
mlflow.set_tracking_uri(tracking_uri)

experiment_name = 'name'
mlflow.set_experiment(experiment_name)  

...

### Framework specific model training code ###

...

# Start the MLflow run
with mlflow.start_run():
    history = model.fit(x_train, y_train,
                    batch_size=batch_size,
                    epochs=epochs,
                    verbose=1,
                    validation_split=0.1)
    score = model.evaluate(x_test, y_test,
                       batch_size=batch_size, verbose=1)
    print('Test score:', score[0])
    print('Test accuracy:', score[1])

API-интерфейсы отслеживания MLflow могут регистрировать информацию о каждом запуске обучения, например гиперпараметры, используемые для обучения модели, и метрики, используемые для оценки модели. Мы также можем сериализовать модель в формате, который MLflow умеет развертывать.

Мы можем добавить конфигурацию с помощью mlflow.start_run():

# Log Parameters
    mlflow.log_param("alpha", alpha)
    mlflow.log_param("l1_ratio", l1_ratio)

    # Log Metrics
    mlflow.log_metric("rmse", rmse)
    mlflow.log_metric("r2", r2)
    mlflow.log_metric("mae", mae)

    # Log Model
    mlflow.[keras|tensorflow|sklearn].log_model(lr, "model")

Каждый раз, когда мы запускаем код, MLflow регистрирует информацию о наших экспериментах в расположении, указанном в переменной среды MLFLOW_TRACKING_URI.

Теперь давайте посмотрим на это в действии и обучим модели с помощью Keras, Tensorflow и Scikit-learn.

Мы запускаем пример Keras, который обучает и оценивает простой MLP в задаче классификации темы новостной ленты Reuters.

cd ~/katacoda-notebooks/07_mlflow_training
cat MLflow_Keras.py
cd ~/katacoda-notebooks/07_mlflow_training
cat MLflow_Keras.py

Также запускаем образец TensorFlow, который также обучает и оценивает простой MLP в задаче классификации тем новостной ленты Reuters.

cd ~/katacoda-notebooks/07_mlflow_training
cat MLflow_TensorFlow.py
cd ~/katacoda-notebooks/07_mlflow_training
python MLflow_TensorFlow.py

Мы запускаем пример Scikit-Learn, который прогнозирует качество вина с помощью sklearn.linear_model.ElasticNet.

cd ~/katacoda-notebooks/07_mlflow_training
cat MLflow_Scikit_Learn.py
cd ~/katacoda-notebooks/07_mlflow_training
python MLflow_Scikit_Learn.py

Откроем UI

Пайплайны в MLflow

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

API mlflow.projects.run() в сочетании с mlflow.tracking позволяет создавать многоэтапные рабочие процессы с отдельными проектами (или точками входа в одном проекте) в качестве отдельных шагов. Каждый вызов mlflow.projects.run() возвращает объект выполнения, который можно использовать с mlflow.tracking, чтобы определить, когда выполнение закончилось, и получить его выходные артефакты. Затем эти артефакты можно передать на другой шаг, который принимает параметры пути или uri. Вы можете координировать весь рабочий процесс в одной программе Python, которая просматривает результаты каждого шага и решает, что отправить дальше, используя собственный код.

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

Этот рабочий процесс состоит из четырех шагов:

  • load_raw_data.py: загружает набор данных MovieLens (набор троек идентификатора пользователя, идентификатора фильма и рейтинга) в формате CSV и помещает его в хранилище артефактов.

  • etl_data.py: преобразует CSV-файл MovieLens из предыдущего шага в Parquet, попутно удаляя ненужные столбцы. Это уменьшает размер входных данных с 500 МБ до 49 МБ и обеспечивает столбцовый доступ к данным.

  • als.py: запускает чередующийся метод наименьших квадратов для совместной фильтрации в версии MovieLens Parquet для оценки movieFactors и userFactors. Это дает относительно точную оценку.

  • train_keras.py: обучает нейронную сеть на исходных данных, дополненных ALS movie/userFactors — мы надеемся, что это улучшит оценки ALS.

В программе main.py мы будем выполнять эти шаги по порядку и передавать результаты одного шага другому.

Трекинг MLflow

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

Каждый запуск записывает следующую информацию:

  • Версия кода: хэш фиксации Git, используемый для запуска, если он был запущен из проекта MLflow.

  • Время начала и окончания: время начала и окончания прогона.

  • Источник: имя файла для запуска выполнения или имя проекта и точка входа для выполнения, если оно выполняется из проекта MLflow.

  • Параметры: входные параметры типа "ключ-значение" по вашему выбору. И ключи, и значения являются строками.

  • Метрики: метрики "ключ-значение", где значение является числовым. Каждую метрику можно обновлять в ходе выполнения (например, чтобы отслеживать, как сходится функция потерь вашей модели), а MLflow записывает и позволяет визуализировать полную историю метрики.

  • Артефакты: выходные файлы в любом формате. Например, вы можете записывать изображения (например, PNG), модели (например, замаринованную модель scikit-learn) и файлы данных (например, файл Parquet) в качестве артефактов.

При желании мы можем организовать прогоны в эксперименты, которые объединяют прогоны для конкретной задачи. Мы можем создать эксперимент, используя интерфейс командной строки экспериментов mlflow, функцию mlflow.create_experiment() или соответствующие параметры REST. API и пользовательский интерфейс MLflow позволяют создавать и искать эксперименты.

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

Вот простой пример Python:

with mlflow.start_run():
    for epoch in range(0, 3):
        mlflow.log_metric(key="quality", value=2*epoch, step=epoch)

Мы запускаем многошаговый образец Spark и Keras

cd ~/katacoda-notebooks/08_mlflow_pipelines
cat MLproject

cd ~/katacoda-notebooks/08_mlflow_pipelines
MLFLOW_TRACKING_URI=file:///root/mlflow mlflow run --experiment-name spark-keras

Посмотрим на это в UI


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

Гиперпараметры — это переменные, управляющие процессом обучения модели.

Например:

  • Скорость обучения.

  • Количество слоев в нейронной сети.

  • Количество узлов в каждом слое.

Значения гиперпараметров не запоминаются. Другими словами, в отличие от весов узлов и других параметров обучения, процесс обучения модели не корректирует значения гиперпараметров.

Настройка гиперпараметров — это процесс оптимизации значений гиперпараметров для максимизации точности прогнозирования модели.

Существует множество подходов к оптимизации/настройке гиперпараметров:

  • Поиск по сетке

  • Случайный поиск

  • Байесовская оптимизация

  • Оптимизация на основе градиента

  • Эволюционная оптимизация

  • Обучение населения

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

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

Настройка гиперпараметров с помощью MLflow

Во-первых, нам нужно решить, что отслеживать.

  • Гиперпараметры: все против тех, которые настраиваются

  • Метрика(и): обучение и проверка, потеря и цель, несколько целей

  • Теги: происхождение, простые метаданные

  • Артефакты: сериализованная модель, большие метаданные

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

В следующем примере мы попытаемся оптимизировать показатель RMSE модели глубокого обучения Keras для набора данных о качестве вина. Модель Кераса имеет два гиперпараметра, которые мы пытаемся оптимизировать: скорость обучения и импульс.

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

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



MLproject имеет 4 таргета:

  • Train - Мы обучаем простую модель глубокого обучения на наборе данных о качестве вина из нашего руководства. Он имеет 2 настраиваемых гиперпараметра: скорость обучения и импульс. Содержит примеры того, как обратные вызовы Keras можно использовать для интеграции MLflow.

  • random выполняет простой случайный поиск в пространстве параметров.

  • gpyopt использует GPyOpt для оптимизации гиперпараметров поезда. GPyOpt может запускать несколько прогонов mlflow параллельно, если запускается с размером пакета > 1 и max_p > 1.

  • hyperopt мы используем Hyperopt для оптимизации гиперпараметров.

Давайте запустим это.

Мы запускаем пример настройки гиперпараметров:


cd ~/katacoda-notebooks/09_mlflow_tuning
cat MLproject

cd ~/katacoda-notebooks/09_mlflow_tuning
MLFLOW_TRACKING_URI=file:///root/mlflow mlflow run -e random --experiment-name random-search

Взглянем на UI


MLflow Model Serving


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

Разворачиваем модель MLflow локально или генерируем Docker-образ с помощью CLI-интерфейса к модулю mlflow.models.

Сервер REST API принимает следующие форматы данных в качестве входных данных POST для пути /invocations:

  • JSON-сериализованные панды DataFrames в разделенной ориентации. Например, data = pandas_df.to_json(orient='split'). Этот формат указывается с использованием значения заголовка запроса Content-Type application/json или application/json; формат = панды-разделить.

  • JSON-сериализованные панды DataFrames в ориентации записей. Я не рекомендую использовать этот формат, поскольку он не гарантирует сохранения порядка столбцов. Этот формат указывается с использованием значения заголовка запроса Content-Type application/json; формат = панды-записи.

  • CSV-сериализованные панды DataFrames. Например, данные = pandas_df.to_csv(). Этот формат указывается с использованием значения заголовка запроса Content-Type text/csv.

Вот пример вызова:

# split-oriented
curl http://localhost:5001/invocations -H 'Content-Type: application/json' -d '{
    "columns": ["a", "b", "c"],
    "data": [[1, 2, 3], [4, 5, 6]]
}'

# record-oriented (fine for vector rows, loses ordering for JSON records)
curl http://localhost:5000/invocations -H 'Content-Type: application/json; format=pandas-records' -d '[[1, 2, 3], [4, 5, 6]]'

Команда прогнозирования принимает те же входные форматы. Формат указывается в качестве аргументов командной строки.

Команды:

  • serve развертывает модель как локальный сервер REST API.

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

  • Predict использует модель для создания прогноза для локального файла CSV или JSON.

    Мы показываем модель для развертывания:

cd ~/katacoda-notebooks/10_mlflow_serving
cat train.py

Мы запускаем образец развертывания модели:

cd ~/katacoda-notebooks/10_mlflow_serving
MLFLOW_TRACKING_URI=file:///root/mlflow mlflow run --experiment-name serve-sample .

Разворачиваем модель в фоновом режиме:

MLFLOW_TRACKING_URI=file:///root/mlflow mlflow models serve --model-uri runs:/[PASTE-THE-RUN-ID-HERE]/model --port 5001 &

Осталось запустить прогноз:

curl -d '{"columns":[0],"index":[0,1],"data":[[1],[-1]]}' -H 'Content-Type: application/json' http://localhost:5001/invocations

Мы узнали, как развертывать разные ворклоды машинного обучения с помощью MLflow.

Статья подготовлена в преддверии старта курса MLOps от OTUS. По ссылке вы сможете абсолютно бесплатно посмотреть демоурок курса, а также узнать подробнее о курсе.

Комментарии (0)