Мониторинг дрифта данных¶
~8 минут чтения
Предварительно: Наблюдаемость LLM | Сравнение Experiment Tracking
Модели в production деградируют неизбежно. По данным Arize AI, 91% ML-моделей теряют качество в первый год после деплоя. Средний time-to-detect для data drift без мониторинга -- 3-6 месяцев, за которые бизнес-метрики могут просесть на 10-30%. PSI > 0.25 на ключевых фичах -- это сигнал к немедленному переобучению. Мониторинг дрифта -- не "nice-to-have", а обязательная часть MLOps pipeline.
Зачем нужен мониторинг дрифта¶
Модель обучена на данных из прошлого. Мир меняется -- данные тоже. Без мониторинга модель деградирует тихо: accuracy падает, но никто не замечает пока бизнес-метрики не проседают.
Ключевой инсайт: дрифт -- это не вопрос "если", а вопрос "когда". Каждая production модель столкнется с дрифтом.
1. Типы дрифта¶
| Тип | Что меняется | Пример | Как обнаружить |
|---|---|---|---|
| Data drift (covariate shift) | \(P(X)\) -- распределение фичей | После COVID средний чек вырос 3x | Статистические тесты на фичах |
| Concept drift | \(P(Y\|X)\) -- связь фичей с таргетом | "Спам" раньше = нигерийские письма, теперь = фишинг через AI | Мониторинг model performance |
| Label drift (prior probability shift) | \(P(Y)\) -- распределение таргета | Fraud rate вырос с 0.1% до 2% | Мониторинг prediction distribution |
| Feature drift | Отдельные фичи меняются | Новый формат телефонных номеров | Per-feature statistical tests |
Data Drift vs Concept Drift¶
Data drift: входные данные изменились, но правила те же. Модель видит непривычные inputs.
Concept drift: правила изменились. Те же inputs -> другие правильные outputs. Это опаснее, потому что data distribution может выглядеть нормально.
2. Статистические тесты¶
Kolmogorov-Smirnov (KS) Test¶
Измеряет максимальное расстояние между двумя CDF (cumulative distribution functions).
- Порог: p-value < 0.05 = дрифт обнаружен
- Для: непрерывные фичи
- Плюс: не требует бинаризации, чувствителен к любому типу различий
- Минус: теряет мощность на малых выборках
Population Stability Index (PSI)¶
Стандарт в банковской сфере для мониторинга скоринговых моделей.
где \(p_i\) -- доля наблюдений в бине \(i\) для production, \(q_i\) -- для reference.
| PSI | Интерпретация |
|---|---|
| < 0.1 | Нет значимого дрифта |
| 0.1 - 0.25 | Умеренный дрифт, требует внимания |
| > 0.25 | Значительный дрифт, модель нужно переобучить |
Jensen-Shannon Divergence (JSD)¶
Симметричная версия KL-divergence. Диапазон \([0, 1]\) (при log base 2).
- Порог: > 0.1 -- подозрение, > 0.2 -- значимый дрифт
- Для: любые распределения (дискретные и непрерывные)
- Плюс: всегда определена (в отличие от KL, не делит на 0)
Comparison¶
| Тест | Тип фичей | Чувствительность | Интерпретируемость | Скорость |
|---|---|---|---|---|
| KS | Непрерывные | Высокая | Средняя | Быстро |
| PSI | Любые (бины) | Средняя | Высокая (пороги) | Быстро |
| JSD | Любые | Высокая | Средняя | Быстро |
| Chi-squared | Категориальные | Высокая | Высокая | Быстро |
| Wasserstein | Непрерывные | Высокая | Высокая (масштаб) | Средне |
PSI и KS тесты дают false positives на больших выборках
При N > 100K почти ЛЮБОЕ различие будет статистически значимым (p < 0.05). Тест показывает "дрифт", хотя разница 0.001 в среднем. Решение: используйте effect size (Wasserstein distance, PSI) вместо p-value. PSI < 0.1 = незначимо, даже если KS p-value = 0.0001. Для production систем: alert на PSI > 0.25, не на p-value.
3. Архитектура мониторинга¶
graph LR
subgraph Production["Production Pipeline"]
A[Model Predictions] --> B[Log Features + Predictions]
end
subgraph Monitor["Monitoring Layer"]
B --> C[Compute Statistics]
C --> D{Drift Detected?}
D -->|PSI > 0.25| E[Alert]
D -->|PSI < 0.1| F[OK]
D -->|0.1-0.25| G[Watch]
end
subgraph Action["Response"]
E --> H[Investigate Root Cause]
H --> I[Retrain / Rollback]
end
style A fill:#e8eaf6,stroke:#3f51b5
style D fill:#fff3e0,stroke:#ef6c00
style E fill:#fce4ec,stroke:#c62828
style F fill:#e8f5e9,stroke:#4caf50
Production Pipeline¶
from evidently.report import Report
from evidently.metric_preset import DataDriftPreset
import pandas as pd
def check_drift(reference_data: pd.DataFrame, production_data: pd.DataFrame) -> dict:
"""Check data drift between reference and production datasets."""
report = Report(metrics=[DataDriftPreset()])
report.run(
reference_data=reference_data,
current_data=production_data,
)
result = report.as_dict()
drift_share = result["metrics"][0]["result"]["share_of_drifted_columns"]
is_drift = drift_share > 0.3 # >30% columns drifted
return {
"drift_detected": is_drift,
"drift_share": drift_share,
"details": result["metrics"][0]["result"]["drift_by_columns"],
}
Monitoring Schedule¶
| Частота | Когда использовать |
|---|---|
| Real-time | Fraud detection, ad bidding -- цена ошибки высока |
| Hourly | Recommendations, search ranking |
| Daily | Credit scoring, content moderation |
| Weekly | Long-term models, batch predictions |
4. Инструменты¶
| Tool | Тип | Drift Detection | Сильные стороны | Слабые стороны |
|---|---|---|---|---|
| Evidently | Open-source | KS, PSI, Wasserstein, JSD, Chi2 | Гибкость, отчеты, интеграция с любым стеком | Нет managed service |
| WhyLabs | SaaS | whylogs profiling + statistical tests | Enterprise alerting, root cause analysis | Коммерческий |
| Arize | SaaS | PSI, embedding drift | Embedding monitoring, LLM-specific | Коммерческий |
| NannyML | Open-source | CBPE (без ground truth) | Оценка performance без labels | Менее зрелый |
| Great Expectations | Open-source | Data validation (не drift) | Data quality checks | Не мониторинг, а валидация |
Decision Framework¶
graph TD
A[Нужен мониторинг дрифта] --> B{Бюджет?}
B -->|Open-source| C{LLM/Embeddings?}
B -->|Enterprise| D{Root Cause Analysis?}
C -->|Да| E[NannyML + custom]
C -->|Нет| F[Evidently]
D -->|Критично| G[WhyLabs]
D -->|Nice-to-have| H[Arize]
style A fill:#e8eaf6,stroke:#3f51b5
style F fill:#e8f5e9,stroke:#4caf50
style G fill:#f3e5f5,stroke:#9c27b0
style H fill:#fff3e0,stroke:#ef6c00
5. LLM-специфичный дрифт¶
Для LLM мониторинг дрифта отличается от табличных моделей:
| Аспект | Табличные модели | LLM |
|---|---|---|
| Входы | Числовые фичи | Текст, промпты |
| Дрифт фичей | PSI/KS на каждой фиче | Embedding drift (cosine distance) |
| Output drift | Prediction distribution | Response length, topic shift, refusal rate |
| Ground truth | Часто доступен | Редко доступен |
Embedding drift detection:
import numpy as np
from sklearn.metrics.pairwise import cosine_similarity
def embedding_drift(ref_embeddings: np.ndarray, prod_embeddings: np.ndarray) -> float:
"""Compute drift as 1 - average cosine similarity between centroids."""
ref_centroid = ref_embeddings.mean(axis=0, keepdims=True)
prod_centroid = prod_embeddings.mean(axis=0, keepdims=True)
sim = cosine_similarity(ref_centroid, prod_centroid)[0, 0]
return 1.0 - sim # 0 = no drift, 1 = max drift
6. Response Strategies¶
| Стратегия | Когда | Сложность |
|---|---|---|
| Alert + investigate | Любой drift | Низкая |
| Fallback model | Performance drop > threshold | Средняя |
| Auto-retrain | Scheduled + drift-triggered | Высокая |
| Online learning | Continuous stream, fast drift | Очень высокая |
Retrain Triggers¶
| Trigger | Описание | Пример |
|---|---|---|
| Time-based | Регулярное переобучение | Каждую неделю |
| Performance-based | Accuracy dropped > 5% | AUC < 0.85 |
| Drift-based | PSI > 0.25 на >30% фичей | Seasonal shift detected |
| Hybrid | Time OR performance OR drift | Best practice |
Для интервью¶
Q: "Как вы мониторите data drift в production?"¶
Три уровня: (1) Feature-level: PSI на каждой фиче, alert при PSI > 0.25, watch при 0.1-0.25. Для категориальных -- Chi-squared. (2) Model-level: prediction distribution shift, confidence calibration. (3) Business-level: conversion rate, revenue per user. Инструмент: Evidently (open-source) для отчетов + custom alerts в Grafana.
Q: "Разница между data drift и concept drift?"¶
Data drift (\(P(X)\) изменился): входные данные другие, но правила те же. Пример: средний чек вырос после инфляции, но "дорогая покупка" по-прежнему > \(500. **Concept drift** (\)P(Y|X)$ изменился): правила изменились при тех же данных. Пример: покупка на $500 раньше была нормальной, теперь -- подозрительная. Concept drift опаснее: data distribution может выглядеть нормально.
Q: "PSI vs KS test -- когда какой?"¶
PSI для бизнес-репортинга: интерпретируемые пороги (< 0.1 / 0.1-0.25 / > 0.25), стандарт в банках. KS для исследования: non-parametric, чувствителен к любому типу различий, но на больших выборках (N > 100K) дает false positives. Рекомендация: PSI для alerting (effect size), KS для exploratory analysis (p-value + effect size).
Частые заблуждения¶
Заблуждение: обнаружили дрифт -- значит нужно срочно переобучать модель
Дрифт != деградация performance. Data drift (P(X) изменился) может не влиять на качество модели, если изменения в области, где модель уверена. Сначала проверьте business metrics и model performance. Если accuracy не упала -- достаточно увеличить частоту мониторинга. Переобучение без деградации -- это waste of compute и риск regression.
Заблуждение: concept drift можно поймать стандартными тестами на фичах
Concept drift (P(Y|X) изменился) коварен тем, что P(X) может остаться прежним. KS/PSI на фичах покажут "все ок", а модель уже ошибается. Единственный надежный способ обнаружить concept drift -- мониторить prediction performance с ground truth labels. Если labels недоступны в реальном времени -- используйте proxy (NannyML CBPE, confidence calibration, prediction distribution shift).
Заблуждение: для LLM достаточно мониторить embedding drift
Embedding drift (cosine distance между centroid'ами) ловит грубые изменения в распределении запросов, но пропускает тонкие: смену intent при похожей лексике, рост adversarial inputs, изменение длины и структуры промптов. Полноценный LLM-мониторинг включает: embedding drift + response length distribution + topic modeling + refusal rate + latency percentiles + user feedback signals.
Вопросы для собеседования¶
Вы видите PSI = 0.18 на важной фиче. Ваши действия?
"PSI > 0.1, значит дрифт есть, переобучаем модель" -- преждевременная реакция без анализа impact.
Сильный ответ: PSI 0.18 -- зона "watch" (0.1-0.25). Действия: (1) Проверить model performance metrics -- если accuracy/AUC не упали, дрифт может быть безвредным. (2) Визуализировать распределение фичи (reference vs production) -- понять характер изменения (сдвиг среднего? хвосты?). (3) Проверить другие фичи -- если дрифт только в одной, вероятно локальная аномалия. (4) Увеличить частоту мониторинга (daily -> hourly). (5) Установить alert на PSI > 0.25. Переобучение только если подтверждена деградация performance.
Как мониторить drift для LLM-приложения, где нет четких фичей?
"Используем PSI на входном тексте" -- PSI не работает напрямую с текстом.
Сильный ответ: Для LLM мониторинг многоуровневый: (1) Input drift -- embedding centroids (cosine distance > 0.1 = alert), topic distribution через lightweight classifier, средняя длина промпта. (2) Output drift -- response length distribution, refusal rate, confidence scores. (3) Behavioral drift -- latency P50/P99, token usage, tool call patterns. (4) Quality proxy -- user thumbs up/down ratio, regeneration rate, session abandonment. Инструменты: Arize для embedding drift, Langfuse для LLM-specific metrics, custom dashboards в Grafana.
Спроектируйте pipeline мониторинга для модели кредитного скоринга.
"Запускаем Evidently раз в неделю" -- нет архитектуры, нет response strategy.
Сильный ответ: Архитектура: (1) Data layer -- логируем features + predictions + timestamps в feature store. (2) Compute layer -- daily batch job: PSI на каждой фиче (reference = training data), prediction distribution (mean/std/percentiles), performance metrics (когда labels доступны, обычно 30-60 дней задержка). (3) Alert layer -- PSI > 0.25 на >30% фичей = P1 alert, PSI > 0.1 на >50% = P2. (4) Response -- auto-trigger retrain pipeline при P1; при P2 -- notify ML team + increase monitoring frequency. (5) Regulatory -- квартальный отчет о стабильности модели (PSI trend, performance trend). Tool: Evidently для compute, Grafana для dashboards, PagerDuty для alerts.
Sources¶
- Evidently AI -- "Data Drift Detection" documentation
- NannyML -- "Estimating Performance Without Ground Truth"
- Arize -- "Embedding Drift Monitoring for LLMs"
- Google -- "Monitoring Machine Learning Models in Production" (2022)
- scikit-multiflow -- "Concept Drift Detection Methods"
See Also¶
- Наблюдаемость LLM -- мониторинг quality/latency/cost, Langfuse трейсы -- drift detection как часть observability
- Гардрейлы оценки LLM -- guardrails как protection layer, работает в паре с drift monitoring
- Сравнение Experiment Tracking -- MLflow/W&B для трекинга экспериментов по переобучению при обнаруженном дрифте
- Сравнение Feature Stores -- feature stores как источник данных для drift computation
- Непрерывное обучение LLM -- continual learning как ответ на concept drift