Мониторинг и дрифт данных
В день релиза модель — лучшая версия себя. Дальше мир меняется, а веса — нет: качество утекает тихо, без единой ошибки в логах. Мониторинг — то, что отличает «мы задеплоили модель» от «у нас работает ML-система».
Интуиция
Модель — это навигатор со снимком карты на момент обучения. Первые месяцы всё отлично, потом в городе строят новые развязки — а навигатор уверенно ведёт через перекрёсток, которого больше нет. Хуже всего то, что он не выдаёт ошибку: он выдаёт правдоподобный маршрут. Точно так же модель в проде продолжает возвращать предсказания с прежней уверенностью, даже когда данные, на которые она смотрит, уже не похожи на обучающие.
Три вида дрифта
- Дрифт данных (data drift, covariate shift) — изменилось распределение входов X, а связь X→y прежняя. Пример: приложение запустилось в новой стране — средний чек, язык запросов и время активности другие.
- Дрифт концепции (concept drift) — изменилась сама связь X→y. Пример: мошенники сменили схему — те же признаки транзакций теперь означают другой лейбл. Самый коварный вид: входы могут выглядеть как раньше.
- Дрифт лейблов (label drift, prior shift) — изменилось распределение целевой переменной: доля спама выросла с 5% до 20%, и откалиброванные пороги поплыли.
Почему нельзя просто смотреть на точность
Хотелось бы построить график accuracy в проде и поставить алерт. Но настоящие лейблы приходят с задержкой (дефолт по кредиту виден через год) или не приходят никогда (в рекомендациях нет честного «понравилось бы»). Поэтому мониторят прокси-сигналы (proxy metrics) — то, что видно сразу:
- распределения входных фичей против эталона с трейна — через PSI или KL-дивергенцию (KL divergence);
- распределение предсказаний модели (score drift): если модель вдруг стала выдавать вдвое больше «единиц», что-то случилось;
- доля пропусков, выбросов и невалидных значений — часто дрифт оказывается просто сломанным пайплайном данных;
- для LLM-приложений: доля отказов (refusals), длина ответов, явный фидбек пользователей и LLM-судья (LLM-as-judge) на небольшом сэмпле трафика.
Классическая метрика сдвига распределений — PSI (Population Stability Index). Разбиваем значения фичи на корзины и сравниваем доли:
Ориентиры, пришедшие из кредитного скоринга: PSI < 0.1 — спокойно, 0.1–0.2 — присмотреться, > 0.2 — классический звонок «распределение существенно уехало».
Поймали дрифт — что дальше
Алерт по PSI — это не команда «переобучай», а команда «расследуй». Порядок действий:
- Расследовать причину. Половина «дрифтов» — сломанный пайплайн: фича стала null, изменилась единица измерения, апстрим переименовал поле. Вторая половина — реальные изменения: новый сегмент пользователей, сезонность, маркетинговая акция.
- Действовать по причине. Баг — чинить данные, не трогая модель. Реальный сдвиг — переобучить на свежих данных или откатить проблемную фичу/версию модели.
Переобучение (retraining) организуют двумя способами: по расписанию (раз в неделю/месяц — просто и предсказуемо, но между циклами модель стареет) и по триггеру (алерт по дрифту или падение прокси-метрик запускает пайплайн — экономнее и быстрее реагирует, но требует зрелой автоматики). Новую версию перед полной выкаткой держат в shadow-режиме (shadow mode): она получает реальный трафик и пишет предсказания в лог, но пользователям их не показывает — так сравнивают поведение моделей без риска. А влияние на бизнес-метрики честно измеряют через A/B-тест.
- «Чем data drift отличается от concept drift?» — в первом случае сменилось распределение X при прежней связи X→y, во втором — сама связь; concept drift не всегда виден по входам.
- «Как мониторить модель, если лейблы приходят через полгода?» — прокси-сигналы: PSI/KL по фичам, распределение предсказаний, доля пропусков; лейблы подключаются к мониторингу ретроспективно.
- «PSI = 0.25 по ключевой фиче — ваши действия?» — сначала расследование (баг пайплайна? новый сегмент?), затем решение: чинить данные, переобучать или откатывать.
- «Как мониторить LLM-приложение без метрики качества?» — доля отказов, длина ответов, пользовательский фидбек, LLM-судья на сэмпле трафика.