Хакатон – это всегда повышенный стресс, потому что за короткое время нужно найти лучшее решение для поставленной задачи. Вам придется обучить десятки моделей, найти оптимальную комбинацию гиперпараметров и при этом координировать действия с командой. Чтобы минимизировать хаос совместной разработки, предлагаю воспользоваться MLflow Tracking. С его помощью вы сможете синхронизировать усилия всей команды, а также иметь доступ к истории всех экспериментов: к обученным моделям, их гиперпараметрам, метрикам и не только. 

Суть проблемы

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

Что такое MLflow?

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

Сразу отмечу, что я не буду подробно разбирать возможности Mlflow. Об этом достаточно написано в интернете и всю необходимую информацию вы можете найти в документации. Цель этой статьи – дать краткое представление о том, как реализовать удаленный сервер MLflow Tracking, даже если у читателя нет опыта взаимодействия с удаленными виртуальными машинами (ВМ). 

Выбор хостинга

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

Сколько это стоит?

Расходы будут зависеть от параметров виртуальной машины. Обычно хакатон длится 2-3 дня, что обойдется примерно в 100-300 рублей. 

Многие хостинги, Yandex Cloud в том числе, предоставляют стартовые гранты, поэтому от вас могут даже не потребоваться дополнительные вложения. Подробнее о гранте Yandex Cloud читайте здесь.

План

  1. Регистрация на Yandex Cloud и привязка платежного аккаунта.

  2. Создание SSH-ключей, виртуальной машины и подключение.

  3. Разворачивание сервера MLflow Tracking.

  4. Настройка локальной машины для подключения к серверу MLflow.

1. Регистрация на Yandex Cloud и привязка платежного аккаунта

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

2. Создание SSH-ключей, виртуальной машины и подключение

Прежде, чем приступить к созданию виртуальной машины, нужно на своем компьютере создать пару SSH-ключей. Они нужны для подключения к удаленной ВМ. Процесс создания SSH-ключей и виртуальной машины весьма прост – смотрите видео от Yandex Cloud.

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

Важные моменты:

  • Размер диска ВМ я рекомендую выбирать не менее 18гб (значение по умолчанию), потому что на диске виртуальной машины будут храниться все ваши обученные модели. Лучше выбрать 40гб и более – на цене это отразится незначительно.

Скриншот с интерфейсом Yandex Cloud
Скриншот с интерфейсом Yandex Cloud
  • Какие-либо изменения в разделе вычислительных ресурсов, в отличие от размера диска, существенно влияют на цену ВМ. Здесь следует обратить внимание на две опции: 
    - Гарантированная доля vCPU. По умолчанию стоит 100%, но если вы выберете, например, 50%, то ничего страшного не произойдет, а ценник существенно снизится.
    - Тип BM: прерываемая. Прерываемая ВМ работает не более 24 часов и может быть остановлена в любой момент, но зато она предоставляется с большой скидкой. После остановки все данные сохраняются. Чтобы продолжить работу, запустите ВМ повторно.
    По моему опыту, ВМ останавливалась не чаще, чем раз в сутки.

Скриншот с интерфейсом Yandex Cloud
Скриншот с интерфейсом Yandex Cloud
  • Наличие статического публичного IP-адреса виртуальной машины. По умолчанию виртуальной машине присваивается динамический публичный IP, который меняется при ее остановке. Поскольку прерываемая ВМ останавливается раз в 24 часа, то вам придется менять IP-адрес в конфигурационном файле вашего DS-проекта, иначе вы не сможете подключиться к серверу MLflow. Как зарезервировать статический публичный IP-адрес, читайте здесь.

Если вы в первый раз поднимаете удаленный сервер MLflow, то будет достаточно выбрать минимальные параметры ВМ, сделать ее прерываемой и оставить динамический IP по умолчанию. Для хакатона же имеет смысл зарезервировать статический IP и НЕ делать виртуальную машину прерываемой. Так вы избавите себя от лишнего "головняка" с периодическим включением ВМ и обновлением IP-адреса в ходе работы над проектом. 

Важно

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

3. Разворачивание сервера MLflow Tracking

Источник: min.io
Источник: min.io

На этой картинке показано, как происходит взаимодействие сервисов, поднятых в контейнерах на ВМ, и локальной машины разработчика. Когда вы обучили модель, информация об этом передается в MLflow Tracking, который в свою очередь распределяет ее между базой данных PostgreSQL и S3-хранилищем MinIO. В PostgreSQL будут храниться гиперпараметры модели и полученные метрики. В MinIO – обученные модели и прочие артефакты – например, изображения, если вам необходимо логировать графики.   

Подробнее об этой архитектуре читайте на сайте MinIO.

Узнать больше о других вариантов архитектуры MLflow можно здесь.

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

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

git clone https://github.com/pestich/mlflow-server.git

Разберемся, какие файлы вы сейчас скачали и зачем они нужны:

  • docker-compose.yml  и папка mlflow_image необходимы для создания контейнеров Docker для база данных, S3-хранилища и непосредственно MLflow;

  • .env – файл с переменными окружения. Он будет нужен при создании контейнеров и выполнении скрипта main.py;

  • create_bucker.py – скрипт для автоматического создания бакета в S3-хранилище MinIO;

  • main.py – скрипт, который последовательно выполнит ряд необходимых команд. 

  • run_example.py – скрипт с тестовым запуском эксперимента.

После клонирования репозитория на ВМ должна появиться папка mlflow-server. Проверить это можно командой ls (используется для вывода содержимого каталогов и информации о файлах).

Пример вывода в консоли
Пример вывода в консоли

Перейдем в папку mlflow-server и запустим скрипт main.py:

# команда для перехода в папку mlflow-server
сd mlflow-server 

# команда для запуска main.py
python3 main.py

Как уже говорилось выше, main.py последовательно выполняет определенные команды. Разберем их:

# установка Docker
curl -fsSL https://get.docker.com -o get-docker.sh
sudo sh get-docker.sh

# разворачивание Docker-контейнеров
sudo docker compose up -d --build

# установка менеджера пакетов pip
sudo apt install python3-pip

# установка библиотек boto3 и dotenv
# они необходимы для взаимодействия с S3-хранилищем и переменными окружения
pip3 install boto3 python-dotenv

# создание бакета в S3-хранилище MinIO
python3 create_bucket.py

Скрипт будет выполняться примерно 5 минут. В течение этого времени вам будет нужно подтвердить установку pip, введя в консоли символ «Y».

Пример вывода в консоли
Пример вывода в консоли

В конце вы увидите сообщение об успешном создании бакета в MinIO.

Пример вывода в консоли
Пример вывода в консоли

Теперь ваш MLflow-сервер готов! Чтобы убедиться в этом, перейдите по ссылке ниже, предварительно указав в ней публичный IP-адрес вашей виртуальной машины:

http://ПУБЛИЧНЫЙ_IP_ВАШЕЙ_ВМ:5000

Обратите внимание, что нужно использовать именно «http:», а не «https:».

Интерфейс MLflow
Интерфейс MLflow

Если при переходе по ссылке вы видите такую страницу, то MLflow запущен успешно. Но давайте в этом убедимся и выполним скрипт run_example.py. Он загрузит один из датасетов sklearn и обучит модель RandomForestRegressor.

# команда для запуска тестового эксперимента в MLflow
python3 run_example.py

После выполнения run_example.py вы увидите сообщение об успешном завершении эксперимента.

Пример вывода в консоли
Пример вывода в консоли

Тем временем в интерфейсе MLflow уже должна появиться запись об этом запуске.

Имя запуску присваивается автоматически, если оно явно не было указано. В данном случае он называется "delicate-stork-784". Перейдем в него и посмотрим, какие данные были залогированы.

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

Гиперпараметры
Гиперпараметры
Метрики
Метрики

MLflow автоматически рассчитывает ряд метрик в зависимости от типа модели. При этом мы явно указали логировать нашу собственную метрику "my_metric" со значением 0.

Информация о модели
Информация о модели

На этой же странице ниже вы найдете информацию об обученной модели. MLflow сразу генерирует код, для загрузки обученной модели из S3-хранилища.

MLflow поддерживает автологирование моделей из ряда библиотек, таких как sklearn, и будет логировать все гиперпараметры и возможные метрики. Ознакомиться со списком библиотек, поддерживаемых в автологировании, можно по ссылке. Ниже код из run_example.py, в котором используется автологирование.

# Импорт необходимых библиотек
import mlflow
import os
from sklearn.datasets import load_diabetes
from sklearn.model_selection import train_test_split
from sklearn.metrics import mean_absolute_error
from sklearn.ensemble import RandomForestRegressor
from dotenv import load_dotenv

# Загрузка переменных окружения из файла .env
load_dotenv()

# Загрузка датасета Diabetes из scikit-learn
df = load_diabetes()

# Разделение данных на обучающий и тестовый наборы
X_train, X_test, y_train, y_test = train_test_split(df.data, df.target)

# Установка URI для отслеживания MLflow с использованием переменной окружения
mlflow.set_tracking_uri(os.getenv("MLFLOW_TRACKING_URI"))

# Установка имени эксперимента в MLflow
mlflow.set_experiment('Example Project')

# Включение автоматического логирования параметров и метрик MLflow
mlflow.autolog()

print('Starting...')

# Создание нового run в рамках эксперимента в MLflow
with mlflow.start_run():
    rf = RandomForestRegressor(n_estimators=100, max_depth=6, max_features=3)
    rf.fit(X_train, y_train)
    prediction = rf.predict(X_test)

    # Явное логирование метрик
    mlflow.log_metric("my_metric", 0) 

print('The experiment was successfully completed')

Если вы используете модель, которая не поддерживается автологированием, то можно явно указать какие гиперпараметры и метрики нужно отслеживать.

# Создание нового run в рамках эксперимента в MLflow
with mlflow.start_run():
    # Задаем параметры модели
    params = {'n_estimators':100, 
              'max_depth':6}
    
    # Инициализация модели RandomForestRegressor с указанными параметрами
    rf = RandomForestRegressor(**params)

    # Обучение модели на обучающих данных
    rf.fit(X_train, y_train)

    # Предсказание на тестовых данных
    prediction = rf.predict(X_test)

    # Вычисление средней абсолютной ошибки (MAE)
    MAE = mean_absolute_error(y_test, prediction)

    # Явное логирование параметров
    mlflow.log_params(params)

    # Явное логирование метрики
    mlflow.log_metric("my_metric_MAE", MAE)
    
    # Явное логирование модели
    mlflow.sklearn.log_model(rf, 'RandomForestRegressor')

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

4. Настройка локальной машины для подключения к серверу MLflow

Чтобы mlflow мог отслеживать ваши эксперименты с локальной машины, у вас должна быть установлена библиотека mlflow, а в коде проекта в mlflow.set_tracking_uri() в качестве аргумента указан адрес MLflow-сервера.

import mlflow

MLFLOW_TRACKING_URI="http://ПУБЛИЧНЫЙ_IP_ВАШЕЙ_ВМ:5000"

mlflow.set_tracking_uri(MLFLOW_TRACKING_URI)

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

После клонирования проекта нужно будет установить в ваше виртуальное окружение библиотеки из requirements.txt и указать в файле .env IP-адрес вашей ВМ. В файла .env находится только MLFLOW_TRACKING_URI, необходимая для подключения к серверу MLflow. Подробности вы найдете в README.md репозитория.

Заключение

В этой статье представлен необходимый минимум для создания удаленного сервера MLflow Tracking. Дополнительно к этому минимуму можно поднять сервисы для отслеживания работы контейнеров и базы данных: Portainer и pgAdmin. Как это сделать – смотрите в этом видео. А если вы хотите лучше разобраться в теме MLOps, то рекомендую пройти бесплатный курс на ODS.

Успехов на хакатонах!

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