MLflow Made Easy: руководство для начинающих

Упростите рабочий процесс машинного обучения с помощью MLflow: подробный обзор

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

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

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

Если на вашем компьютере еще нет mlflow, не беда! Просто введите это в командную строку (или терминал): pip install mlflow. Или, если вы используете «conda», попробуйте это: conda install -c conda-forge mlflow.

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

Начнем с импорта необходимых библиотек:

# Import necessary libraries
import mlflow
import pandas as pd

from sklearn.datasets import load_iris
from sklearn.linear_model import LogisticRegression
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score, precision_score, recall_score

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

# Load Iris dataset
dataset = load_iris()

# Split dataset into train and test
X_train, X_test, y_train, y_test = train_test_split(dataset.data, dataset.target, test_size=0.2, stratify=dataset.target)

# Checkout train and test datasets
print(f"Train set shape: {X_train.shape[0]} rows, {X_train.shape[1]} columns", )
print(f"Test set shape: {X_test.shape[0]} rows, {X_test.shape[1]} columns")
print(f"Columns names: {dataset.feature_names}")

# Output:
# Train set shape: 120 rows, 4 columns
# Test set shape: 30 rows, 4 columns
# Columns names: ['sepal length (cm)', 'sepal width (cm)', 'petal length (cm)', 'petal width (cm)']

Приготовьтесь: мы строим аккуратную модель классификации, используя логистическую регрессию с помощью mlflow, чтобы отслеживать наши эксперименты!

# Set the experiment for MLflow
mlflow.set_experiment('Baseline Model')

# Start an MLflow run context
with mlflow.start_run():
    # Initialize a LogisticRegression model
    model = LogisticRegression()
    
    # Train the model on the training data
    model.fit(X_train, y_train)

    # Make predictions on the test data
    y_pred = model.predict(X_test)

    # Calculate various evaluation metrics
    accuracy = accuracy_score(y_test, y_pred)
    precision = precision_score(y_test, y_pred, average='macro')
    recall = recall_score(y_test, y_pred, average='macro')

    # Log the evaluation metrics to the MLflow run
    mlflow.log_metric('accuracy', accuracy)
    mlflow.log_metric('precision', precision)
    mlflow.log_metric('recall', recall)

    # Log the trained model to the MLflow run
    mlflow.sklearn.log_model(model, 'model')

    # Set developer information as a tag
    mlflow.set_tag('developer', 'Sagar Thacker')

    # Set preprocessing details as a tag
    mlflow.set_tag('preprocessing', 'None')

    # Set the model type as a tag
    mlflow.set_tag('model', 'Logistic Regression')

Давайте разберемся, что делает приведенный выше код:

  1. Код начинается с установки для эксперимента MLflow значения «Базовая модель». Это означает, что запуски эксперимента и связанные с ним метаданные будут организованы под названием этого эксперимента в системе отслеживания MLflow.
  2. Внутри блока with mlflow.start_run(): инициируется новый контекст запуска MLflow. Этот контекст инкапсулирует отслеживание всей информации, связанной с этим конкретным запуском в рамках эксперимента.
  3. Мы обучаем модель логистической регрессии, прогнозируем результаты на основе тестовых данных и рассчитываем метрики для расчета производительности модели.
  4. Вычисленные метрики оценки (точность, точность и полнота) регистрируются как метрики в рамках текущего запуска MLflow с помощью функции mlflow.log_metric().
  5. Обученная модель логистической регрессии регистрируется как артефакт при запуске MLflow с помощью функции mlflow.sklearn.log_model().
  6. Дополнительные метаданные связываются с запуском путем установки тегов с помощью mlflow.set_tag().

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

А вот и самое интересное! Откройте командную строку (или терминал) и введите следующее: mlflow ui. Волшебство! Вы увидите, как пользовательский интерфейс отслеживания оживает в http://localhost:5000.

Нажмите на Run Name, чтобы просмотреть подробности эксперимента. Вы увидите такую ​​страницу:

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

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

Эксперимент

Представьте себе эксперимент в виде большого крутого зонтика, в котором собраны все ваши любопытные мысли и тесты. Допустим, вы начинаете с эксперимента под названием Baseline Model — это похоже на вашу первую большую идею. Затем следует еще один эксперимент, Vanilla Models, в котором вы возитесь с такими вещами, как случайный лес и SVM. И, эй, вы могли бы пойти еще глубже, попробовав такие вещи, как настройка гиперпараметров. Каждый из них — это новое «experiment» — новое приключение.

Экспериментальный запуск

Кстати, в каждом из этих приключений, когда вы пытаетесь создать или обучить модель, это похоже на маленький эксперимент внутри большого — это «experiment run». Например, когда мы работали над нашей базовой моделью, был создан эксперимент под названием illustrious-mule-887. И угадай что? Компьютер достаточно умен, чтобы автоматически придумывать эти имена! Или, если у вас есть воображение, вы можете дать своему эксперименту собственное имя.

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

Вот и все: отслеживание экспериментов — это ваш метод отслеживания всех замечательных вещей, которые вы создаете.

Присмотримся к MLflow

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

  • Отслеживание MLflow: API для регистрации параметров, кода и результатов эксперимента и сравнения их с интерактивным пользовательским интерфейсом. (Мы видели это в нашем примере выше)
  • Модели MLflow.Формат упаковки моделей и инструментов, упрощающий развертывание одной и той же модели (из любой библиотеки ML) для пакетной оценки и оценки в реальном времени на таких платформах, как Docker, Apache Spark, Azure ML, и AWS SageMaker. (проверьте формат зарегистрированной модели)
  • Реестр моделей MLflow. Управление версиями моделей, переходами между этапами и аннотациями можно осуществлять совместно с помощью реестра моделей MLflow, который служит центральным хранилищем моделей.

Отслеживание Млфлоу

Ммм… если бы вы спросили себя: «Где MLflow хранит все эти данные?»; тогда вы задаете правильный вопрос.

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

Ниже приведен снимок моего каталога mlruns:

.
├── mlruns
│   ├── 0
│   │   └── meta.yaml
│   ├── 758224673514181683                    <- (experiment id of Baseline Model)
│   │   ├── 33059883f56c4f208de0afd8eed42315  <- (run id of Logistic Regression run)
│   │   │   ├── artifacts                     <- (model stored here)
│   │   │   ├── meta.yaml
│   │   │   ├── metrics                       <- (metrics stored here)
│   │   │   ├── params                        <- (params stored here)
│   │   │   └── tags                          <- (tags stored here)
│   │   └── meta.yaml
│   └── models
└── notebook.ipynb                            <- (my code file)

# You can cross check the id's associated with the 
# experiement & experiment run in the above images.

Как выполняются записи MLflow и возникают артефакты?

MLflow использует два компонента для хранения:

  1. Внутреннее хранилище:
     – используется для сохранения объектов MLflow, таких как прогоны, параметры, метрики, теги, примечания, метаданные и т. д.
     – Внутреннее хранилище может храниться в локальные файлы (как в нашем примере выше), в базу данных, совместимую с SQLAlchemy, или удаленно на сервер отслеживания.
  2. Хранилище артефактов:
     — используется для сохранения артефактов, таких как файлы, модели, изображения, объекты в памяти, сводка модели и т. д.
     — Хранилище артефактов может быть сохранялся в локальных файлах (как в нашем примере выше — папка артефактов в эксперименте) и в различных вариантах удаленного хранения файлов, таких как корзина S3.

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

Существует 6 сценариев конфигурации для настройки серверной части и хранилища артефактов.

Сценарий, в котором серверная часть и хранилище артефактов настраиваются на локальном хосте или в локальном каталоге, называется MLflow на локальном хосте. Это первый сценарий в списке отслеживания MLflow.

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

А пока я рекомендую посетить официальную страницу документации для подробного обзора этих шести сценариев.

Модели Млфлов

Модель MLflow — это стандартный формат для упаковки ваших моделей машинного обучения. Это позволяет нам использовать модель в различных последующих инструментах. Думайте об этом как о помещении вашей модели в коробку с разными этикетками, чтобы разные инструменты знали, как ее открыть и использовать. Они называют эти разные форматы «ароматами».

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

  1. Обслуживание в реальном времени. Возможно, вы захотите обслуживать свою модель в режиме реального времени через REST API, чтобы она могла делать прогнозы, как только поступят новые данные.
  2. Пакетный вывод. В качестве альтернативы вы можете использовать ту же модель в системе пакетной обработки, такой как Apache Spark, где она обрабатывает большой объем данных в пакетном режиме.

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

Формат хранения

В нашем примере мы зарегистрировали нашу модель как вариант mlflow.sklearn.

# Log the trained model to the MLflow run (From above code snippet)
mlflow.sklearn.log_model(model, 'model')

Несколько ключевых понятий о модели MLflow:

  1. Каталог модели MLflow: каждая модель MLflow организована как каталог, содержащий различные файлы, включая файл MLmodel в корневом каталоге. Он определяет несколько вариантов, в которых можно просматривать модель.
  2. Файл модели ML. Все варианты, поддерживаемые конкретной моделью, описаны в файле модели ML, который обычно записывается в формате YAML. Этот файл служит справочным материалом для понимания того, как использовать модель и ее различные варианты в различных средах развертывания.
  3. Варианты. Варианты — это центральная концепция в моделях MLflow. Это соглашение, которое позволяет инструментам развертывания понять, как использовать модель. Определив различные варианты, вы можете адаптировать модель к различным сценариям развертывания без необходимости интегрировать каждый инструмент с каждой библиотекой машинного обучения.
  4. Стандартные варианты: MLflow включает предопределенные или «стандартные» варианты, которые поддерживают встроенные инструменты развертывания. Например, существует разновидность «функции Python» (python_function), которая объясняет, как запустить модель как функцию Python. Эти стандартные варианты упрощают последовательное развертывание моделей.
  5. Пользовательские варианты. Хотя MLflow предоставляет стандартные варианты, библиотеки также могут определять и использовать свои собственные варианты. Например, библиотека mlflow.sklearn может загружать модели как объекты конвейера scikit-learn для использования в коде, поддерживающем scikit-learn, или как общие функции Python для инструментов, которым нужно только применять модель.

Я также советую вам изучить такие понятия, как Model Signature and Input Examples. Модели MLflow позволяют нам включать дополнительные метаданные о входных, выходных данных и параметрах модели, которые могут использоваться последующими инструментами. Также продемонстрируйте пример допустимых входных данных для нашей модели.

Подробнее об этих темах можно прочитать в официальной документации.

Реестр моделей MLflow

Возможно, вы задаетесь вопросом: «Я уже сохранил или зарегистрировал свою модель как артефакт, так зачем мне знать о реестре модели?» Давайте рассмотрим сценарий: вы провели 5 экспериментов, и в каждом из них вы зарегистрировали модель. После тщательной оценки вы обнаружили, что четвертая модель работает лучше всего, и хотите внедрить ее в своем приложении.

Теперь возникают некоторые существенные вопросы:

  1. На какой стадии находится моя модель? Он находится в стадии постановки, производства или в архиве?

2. Если кто-то спросит, какой эксперимент и прогон позволили создать эту модель, можете ли вы дать ответ?

3. В будущем, когда вы создадите лучшую модель и захотите заменить текущую, как вы будете отслеживать старые модели?

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

Давайте посмотрим на реестр моделей в действии!

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

Зарегистрировать модель можно четырьмя способами:

  1. Пользовательский интерфейс Млфлов
  2. Вариант модели MLflow
  3. Модель регистра MLflow
  4. API отслеживания клиентов MLflow

Пользовательский интерфейс Млфлов

  1. Вы найдете большую синюю кнопку с именем Register Model в разделе «Артефакты» на странице сведений о запусках MLflow. Нажмите здесь!
  2. Если вы добавляете новую модель, укажите Model Name, чтобы однозначно идентифицировать модель. Если вы регистрируете новую версию существующей модели, вы можете выбрать существующее имя модели из раскрывающегося списка.
  3. Нажмите «Зарегистрироваться»!

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

Если вы нажмете Version 1 , вы сможете перейти на страницу сведений о версии. На странице сведений вы можете изменить этап модели, просмотреть происхождение модели (исходный запуск) и другие метаданные.

Вариант модели MLflow

Вы можете войти и зарегистрировать свою модель во время эксперимента. Вы можете использовать метод mlflow.<model_flavor>.log_model().

# Import libraries
# Prepare data and perform preprocessing...

with mlflow.start_run():
  model = LogisticRegression()

  # Train the model
  # Predict on test set
  # Log metrics and set tags

  # Log the sklearn model and register as version 1
  mlflow.sklearn.log_model(
    sk_model=model,
    artifact_path='model',
    registered_model_name='Logistic Regression'
  )

В приведенном выше фрагменте кода мы использовали вариант модели sklearn для регистрации и регистрации модели. Если зарегистрированная модель с таким именем не существует, метод регистрирует новую модель и создает версию 1. Если зарегистрированная модель с таким именем существует, метод создает новую версию модели.

Модель регистра MLflow

Для регистрации модели мы используем метод mlflow.regiter_model().

В приведенном выше методе есть два обязательных аргумента: model_uri и name .

model_uri:URI, ссылающийся на каталог MLmodel. Используйте URI runs:/, если вы хотите записать идентификатор запуска с моделью в реестре модели.

name: Название зарегистрированной модели.

# model_uri format: runs:/<RUN_ID>/<DIRECTORY_NAME>

result = mlflow.register_model(
    "runs:/f3f14056a49f48168af1b187f36e5aea/model", "Logistic Regression"
)

Если зарегистрированная модель с таким именем не существует, метод регистрирует новую модель и создает версию 1. Если зарегистрированная модель с таким именем существует, метод создает новую версию модели.

API отслеживания клиентов MLflow

В этом методе нам сначала нужно создать Model Name, иначе будет выброшено MLflowException.

from mlflow import MlflowClient

client = MlflowClient()

# Create Model Name if not exists
client.create_registered_model('Logistic Regression')

# Register the model
client.create_model_version(
  name='Logistic Regression',
  source='file:///<hidden-privacy>/mlruns/758224673514181683/817ae04665574b2abe5384144a9be015/artifacts/model',
  run_id="817ae04665574b2abe5384144a9be015'
)

source: исходный путь, в котором хранится модель MLflow. Вы можете скопировать полный путь к артефакту модели.

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

Бонус: использование реестра моделей во время развертывания.

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

Ответ кроется в API отслеживания клиентов MLflow.

from mlflow import MlflowClient

client = MlflowClient()

# Filter params
MODEL_NAME = 'Logistic Regression'
STAGE = 'Staging'

# Search for the model with MODEL NAME and 
# version number in descending order
mlflow_model = client.search_model_versions(
  filter_string=f"name = '{MODEL_NAME}'", 
  order_by=["version_number DESC"]
)

# Out of all the models, find the one with 
# the current stage as Staging.
# Log that model
for model in mlflow_model:
  if model.current_stage == STAGE:
    clf = mlflow.sklearn.load_model(model_uri=f"models:/{model.name}/{model.version}")
    break

Если вам понравился этот пост, поставьте ему аплодисменты! Поделитесь своими мыслями и предложите темы, которые вы хотели бы, чтобы я рассмотрел в комментариях.

Если вам нравятся подробные учебные пособия и руководства, обязательно подписывайтесь на них, чтобы узнать больше!