MLOps Path

4.1.2 · блок 4

Артефакты и воспроизводимость

Артефакты и воспроизводимость

Зачем это нужно

«У меня локально accuracy 0.91, а в prod модель ведёт себя иначе» — классическая боль. Причины часто не в «магии prod», а в разных версиях кода, данных и окружения. MLOps начинается с дисциплины артефактов: всё, что влияет на результат, должно быть зафиксировано, версионировано и связано друг с другом.

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

Основные идеи

Что такое ML-артефакт. Любой объект, который можно сохранить и передать дальше по pipeline:

| Артефакт | Пример | Где хранить |

|----------|--------|-------------|

| Код | commit SHA, tag | Git |

| Данные | snapshot parquet, версия датасета | S3 / data lake + manifest |

| Модель | `.pkl`, ONNX, SavedModel | Model registry, artifact store |

| Окружение | `requirements.txt`, Docker image digest | Git + container registry |

| Конфиг обучения | YAML hyperparameters | Git / experiment tracker |

| Метрики | F1, calibration plot | ClearML / MMS |

Reproducibility triad (триада воспроизводимости).

1. Code — тот же commit.

2. Data — тот же snapshot (или детерминированный query + seed).

3. Environment — тот же образ или lockfile.

Изменение любого leg triad — новый эксперимент, не «мелкий фикс».

Детерминизм vs стохастика. Обучение с random_state=42 и фиксированным порядком батчей даёт повторяемый результат. На GPU некоторые ops недетерминированы — документируйте это в model card.

Immutable artifacts. Образ scorer:latest перезаписали — старая версия потеряна. Правило курса: тег = gitSha-buildNumber или semver + digest. Никогда не деплоить mutable latest в prod.

Lineage (происхождение). Цепочка: dataset v3 → train job #8842 → model v1.2.3 → deploy release 17. Без lineage вы не ответите на вопрос «какие данные были в prod вчера в 3:00».

Model serialization. scikit-learn: joblib.dump / load. Важно: версия sklearn при save и load должна совпадать (или быть совместимой). pickle и joblib.load могут выполнить произвольный код — загружайте только доверенные, проверенные артефакты. Для production предпочитайте подписанные артефакты; где подходит, переносимые форматы ONNX или skops. В CI — тест «загрузить модель из artifact и вызвать predict на фикстуре».

Конфиг vs код. Гиперпараметры в YAML рядом с кодом или в experiment tracker — не «зашиты в ноутбук ячейкой 47». Notebook — прототип; prod pipeline — скрипт + config.

Как это выглядит на практике

Команда переобучает churn-модель:

1. Data engineer публикует churn_features_2026-07-28.parquet с manifest (hash, row count, schema version).

2. Train job (локально или в Argo WF) читает manifest, логирует hash в ClearML.

3. На выходе: model.joblib, metrics.json, confusion_matrix.png — все привязаны к Task ID в ClearML.

4. Jenkins собирает inference-образ с pin scikit-learn==1.4.2 из lockfile; model копируется в образ или монтируется из registry по URI models/churn/v1.2.3.

5. MMS регистрирует запись: model id, ClearML task, image tag, approver.

Через месяц инцидент: drift по фиче tenure. SRE открывает MMS → видит lineage → поднимает тот же train config + dataset snapshot → воспроизводит обучение → сравнивает метрики.

Anti-pattern (избегайте):


model_final_v2_REALLY_FINAL.pkl на рабочем столе
requirements «поставил вручную, вроде работает»

Что сделать после занятия

Официальные материалы

Открыть интерактивную версию