Модуль 10. Аномалии: от z-score до леса
Цель модуля: научиться отвечать не на вопрос «кто выброс?», а на вопрос «что считать аномалией и что с ней делать». После модуля вы считаете z-score и IQR, понимаете, почему z-score ломается на собственных выбросах, знаете идею isolation forest для многомерных случаев и выбираете действие — алерт, сглаживание или отбрасывание — по контексту задачи.
Перед началом: модуль 2 (среднее, MSE и почему они боятся выбросов) и модуль 9 (аномалия — это «не похож на остальных»). Инструменты: песочница сайта (чистый Python), сниппет ниже. Трудоёмкость: ~1.5 ч (чтение 45 мин · сниппет и практика 35 мин).
🔥 Алерт стрелял ночью 40 раз
Порог алерта на p99 латентности — 200 мс. За ночь правило сработало сорок раз: график похож на кардиограмму, дежурный утром разбирает список, где тридцать девять записей — один и тот же инцидент с диском. Формально всё было выше порога, но 200 мс — почему и что вообще считать аномалией?
Порог отвечает на вопрос «когда тревожиться», но не на вопрос «что такое аномалия». Это два разных решения: статистическое (насколько значение необычно для распределения) и продуктовое (тревожить ли человека). Модуль разбирает оба.
📖 10.1. Порог — это решение, а не определение аномалии
Аномалия — отклонение от того, что ожидалось в этих условиях. Понедельник, десять утра, релизный день — пик нагрузки нормален; тот же пик в субботу — аномалия. «Ожидаемое» зависит от контекста, которого константа 200 мс не видит.
Отсюда первый шаг: определить, относительно чего мерить. Два частых ответа — «насколько значение далеко от среднего» (z-score) и «вне типичного диапазона» (IQR) — работают с одной метрикой против её истории. Второй тип аномалий — сочетание нормальных фич; о нём в 10.5, а сначала — одномерные инструменты.
📖 10.2. z-score: сколько сигм от среднего
z-score переводит значение в вопрос «на сколько сигм я дальше среднего»:
textz = (x − среднее) / сигма
Правило трёх сигм: для нормального распределения за |z| > 3 лежит примерно 0.3% значений — их и объявляют выбросами. Одна формула, одно число, прямая интерпретация. Но у метода два смертельных изъяна на реальных данных.
Первый: среднее и сигма считаются по тем же данным, где сидит выброс. Выброс раздувает обе величины и прячется в раздутой сигме — логический круг. Сниппет это показывает буквально: сигма 1037.8 мс, значение 5000 мс — «всего» 4.46 сигмы, а реальная деградация 400 мс — 0.03 сигмы, то есть «норма». Метод оглушил сам себя.
Второй изъян мягче: гипотеза нормальности. Латентности и суммы платежей — распределения с тяжёлыми хвостами, и сигма их хвост не описывает. Для мониторинга берут медиану и квантили — то есть IQR из следующего раздела.
📖 10.3. IQR: квартили, которые не сдвигаются
IQR (interquartile range) строится на квартилях — это 25-й и 75-й процентили (Q1 и Q3). IQR = Q3 − Q1 — ширина «средней половины» данных. Границы Тьюки (из «ящика с усами» на box-plot):
text[Q1 − 1.5 · IQR; Q3 + 1.5 · IQR]
Всё за этими границами — кандидаты в выбросы. Ключевое свойство — робастность: квартили определяются порядком значений, а не их величиной. Один безумный замер не сдвинет Q1 и Q3: в сниппете границы [110.0; 134.0], хотя среднее тех же данных — 366.5 мс (испорчено, а квартили — нет).
Цена устойчивости: IQR отвечает «вне диапазона» — да или нет, — но не говорит, насколько далеко: 400 и 5000 для него одинаково «выше границы». Множитель 1.5 — соглашение, а не закон; по пяти точкам квартили бессмысленны.
📖 10.4. Сниппет: два метода на одних данных
Запустите outliers.py. В нём 21 замер p99: ровный ряд около 120 мс,
деградация диска 400 мс в 17:04 и таймаут 5000 мс в 17:05. Вывод:
textЗамеров: 21, значения 110…5000 мс Среднее = 366.5 мс, сигма = 1037.8 мс (выбросы раздувают обе цифры!) значение z-score вердикт |z|>3 5000 4.46 ВЫБРОС 400 0.03 норма 130 -0.23 норма 128 -0.23 норма 126 -0.23 норма 125 -0.23 норма Q1 = 119.0, Q3 = 125.0, IQR = 6.0 → границы [110.0; 134.0] 5000 ВЫБРОС (по IQR) 400 ВЫБРОС (по IQR) 130 норма (по IQR) 128 норма (по IQR) 126 норма (по IQR) 125 норма (по IQR)
Читайте таблицу как детектив. 5000 мс — выброс у обоих методов. 400 мс — идеальный учебный контраст: z-score считает его нормой (z = 0.03), потому что сигма раздута до 1037.8 одним значением 5000; IQR объявляет выбросом, потому что 400 выше границы 134. Именно 400 мс — реальная деградация, ради которой всё и затевалось; метод, который её «не заметил», провалил бы ночной алерт. И мелочь: у значений 130, 128, 126, 125 z-score одинаковый до сотых (−0.23) — сигма в тысячу миллисекунд сжала весь рабочий диапазон в точку у среднего. Так выглядит потеря разрешения.
Вывод сниппета: это разные вопросы. z-score — «насколько я далеко от среднего», IQR — «вне типичного диапазона». Для мониторинга почти всегда берут второй; z-score полезен на чистых симметричных данных, где нужно «насколько».
📖 10.5. Когда порога мало: сочетания и идея isolation forest
Одномерные методы ловят «одна метрика против своей истории». Но аномалия часто — редкая комбинация нормальных значений: CPU 55% — обычный день, CPU 55% при упавшем вдвое трафике — подозрительно. Пороги по каждой оси такое не поймают: каждая координата по отдельности «в норме». Нужна мера «насколько точка далека от облака целиком» (по-взрослому — Mahalanobis или оценка плотности), и здесь в игру вступает isolation forest — метод, построенный на одной красивой идее.
Идея: аномалию легко изолировать. Возьмите случайные деревья: на каждом шаге выбирается случайная фича и случайный порог, точка уходит влево или вправо. Обычных точек много, и они похожи друг на друга — чтобы отделить одну от остальных, нужно много разрезов; аномалия одинока и сильно отличается — её отсекают от всех за пару шагов. Средняя длина пути по ансамблю деревьев становится скором: короткий путь — аномалия. Метод не требует разметки (аномалий обычно и нет в размеченном виде), не требует гипотезы нормальности и масштабируется. Родственная идея — One-class SVM: «обучиться на нормали и мерить удалённость от неё», дороже на больших данных.
Важная оговорка: лес выдаёт скор, а не вердикт — порог отсечения всё
равно ваш, и порог аномалий — бюджет ложных тревог («сколько раз в неделю
дежурный готов подняться зря»), ровно как порог классификатора (модуль 3)
и метрик (модуль 7). В sklearn — IsolationForest в несколько строк; но
берите его, когда сочетания фич реально бьют по одномерным порогам.
📖 10.6. Что делать с найденным: алерт, сглаживание, отбросить
Детекция нашла кандидатов. Дальше — решение по контексту, и вариантов три.
Алерт — выброс есть сигнал (латентность, деньги, ошибки). Правила: порог — по цене пропуска и цене ложной тревоги; группировать — сорок ночных срабатываний одной причины это один инцидент, а не сорок; хранить ответ «почему считаем аномалией», иначе дежурный не доверяет.
Сглаживание — выброс есть ошибка измерения. Для графиков и агрегатов: обрезать концы (winsorize), брать медиану вместо среднего, p95/p99 вместо максимума. Данные не исчезают — одно значение перестаёт определять итог.
Отбросить для обучения — выброс есть ошибка склейки или логов. Самый рискованный путь, и вот его правила: (1) сначала посмотрите на единичные выбросы глазами — 5000 мс из таймаута это реальность или артефакт складывания; (2) ошибку измерения/логирования исключать можно, а выброс-сигнал (мошенничество, сбой) — нельзя: вы выбросите то, что хотите предсказывать; (3) «модель на нём ошибается» — не повод выкинуть, это подгонка метрики; (4) правило живёт в коде пайплайна и одинаково применяется в обучении и в бою, иначе модель в бою встретит то, от чего её отучили (модуль 8).
И общая привычка: аномалии — не мусор, а наблюдения. Сохраняйте их отдельно и помечайте: через месяц вопрос «что случилось в 17:05» будет иметь ответ.
📖 10.7. Компромиссы
- z-score vs IQR. z — число и интерпретация «насколько далеко», но ломается выбросами и гипотезой нормальности; IQR устойчив, но отвечает только «да/нет». Считайте оба: расхождение — самое интересное.
- Порог vs алгоритм. Порог дёшев и объясним; алгоритм ловит сочетания, но требует данных и хуже объясняется. Начинайте с порогов по осям, лес — когда сочетания реально бьют.
- Устойчивость vs чувствительность. Медиана и квартили дают меньше ложных тревог, но могут проспать раннюю деградацию; среднее заметит раньше, но разбудит зря. Классический обмен точности на полноту.
- Удалять выбросы vs оставлять. Удаление чистит обучение, но может стереть редкий важный сигнал. Явная единая политика безопаснее ручной «чистки на глаз».
- Автоматика vs человек в контуре. Полная автоматика тонет в тревогах, ручной контроль не масштабируется. Гибрид: автоматика ранжирует и группирует, человек решает.
💻 Практика
- (15 мин) Лечим z-score. Запустите
outliers.pyи уберите изLATENCYзначение 5000. Пересчитайте: среднее упадёт до ~134.8 мс, сигма — до ~61.0, и 400 мс внезапно станет выбросом (z ≈ 4.35). Во сколько раз уменьшилась сигма и что это говорит про «круг» z-score? - (15 мин) IQR руками. Для ряда (100, 102, 105, 110, 200, 101, 99, 103, 104) посчитайте Q1, Q3, IQR и границы. Кто выброс? Замените 200 на 10 000 — сдвинулись ли границы? Почему?
- (10 мин) Метрика своего сервиса. Для рабочей метрики (латентность, ошибки, конверсия) выпишите: что «норма», что «мягкая аномалия», что «тревога» и какие плановые события аномалией не считаются.
- (10 мин) Политика выбросов. Для задачи «срочный тикет» (модуль 3) решите: какие выбросы в фичах отбросите, какие превратите в признак-флаг «аномалия», и запишите решение правилом в одну строку.
🧩 Quiz "Проверь себя"
✅ Итоги модуля
- Объяснить, почему порог — это решение, а не определение аномалии.
- Посчитать z-score и IQR и показать на сниппете, где они расходятся (400 мс: норма у z, выброс у IQR).
- Объяснить «круг» z-score: выбросы участвуют в тех же среднем и сигме.
- Описать идею isolation forest: аномалия изолируется коротким путём.
- Для своей метрики выписать плановые события, которые не аномалии.
- Сформулировать политику выбросов для обучения и боя — одинаковую.
🔗 Мостик к Модулю 11
В этом модуле один и тот же набор данных дал два разных вердикта: всё решили определение и порог. Та же болезнь ждёт в оценке моделей: одна цифра на одной выборке умеет врать. Дальше — как мерить честно: k-fold, разброс вместо единственной цифры, подбор гиперпараметров и таблица «какая модель когда».