PSI для дрейфа признака: почему границы корзин нельзя пересчитывать
Средний чек в сервисе вырос, но дашборд PSI показывает почти ноль. Аналитик обнаруживает, что каждую неделю границы квантильных корзин считали заново. В обеих выборках каждый бин содержал примерно одинаковую долю строк — именно так работает квантильное разбиение. Оно сравнивает ранги внутри каждой недели, а не распределения на одной шкале. Сигнал сдвига исчез.
Одна сетка для эталона и текущих данных
Выберите базовый период, постройте границы по нему и сохраните их как версию мониторинга. Затем считайте доли и в эталоне, и в новом окне по тем же границам. Для крайних значений полезны открытые хвостовые интервалы: данные за пределами старого диапазона тоже должны попасть в расчёт. PSI складывает по бинам (p_current − p_reference) × ln(p_current / p_reference). Для пустых корзин нужна заранее зафиксированная политика сглаживания.
Небольшой пример берёт эталон от 0 до 9 и текущие значения от 5 до 14. Десятичные бины здесь не нужны: пять фиксированных промежутков достаточно, чтобы показать эффект.
import numpy as np
reference = np.arange(10, dtype=float)
current = np.arange(5, 15, dtype=float)
edges = np.array([-np.inf, 2, 4, 6, 8, np.inf])
def shares(values, boundaries):
counts = np.histogram(values, bins=boundaries)[0]
return counts / counts.sum()
def psi(left, right, epsilon=1e-6):
a = np.clip(left, epsilon, None)
b = np.clip(right, epsilon, None)
return float(np.sum((b - a) * np.log(b / a)))
fixed = psi(shares(reference, edges), shares(current, edges))
separate_edges = np.quantile(current, [0, .2, .4, .6, .8, 1])
recomputed = psi(shares(reference, np.quantile(reference, [0, .2, .4, .6, .8, 1])),
shares(current, separate_edges))
print("fixed:", round(fixed, 3), "recomputed:", round(recomputed, 3))
assert fixed > 0.5
assert np.isclose(recomputed, 0.0)При общей сетке PSI заметно выше нуля; при отдельных квантилях он равен нулю, хотя текущий ряд явно сдвинут. В реальном мониторинге отдельно учитывайте пропуски и новые категории, проверяйте объём окна и сравнивайте показатели по сегментам. PSI сообщает о различии распределений, но не устанавливает причину и не доказывает падение качества модели. Для качества нужны метки, когда они появятся.
Сглаживание в формуле влияет на число особенно сильно, когда в текущем окне появляется доля в корзине, пустой в эталоне. Значение 1e-6 в примере выбрано только для вычислимости логарифма. В рабочем дашборде задайте правило заранее и покажите вклад каждой корзины: огромный PSI из одной новой области значений требует другого разбора, чем небольшой сдвиг во всех интервалах. Если часть входов теперь отсутствует, не прячьте её в заполненную медиану перед мониторингом — заведите отдельную корзину «нет значения».
Не превращайте порог в автоматический диагноз
Сохраните границы, базовый период, правила сглаживания и версию признака вместе с дашбордом. Одинаковое название поля не гарантирует одинаковые единицы измерения. При большом PSI посмотрите вклад отдельных корзин и реальные примеры: выросла доля крупных заказов или сломалась конверсия валют? Эти действия полезнее единого порога тревоги для всех признаков.
Эталон выбирайте из периода, который отражает нормальную работу системы, а не просто из первого доступного файла. Сезонные продажи, акции и смена аудитории могут закономерно менять распределение. В таком случае полезны отдельные сравнения для сегментов и сезонных базовых периодов, но границы внутри каждого сравнения всё равно должны быть зафиксированы. При малом числе наблюдений доли отдельных корзин шумят; добавьте к PSI объём данных и визуальное распределение, прежде чем поднимать инцидент.
В курсе «Data Scientist: от данных до деплоя моделей» мониторинг data drift связан с проверкой качества данных и поддержкой модели после релиза. Посмотрите программу курса, если хотите построить такой контур для своего ML-проекта.
Продолжить на практике
- Data Scientist: от данных до деплоя моделей ↗
Практический курс по Data Science: от постановки ML-задачи и работы с данными до inference API, CI/CD и мониторинга моделей в продакшне. Вы пройдёте EDA, feature engineering, обучение и оценку моделей, experiment tracking, error analysis и deployment — чтобы собирать полноценный рабочий контур вокруг ML-решения.
