Алерт аномалий сработал 40 раз за месяц, 38 из них — шум. Переделайте правило детекции, чтобы команда снова ему доверяла.
Это правило срабатывает, когда сегодняшние регистрации падают более чем на 20% ниже единственного значения 7 дней назад. За месяц оно дало 40 алертов, 38 из них ложные. Ограничения: у регистраций сильная недельная сезонность, случаются праздники, а дни с малым объёмом шумны.
# Срабатывает, если сегодняшние регистрации падают >20% ниже значения 7 дней назад
def is_anomaly(today, week_ago):
return today < 0.8 * week_ago
Перепишите правило так, чтобы оно перестало срабатывать на шум, но всё ещё ловило реальные падения.
Замените порог по одной точке сезонным, робастным, устойчивым правилом: базируйте на прошлых тех же днях недели, а не на одной точке 7 дней назад. Помечайте, только когда отклонение превышает робастный разброс в несколько MAD, держится дольше интервала и бьёт минимальный эффект.
- ✗Ослаблять порог вместо добавления сезонности и устойчивости
- ✗Сравнивать с одной опорной точкой вместо распределения
- ✗Срабатывать на один замер без минимального абсолютного эффекта
- →Как настроить пороги устойчивости и минимального эффекта?
- →Как не дать правилу пропустить медленный реальный спад?
Наивное правило сравнивает сегодня с одной точкой 7 дней назад: оно ловит недельную сезонность (та точка сама могла быть праздником), взрывается на шумных днях малого объёма и срабатывает от одного замера. Робастная замена: база по окну прошлых тех же дней недели, отклонение в единицах MAD (устойчиво к выбросам), плюс требование устойчивости и минимального абсолютного эффекта.
import numpy as np
def is_anomaly(today, same_weekday_history, min_abs_drop=50, k=4):
# same_weekday_history: signups on prior same weekdays (e.g. last 8 Saturdays)
med = np.median(same_weekday_history)
mad = np.median(np.abs(same_weekday_history - med)) or 1.0
robust_z = (today - med) / (1.4826 * mad)
return robust_z < -k and (med - today) >= min_abs_drop
def fire_alert(today_series):
# require the breach to persist over >1 consecutive interval
return all(is_anomaly(*args) for args in today_series[-2:])
Сезонная база убирает недельный паттерн и праздники; порог по MAD пропускает нормальные колебания; min_abs_drop глушит шум малого объёма; проверка на 2 интервала убирает одиночные всплески. Реальное устойчивое падение всё ещё проходит все условия.