Условие
Мониторим тысячи метрик в инфраструктуре. Нужно детектировать аномалии в реальном времени. Какие подходы?
Решение
Подход
Семейства методов:
- Statistical: z-score, IQR, ESD test на residuals.
- Forecast-based residuals: предсказываем точку, аномалия = большой residual.
- Decomposition: STL разложение (trend + seasonality + remainder); аномалия в remainder.
- Reconstruction-based: autoencoder reconstruct; большой error = аномалия.
- Density-based: Isolation Forest на window features.
- Change-point detection: ruptures, Bayesian changepoint, для уровневых изменений.
Forecast-based residual
from statsmodels.tsa.seasonal import STL
import numpy as np
def stl_anomaly(y, period=7, threshold=3.0):
stl = STL(y, period=period, robust=True).fit()
residual = stl.resid
# Аномалия — точка, где |residual| > k·std(residual)
sigma = residual.std()
flags = np.abs(residual) > threshold * sigma
return flags, residual, stlProphet residuals
from prophet import Prophet
m = Prophet(interval_width=0.99)
m.fit(df)
forecast = m.predict(df)
# yhat_lower / yhat_upper — 99% interval
anomalies = df[(df.y < forecast.yhat_lower) | (df.y > forecast.yhat_upper)]Online detection
class StreamingZScore:
def __init__(self, alpha=0.01, threshold=3.0):
self.alpha = alpha
self.mu = None
self.var = None
self.threshold = threshold
def update(self, x):
if self.mu is None:
self.mu, self.var = x, 1.0
return False
z = (x - self.mu) / np.sqrt(self.var + 1e-6)
is_anomaly = abs(z) > self.threshold
if not is_anomaly:
# Update only on non-anomalies
self.mu = (1 - self.alpha)*self.mu + self.alpha*x
self.var = (1 - self.alpha)*self.var + self.alpha*(x - self.mu)**2
return is_anomalyAutoencoder для multivariate
import torch.nn as nn
class LSTMAutoencoder(nn.Module):
def __init__(self, n_features, hidden=64):
super().__init__()
self.enc = nn.LSTM(n_features, hidden, batch_first=True)
self.dec = nn.LSTM(hidden, n_features, batch_first=True)
def forward(self, x):
z, _ = self.enc(x)
z = z[:, -1:, :].repeat(1, x.size(1), 1)
x_hat, _ = self.dec(z)
return x_hat
# loss = MSE(x, x_hat); anomaly score = ||x − x_hat||²Типы аномалий
- Point: одна точка резко вне нормы.
- Contextual: точка в норме в общем, но аномальна в контексте (например, нулевые продажи в понедельник днём).
- Collective: подсерия выглядит аномально.
- Change-point: уровень/тренд переключился.
Разные методы под разные типы; STL хорошо для contextual в сезонных, change-point detection для shifts.
Метрики
- Precision@k, Recall@k.
- PR-AUC на labelled anomalies.
- Detection delay: как быстро после начала аномалии алерт.
- NAB score (Numenta Anomaly Benchmark) — учитывает delay.
Алертинг
- Дедуп: одна аномалия не должна выдавать 100 алертов.
- Severity scoring: degree of anomaly, не binary.
- Контекст: что одновременно происходит в других метриках (correlation).
Подводные камни
- Static threshold на дневных метриках: пропустит ночные аномалии или зальёт ложными в peak. Нужна seasonality decomposition.
- Concept drift: метрика «нормальная» через месяц может стать другой → обновляйте baseline.
- Multi-test correction: 1000 метрик × 0.01 false positive rate = 10 ложных алертов/окно. Нужен FDR или важность по бизнес-приоритету.
- Autoencoder на чистом train: если в train были аномалии, AE их научится «restore» → они не аномальны.
- Anomaly labels редки: обычно unsupervised. Когда становятся доступными — semi-supervised refit.
- Корреляция между метриками: одна аномалия в БД может вызвать всплеск в 50 метриках. Group alerts.
Эталонный ответ
Подходы: forecast-based residual (Prophet, STL), online z-score, density (Isolation Forest на window features), reconstruction (LSTM autoencoder), change-point detection. Учитывайте seasonality (STL decomposition), concept drift (обновляйте baseline), multiple testing (FDR на тысячах метрик), correlation alerts. Метрики: PR-AUC, detection delay, NAB score.