Головна▸Статті▸Anomaly Detection та Predictive Maintenance

Unsupervised виявлення аномалій

Пошук аномалій без міток - isolation forests, автоенкодери, clustering-based detection та виробничі системи виявлення аномалій.

mysimulator teamОновлено 2026-01≈ 4 хв читання▶ Open the simulation

Unsupervised виявлення аномалій ідентифікує незвичні патерни без розмічених прикладів аномалій. Це необхідно коли аномалії рідкісні, невідомі або постійно еволюціонують. Замість вивчення того як виглядають аномалії, ці методи вивчають що є нормою і позначають відхилення.

Де використовується

Unsupervised виявлення аномалій застосовується в різних доменах:

Продукти: Splunk UBA, AWS GuardDuty, Azure Sentinel, Datadog.

Чому Unsupervised?

Сценарій Чому Unsupervised
Немає міток Аномалії ніколи не розмічені або занадто дорого
Невідомі аномалії Нові типи атак, нові збої
Дисбаланс класів 0.01% аномалій робить supervised складним
Еволюційні патерни Визначення норми та аномалій змінюється
Дослідження Відкриття що незвичне перед визначенням

Типові дані

Аспект Типові значення
Зразків 10K до 100M
Features 5 до 1000
Anomaly rate 0.1% до 5%
Розмірність Низька до високої
Типи даних Numeric, categorical, mixed

Що ви робите на практиці

  1. Зрозумійте домен - Що може бути аномальним і чому це важливо
  2. Зберіть нормальні дані - Ідеально без аномалій у тренувальному наборі
  3. Інженеріть фічі - Domain-relevant представлення
  4. Обробіть missing values - Імпутація або indicator features
  5. Нормалізуйте правильно - Robust scaling для присутності outliers
  6. Оберіть метод - Isolation Forest, autoencoder, clustering
  7. Встановіть threshold - На основі оцінки contamination або бізнес потреб
  8. Валідуйте з експертами - Review виявлених аномалій
  9. Деплойте з моніторингом - Відстежуйте detection rates
  10. Ітеруйте на основі feedback - Інкорпоруйте рішення аналітиків

Базова лінія: Isolation Forest

Швидкий, ефективний, вимагає мінімального налаштування:

from sklearn.ensemble import IsolationForest
from sklearn.preprocessing import RobustScaler
import numpy as np

class IsolationForestDetector:
    def __init__(self, contamination=0.01, n_estimators=100):
        self.scaler = RobustScaler()
        self.model = IsolationForest(
            contamination=contamination,
            n_estimators=n_estimators,
            random_state=42,
            n_jobs=-1
        )

    def fit(self, X):
        X_scaled = self.scaler.fit_transform(X)
        self.model.fit(X_scaled)
        return self

    def predict(self, X):
        X_scaled = self.scaler.transform(X)
        # Повертає -1 для аномалій, 1 для нормальних
        predictions = self.model.predict(X_scaled)
        return predictions == -1  # True для аномалій

    def score(self, X):
        X_scaled = self.scaler.transform(X)
        # Нижчий score = більш аномальний
        return -self.model.decision_function(X_scaled)

# Використання
detector = IsolationForestDetector(contamination=0.01)
detector.fit(X_train)
anomalies = detector.predict(X_test)
scores = detector.score(X_test)

Методи виявлення

Метод Опис Найкраще для
Isolation Forest Random partitioning ізолює аномалії швидше Табличні дані, швидкий inference
Local Outlier Factor Density-based локальне відхилення Кластеризовані дані
One-Class SVM Boundary навколо нормальних даних Високорозмірні, малі датасети
Autoencoder Reconstruction error як anomaly score Складні патерни, зображення
DBSCAN Clustering з noise detection Просторові дані
Gaussian Mixture Ймовірність під mixture model Чітко визначені розподіли
k-NN Distance Відстань до найближчих сусідів Простий, інтерпретований

Autoencoder Detector:

import torch
import torch.nn as nn
import numpy as np

class AnomalyAutoencoder(nn.Module):
    def __init__(self, input_dim, encoding_dim=32):
        super().__init__()
        self.encoder = nn.Sequential(
            nn.Linear(input_dim, 128),
            nn.ReLU(),
            nn.Linear(128, 64),
            nn.ReLU(),
            nn.Linear(64, encoding_dim)
        )
        self.decoder = nn.Sequential(
            nn.Linear(encoding_dim, 64),
            nn.ReLU(),
            nn.Linear(64, 128),
            nn.ReLU(),
            nn.Linear(128, input_dim)
        )

    def forward(self, x):
        encoded = self.encoder(x)
        decoded = self.decoder(encoded)
        return decoded

class AutoencoderDetector:
    def __init__(self, input_dim, threshold_percentile=95):
        self.model = AnomalyAutoencoder(input_dim)
        self.threshold_percentile = threshold_percentile
        self.threshold = None

    def fit(self, X, epochs=50, lr=1e-3):
        X_tensor = torch.FloatTensor(X)
        optimizer = torch.optim.Adam(self.model.parameters(), lr=lr)
        criterion = nn.MSELoss()

        self.model.train()
        for epoch in range(epochs):
            optimizer.zero_grad()
            reconstructed = self.model(X_tensor)
            loss = criterion(reconstructed, X_tensor)
            loss.backward()
            optimizer.step()

        # Встановлення threshold з training data
        self.model.eval()
        with torch.no_grad():
            recon = self.model(X_tensor)
            errors = torch.mean((X_tensor - recon) ** 2, dim=1).numpy()
        self.threshold = np.percentile(errors, self.threshold_percentile)

    def predict(self, X):
        X_tensor = torch.FloatTensor(X)
        self.model.eval()
        with torch.no_grad():
            recon = self.model(X_tensor)
            errors = torch.mean((X_tensor - recon) ** 2, dim=1).numpy()
        return errors > self.threshold

Вибір Threshold

import numpy as np

class ThresholdSelector:
    @staticmethod
    def percentile_threshold(scores, percentile=95):
        """Top percentile як аномалії."""
        return np.percentile(scores, percentile)

    @staticmethod
    def iqr_threshold(scores, multiplier=1.5):
        """IQR-based threshold."""
        q1, q3 = np.percentile(scores, [25, 75])
        iqr = q3 - q1
        return q3 + multiplier * iqr

    @staticmethod
    def mad_threshold(scores, multiplier=3.5):
        """Median Absolute Deviation threshold."""
        median = np.median(scores)
        mad = np.median(np.abs(scores - median))
        return median + multiplier * 1.4826 * mad

Метрики оцінки

Метрика Опис Використання
Precision@K Precision у top K scores Обмежена capacity review
Recall Зловлені аномалії Критичні аномалії
F1 Score Баланс precision/recall Загальна оцінка
AUC-ROC Якість ранжування Коли мітки доступні

Типові помилки та чек-лист

Чек-лист для продакшену

Перед деплоєм: - [ ] Валідація на відомих аномаліях якщо доступні - [ ] Встановлення threshold для прийнятного false positive rate - [ ] Побудова review інтерфейсу для аналітиків

Після деплою: - [ ] Моніторинг стабільності detection rate - [ ] Відстеження feedback аналітиків - [ ] Перенавчання на оновлених нормальних даних - [ ] Коригування thresholds на основі feedback

Інструменти та стек

Категорія Інструменти
Бібліотеки PyOD, scikit-learn, PyTorch
Платформи AWS Lookout, Azure Anomaly Detector
Візуалізація Plotly, Altair

Приклад міні-кейсу

Сценарій: Виявлення дефектів виробництва з сенсорних даних.

Підхід: - Isolation Forest на 50 sensor features - Autoencoder для складних патернів - Ensemble обох методів

Результати: - 87% дефектів зловлено (recall) - 5% false positive rate - 2 секунди latency виявлення

Пов'язані сторінки

Додаткові матеріали

Спробуйте наживо

Дослідіть пов'язану модель на практиці: відкрийте AI Anomaly Detection Lab — A Manufacturing Sensor Case Study і змінюйте параметри під час роботи. Усе лишається у вашому браузері.

▶ Відкрити симуляцію AI Anomaly Detection Lab — A Manufacturing Sensor Case Study

Що ви знайшли?

Додати кроки відтворення (опційно)