Почему управление экспериментами в ML - это боль, и как MLflow её решает
Каждый ML-инженер проходил этот сценарий. Вы запускаете серию экспериментов в Jupyter ноутбуках, через неделю возвращаетесь к лучшему результату и не можете вспомнить, какой именно набор гиперпараметров его дал. Артефакты разбросаны по папкам, метрики записаны в комментариях к коду, а воспроизвести ту самую модель, которая показывала 0.94 ROC-AUC на тестовой выборке, невозможно. Это не недостаток дисциплины. Это следствие отсутствия единой системы трекинга.
MLflow решает эту проблему централизацией всего жизненного цикла эксперимента. Платформа логирует каждый запуск: код, данные, гиперпараметры, метрики и выходные артефакты. Вы получаете единый источник истины для всех экспериментов команды. Четыре компонента MLflow закрывают полный цикл работы с моделью: Tracking фиксирует параметры и результаты, Projects упаковывает код в воспроизводимый формат, Models стандартизирует упаковку обученных моделей, Registry управляет версиями и стадиями жизненного цикла.
На практике это означает: вы открываете UI, видите таблицу всех запусков с метриками, сортируете по нужному показателю и одним кликом достаете модель, артефакты и параметры. Никаких догадок, никаких потерянных файлов. Дальше разберем настройку и код, который можно скопировать в свой проект.
Установка и первый запуск MLflow за 5 минут
Установка MLflow выполняется одной командой в терминале. Никаких сложных зависимостей, платформа работает на Python 3.8 и выше.
pip install mlflowПосле установки запустите UI командой:
mlflow uiИнтерфейс откроется по адресу http://127.0.0.1:5000. Вы увидите пустую таблицу экспериментов. По умолчанию все артефакты и метаданные сохраняются в локальную папку mlruns в текущей директории. Для персональных проектов этого достаточно. Для командной работы потребуется настроить Tracking Server.
Настройка Tracking Server для командной работы
Локальный режим хранит данные на диске одного разработчика. Команда не видит чужие запуски, а резервное копирование ложится на самого инженера. Tracking Server решает эту проблему: он поднимается как отдельный сервис, принимает запросы от всех участников и хранит данные в централизованной базе.
Базовая команда для запуска сервера с PostgreSQL и артефактами в S3-совместимом хранилище:
mlflow server \
--backend-store-uri postgresql://user:password@host:5432/mlflow \
--default-artifact-root s3://my-bucket/mlflow-artifacts \
--host 0.0.0.0 \
--port 5000После запуска каждый участник команды указывает URI сервера через переменную окружения:
export MLFLOW_TRACKING_URI=http://mlflow-server:5000Теперь все запуски логируются в общую базу, артефакты уходят в S3, а UI доступен по одному адресу для всей команды. SQLite подходит для прототипов, но при параллельных запросах от нескольких пользователей упирается в блокировки. PostgreSQL снимает это ограничение.
Логирование экспериментов: модели, метрики и гиперпараметры
Базовый цикл логирования в MLflow строится вокруг концепции run - одного выполнения кода эксперимента. Вы открываете run, фиксируете параметры, метрики и артефакты, закрываете run. Минимальный пример на Python:
import mlflow
with mlflow.start_run():
mlflow.log_param("learning_rate", 0.01)
mlflow.log_param("batch_size", 32)
mlflow.log_metric("accuracy", 0.87)
mlflow.log_metric("f1_score", 0.84)
mlflow.sklearn.log_model(model, "model")MLflow поддерживает основные ML-фреймворки через встроенные модули: mlflow.sklearn, mlflow.pytorch, mlflow.tensorflow, mlflow.keras, mlflow.spark, mlflow.xgboost, mlflow.lightgbm. Каждый модуль сохраняет модель в стандартизированном формате вместе с окружением, что гарантирует загрузку без конфликтов зависимостей.
Nested runs решают задачу иерархической организации: родительский run содержит общие настройки, дочерние - отдельные итерации подбора гиперпараметров или кросс-валидации. Это упрощает навигацию в UI, когда эксперимент состоит из десятков запусков.
Сравнение нескольких моделей в одном эксперименте
Типичная задача: проверить три алгоритма на одном датасете и выбрать лучший. MLflow позволяет организовать это в одном эксперименте с автоматическим логированием каждой итерации:
import mlflow
from sklearn.linear_model import LogisticRegression
from sklearn.ensemble import RandomForestClassifier, GradientBoostingClassifier
models = {
"LogisticRegression": LogisticRegression(max_iter=1000),
"RandomForest": RandomForestClassifier(n_estimators=100),
"GradientBoosting": GradientBoostingClassifier(n_estimators=100)
}
for model_name, model in models.items():
with mlflow.start_run(run_name=model_name):
model.fit(X_train, y_train)
y_pred = model.predict(X_test)
accuracy = accuracy_score(y_test, y_pred)
mlflow.log_param("model_type", model_name)
mlflow.log_metric("accuracy", accuracy)
mlflow.sklearn.log_model(model, model_name)В UI вы получаете таблицу, где каждая строка - отдельный запуск с колонками параметров и метрик. Сортировка по accuracy одним кликом показывает победителя. Это экономит часы ручного сравнения.
Логирование артефактов: графики, датасеты и кастомные файлы
Метрики агрегируют результат в одно число, но для полной воспроизводимости нужны артефакты: матрицы ошибок, графики распределений, срезы данных, файлы зависимостей. MLflow сохраняет любые файлы через log_artifact() и log_artifacts():
import matplotlib.pyplot as plt
import seaborn as sns
from sklearn.metrics import confusion_matrix
with mlflow.start_run():
# Матрица ошибок
cm = confusion_matrix(y_test, y_pred)
plt.figure(figsize=(8, 6))
sns.heatmap(cm, annot=True, fmt='d', cmap='Blues')
plt.title('Confusion Matrix')
plt.savefig('confusion_matrix.png')
mlflow.log_artifact('confusion_matrix.png')
# Сохранение тестовой выборки
test_data = pd.concat([X_test, y_test], axis=1)
test_data.to_csv('test_dataset.csv', index=False)
mlflow.log_artifact('test_dataset.csv')
# Фиксация окружения
mlflow.log_artifact('requirements.txt')Артефакты доступны в UI на вкладке Artifacts конкретного run. Загрузить их программно можно через mlflow.artifacts.download_artifacts() - это критично для аудита модели или повторного анализа через полгода после эксперимента.
Автоматизация оценки моделей с mlflow.evaluate()
Ручное вычисление метрик отнимает время и приводит к расхождениям: разные инженеры считают precision по разным формулам, забывают про confidence intervals, не фиксируют порог классификации. mlflow.evaluate() стандартизирует этот процесс. Функция принимает модель и датасет, автоматически вычисляет набор метрик и логирует результаты в текущий run.
Базовый вызов для задачи классификации:
import mlflow
model_uri = "runs:/abc123def456/model"
eval_data = X_test.copy()
eval_data['label'] = y_test
with mlflow.start_run():
results = mlflow.evaluate(
model=model_uri,
data=eval_data,
targets="label",
model_type="classifier"
)Функция поддерживает классификацию, регрессию и кастомные модели. Для классификации автоматически вычисляются accuracy, precision, recall, f1-score, ROC-AUC, log-loss. Для регрессии - MSE, RMSE, MAE, R². Все метрики визуализируются в UI: кривые обучения, confusion matrix, precision-recall кривая генерируются автоматически и сохраняются как артефакты.
Кастомные метрики и пороги для бизнес-задач
Стандартные метрики не всегда отражают бизнес-ценность модели. MLflow позволяет определить свою функцию метрики и передать её в evaluate():
from sklearn.metrics import make_scorer, fbeta_score
def profit_metric(y_true, y_pred):
# Бизнес-логика: true positive приносит $100, false positive стоит $30
cm = confusion_matrix(y_true, y_pred)
tp, fp = cm[1, 1], cm[0, 1]
return tp * 100 - fp * 30
with mlflow.start_run():
results = mlflow.evaluate(
model=model_uri,
data=eval_data,
targets="label",
model_type="classifier",
extra_metrics=[make_scorer(profit_metric, greater_is_better=True)]
)Пороговые значения для классификации задаются через параметр thresholds. Это полезно, когда цена ошибок первого и второго рода асимметрична: например, в детекции мошенничества false negative стоит дороже false positive. evaluate() автоматически строит кривую precision-recall для разных порогов и логирует оптимальное значение по заданной метрике.
Воспроизводимость с MLflow Model Registry: версионирование и загрузка моделей
Tracking решает проблему фиксации экспериментов. Registry решает проблему жизненного цикла модели. Вы регистрируете лучшую модель из run, присваиваете ей версию и двигаете по стадиям: Staging (тестирование), Production (боевое использование), Archived (историческая версия).
Регистрация модели из кода:
with mlflow.start_run() as run:
mlflow.sklearn.log_model(model, "model")
model_uri = f"runs:/{run.info.run_id}/model"
mlflow.register_model(model_uri, "customer_churn_predictor")После регистрации модель получает версию 1. Следующая регистрация с тем же именем создаст версию 2. В UI вы видите все версии, их стадии и можете переключать их одним кликом. API даёт те же возможности:
from mlflow.tracking import MlflowClient
client = MlflowClient()
client.transition_model_version_stage(
name="customer_churn_predictor",
version=2,
stage="Production"
)Загрузка модели по алиасу или версии в production-окружении
В production-коде вы не хотите хардкодить версию модели. Алиасы решают эту проблему: вы назначаете алиас champion на текущую production-модель и загружаете её по алиасу. При переключении на новую версию алиас переназначается, код не меняется:
# Назначение алиаса
client.set_registered_model_alias(
"customer_churn_predictor",
"champion",
version=2
)
# Загрузка в production
model = mlflow.pyfunc.load_model(
"models:/customer_churn_predictor@champion"
)
predictions = model.predict(new_data)Этот паттерн интегрируется с CI/CD пайплайнами: после прохождения тестов новая версия автоматически получает алиас champion, и все сервисы подхватывают её без перезапуска. Для отката достаточно переключить алиас на предыдущую версию одной командой API.
Интеграция MLflow с Databricks: масштабирование для enterprise
В Databricks MLflow предустановлен и интегрирован с платформой на уровне инфраструктуры. Tracking Server настраивается автоматически для каждого workspace, артефакты сохраняются в DBFS (Databricks File System) без дополнительной конфигурации S3-бакетов. Jobs API позволяет запускать MLflow-проекты по расписанию с автоматическим логированием результатов.
Управление доступом работает через штатную систему permissions Databricks: вы можете ограничить видимость экспериментов до конкретных пользователей или групп. Для enterprise-команд с требованиями аудита это критично. Эксперименты, запущенные из Databricks Notebooks, автоматически логируются в MLflow - инженеру не нужно писать дополнительный код для трекинга.
Databricks Feature Store интегрируется с MLflow Tracking: все признаки, использованные при обучении, автоматически связываются с run. При загрузке модели для инференса Feature Store гарантирует, что признаки вычисляются по тем же формулам, что и при обучении. Это закрывает одну из главных причин расхождения метрик между трейном и production.
Ограничения MLflow и альтернативы: когда стоит смотреть дальше
MLflow - мощный инструмент, но не универсальное решение. При количестве runs свыше 100 000 Tracking Server на SQLite начинает деградировать: UI тормозит, поиск по метрикам замедляется. Переход на PostgreSQL решает проблему до определенного предела, но при очень высокой нагрузке потребуется шардирование базы, которое MLflow не поддерживает из коробки.
Отсутствие встроенной оркестрации - второе ограничение. MLflow не управляет вычислительными ресурсами и не строит пайплайны. Для сложных DAG с условными переходами, параллельными ветками и автоматическим перезапуском упавших задач потребуется связка с Airflow, Kubeflow Pipelines или Dagster. MLflow в этой связке отвечает за трекинг и версионирование, оркестратор - за выполнение.
Weights & Biases предлагает более богатую визуализацию: интерактивные графики, сравнение runs в реальном времени, встроенные дашборды для бизнес-заказчиков. Kubeflow закрывает оркестрацию и управление инфраструктурой для Kubernetes-окружений. Выбор зависит от масштаба команды и требований: MLflow оптимален для старта и средних команд (3-15 инженеров), для сложных пайплайнов на Kubernetes имеет смысл рассмотреть Kubeflow, для исследовательских команд с фокусом на визуализацию - Weights & Biases. При этом MLflow остается стандартом де-факто для трекинга экспериментов и часто используется в комбинации с другими инструментами, а не вместо них.