6.1.2 · блок 6
Качество данных и версионирование
Качество данных и версионирование
Зачем это нужно
«Garbage in, garbage out» — не лозунг, а ежедневная реальность. Модель может быть идеальной, но если в prod пришли NULL вместо возраста клиента или схема изменилась без уведомления — predictions деградируют молча. Data quality и версионирование — страховка от этого.
MLOps-инженер отвечает не только за код пайплайна, но за контракты: что считается «хорошими» данными и как фиксируется, какая версия dataset использовалась при обучении.
Основные идеи
Измерения качества данных (упрощённо).
| Измерение | Вопрос | Пример проверки |
|-----------|--------|-----------------|
| **Completeness** | Все ли поля заполнены? | `null_rate(age) < 0.01` |
| **Validity** | Значения в допустимых границах? | `age BETWEEN 0 AND 120` |
| **Uniqueness** | Нет ли дубликатов ключей? | `count(distinct user_id) = count(*)` |
| **Timeliness** | Данные свежие? | `max(event_ts) > now() - 1h` |
| **Consistency** | Согласованы ли связанные поля? | `if status='closed' then close_date IS NOT NULL` |
Data validation vs model validation. Model validation — hold-out, cross-val, метрики ML. Data validation — до обучения: «можно ли вообще запускать train job на этом snapshot?». Если validation failed — train не стартует (fail fast).
Версионирование dataset.
- Snapshot — неизменяемый срез данных на момент времени (
train_2026-01-15_v3.parquet). - Version tag — semver или дата + hash схемы.
- Связь с экспериментом — ClearML/MMS фиксирует: experiment X обучен на dataset v3.
Schema evolution. Добавление nullable колонки — обычно backward compatible. Удаление колонки или смена типа — breaking. Политика: schema registry (Avro/Protobuf в Kafka) или явный changelog в repo.
Great Expectations / dbt tests / custom checks — инструменты вторичны; важна идея: проверки в CI/CD data pipeline, алерт при нарушении.
Train/serve skew из-за качества. Train видел imputed age=median; serve получает NULL и другой imputation path → разные распределения. Решение: одинаковая логика imputation в training pipeline и serving (shared library или Feature Store).
Data contracts (контракты между командами). Команда CRM публикует контракт: «поле balance — float, обновляется daily, SLA 06:00 UTC». ML-команда строит зависимости на этом контракте. Нарушение контракта — incident для обеих сторон.
PII и compliance. Качество включает безопасность: нет ли PII в логах фич, соблюдён ли retention. Версионирование помогает audit: «какие данные использовались для модели v12?».
Как это выглядит на практике
Pre-train gate в Argo Workflow:
# Упрощённый фрагмент DAG
- name: validate-dataset
template: data-quality-check
arguments:
parameters:
- name: dataset_uri
value: "s3://ml-gold/churn/train_2026-01-15_v3/"
- name: train-model
dependencies: [validate-dataset]
# стартует только если validate прошёл
Checks в validate-dataset:
1. Row count > 10 000 (не пустой export).
2. null_rate(feature_*) < 5% для каждой фичи.
3. Label distribution: churn rate между 5% и 40% (не сломанная выборка).
4. Schema hash совпадает с schemas/churn_v2.json.
При провале: Slack-алерт data team + блокировка train. DS не тратит GPU на мусор.
Версионирование в MMS (корпоративный реестр):
| Поле модели | Значение |
|-------------|----------|
| model_version | v44 |
| training_dataset | `churn/train_2026-01-15_v3` |
| feature_schema_hash | `a3f9c2...` |
| data_quality_report | link to artifact |
Rollback модели без знания dataset version — половина решения. Rollback вместе с dataset version — воспроизводимость.
Что сделать после занятия
- [ ] Для одной фичи учебного проекта опишите 3 data quality check'а с порогами.
- [ ] Сформулируйте data contract из 5 полей между «источником» и «ML-пайплайном».
- [ ] Объясните разницу между «версия модели» и «версия dataset» — зачем хранить обе.