Skip to content

Обнаружение аномалий в табличных данных

Обзор

Обнаружение аномалий в табличных данных в applybn реализует неконтролируемое обнаружение выбросов путем оценки баллов. Баллы управляются объектом TabularDetector. Основа этого алгоритма была взята из "Effective Outlier Detection based on Bayesian Network and Proximity".

applybn содержит несколько новых модификаций этого алгоритма, таких как различные баллы, смягчение ограничений нормальности, работа со смешанными данными.

Список изменений:

  • Добавлена поддержка смешанных данных
  • Добавлено несколько новых методов, таких как IQR, Cond Ratio Probability, основанных на произвольной байесовской сети.

Пожалуйста, учитывайте эту таблицу при выборе подходящего алгоритма:

Тип данных Разрешенные методы
Непрерывные iqr, original_modified
Дискретные cond_ratio, original_modified
Смешанные cond_ratio + iqr (по умолчанию), original_modified

Математическая основа

Исходный метод

Исходный метод использует байесовские сети с улучшением на основе близости для обнаружения выбросов.

Моделирование байесовской сети

Для набора данных \( \mathcal{D} = \{\mathbf{x}^{(1)}, \dots, \mathbf{x}^{(N)}\} \), где каждая строка \( \mathbf{x}^{(j)} = (x_1^{(j)}, x_2^{(j)}, \dots, x_n^{(j)}) \), авторы сначала обучают структуру и параметры байесовской сети:

  • Структура: DAG \( G \), где каждый узел \( X_i \) имеет набор родителей \( \text{Pa}(X_i) \)
  • Параметры: УРВ для каждого \( X_i \mid \text{Pa}(X_i) \), обычно гауссовы, если переменные непрерывны.
Оценка строк на основе правдоподобия

После обучения сети правдоподобие каждой строки \( \mathbf{x} \) оценивается как:

\[ P(\mathbf{x}) = \prod_{i=1}^{n} P(x_i \mid \text{Pa}_i(\mathbf{x})) \]

Где \( \text{Pa}_i(\mathbf{x}) \) — это значения \( \text{Pa}(X_i) \) в той же строке.

Оценка строк

Они вычисляют балл аномалии следующим образом.

Если УРВ являются гауссовыми:

\[ P(x_i \mid \text{Pa}_i(\mathbf{x})) = \frac{1}{\sqrt{2\pi\sigma_i^2}} \exp\left( -\frac{(x_i - \mu_i(\text{Pa}_i))^2}{2\sigma_i^2} \right) \]

Тогда балл становится:

\[ S_{\text{BN}}(\mathbf{x}) = \sum_{i=1}^{n} \frac{(x_i - \mu_i(\text{Pa}_i(\mathbf{x})))^2}{2\sigma_i^2} \]

Улучшение на основе близости

Для улучшения обнаружения (особенно для локальных аномалий) они добавляют балл на основе близости. Они определяют комбинированный балл аномалии как:

\[ S_{\text{Total}}(\mathbf{x}) = S_{\text{BN}}(\mathbf{x}) + S_{\text{prox}}(\mathbf{x}) \]

Где \( S_{prox}(x) \) — это отрицательные факторы из LOF.


Исходный модифицированный метод

Для набора переменных \( X = \{X_1, X_2, \dots, X_n\} \) байесовская сеть определяет совместное распределение как:

\[ P(X) = \prod_{i=1}^{n} P(X_i \mid \text{Pa}(X_i)) \]

Где:

  • \( \text{Pa}(X_i) \) обозначает родителей узла \( X_i \) в DAG.
  • Каждое \( P(X_i \mid \text{Pa}(X_i)) \) — это условное распределение вероятностей (УРВ).

Пусть:

  • \( \mathcal{D} = \{\mathbf{x}^{(1)}, \dots, \mathbf{x}^{(N)}\} \)
  • \( \text{pa}_i^{(j)} = \text{pa}_i(\mathbf{x}^{(j)}) \), значения родителей \( X_i \) в строке \( j \)

Тогда локальный балл для узла \( X_i \) в строке \( j \) равен:

\[ s_i^{(j)} = \text{Score}(x_i^{(j)} \mid \text{pa}_i^{(j)}) \]

Этот балл вычисляется путем сравнения \( x_i^{(j)} \) с другими значениями \( X_i \), которые имеют схожие значения родителей \( \text{pa}_i^{(j)} \). Это можно выразить с помощью условной группы:

\[ s_i^{(j)} = \phi \left( x_i^{(j)}, \{ x_i^{(k)} \mid \text{pa}_i^{(k)} = \text{pa}_i^{(j)} \} \right) \]

Где \( \phi \) — это функция сравнения для оценки.


Метод IQR (межквартильный размах)

Для данной строки \( j \):

  • \( y = x_i^{(j)} \)
  • Условное множество: \( \mathcal{C}_i^{(j)} = \{ x_i^{(k)} \mid \text{pa}_i^{(k)} = \text{pa}_i^{(j)} \} \)

  • Границы IQR для узла \( i \) при конфигурации родителей \( \text{pa}_i^{(j)} \): \( Q_1 = \text{Quantile}_{25\%}(\mathcal{C}_i^{(j)}), \quad Q_3 = \text{Quantile}_{75\%}(\mathcal{C}_i^{(j)}) \)

  • IQR: \( \text{IQR}_i^{(j)} = \alpha \cdot (Q_3 - Q_1) \), где \(\alpha\) — гиперпараметр

  • Границы: \( \text{Lower}_i^{(j)} = Q_1, \quad \text{Upper}_i^{(j)} = Q_3 \)

  • Референсные расстояния: \( d_{\min} = \min(\mathcal{C}_i^{(j)}), \quad d_{\max} = \max(\mathcal{C}_i^{(j)}) \)


Функция оценки на основе IQR

Теперь определим балл узла \( s_i^{(j)} \) как:

\[ s_i^{(j)} = \begin{cases} 0, & \text{если } \text{Lower}_i^{(j)} < x_i^{(j)} \leq \text{Upper}_i^{(j)} \\[6pt] \min\left(1, \dfrac{|x_i^{(j)} - c|}{|d|} \right), & \text{иначе} \end{cases} \]

Где:

  • \( c = \arg\min_{b \in \{\text{Lower}_i^{(j)}, \text{Upper}_i^{(j)}\}} |x_i^{(j)} - b| \)
  • \( d = \begin{cases} d_{\max}, & \text{если } c = \text{Upper}_i^{(j)} \\ d_{\min}, & \text{если } c = \text{Lower}_i^{(j)} \\ \end{cases} \)

Вероятность условного отношения

Баллы, основанные на том, насколько неожиданным является значение при его условном распределении по сравнению с маржинальным распределением.

Пусть:

  • \( X_i \) — узел, а \( x_i^{(j)} \) — его значение в строке \( j \)
  • \( \text{pa}_i^{(j)} \) — конфигурация родителей для этой строки
  • \( \mathcal{D} \) — набор данных

Мы определяем:

  • Маржинальная вероятность значения \( x_i^{(j)} \):
\[ P(x_i^{(j)}) = \frac{\#(x_i = x_i^{(j)})}{N} \]
  • Условная вероятность значения при заданных родителях:
\[ P(x_i^{(j)} \mid \text{pa}_i^{(j)}) = \frac{\#(x_i = x_i^{(j)} \land \text{pa}_i = \text{pa}_i^{(j)})}{\#(\text{pa}_i = \text{pa}_i^{(j)})} \]

Теперь локальный балл для узла \( X_i \) и строки \( j \) равен:

\[ s_i^{(j)} = \begin{cases} \text{NaN}, & \text{если } \frac{P(x_i^{(j)})}{P(x_i^{(j)} \mid \text{pa}_i^{(j)})} \notin \mathbb{R} \\ \min\left(1, \frac{P(x_i^{(j)})}{P(x_i^{(j)} \mid \text{pa}_i^{(j)})} \right), & \text{иначе} \end{cases} \]

Этот балл измеряет, насколько удивительным является значение, учитывая его контекст в сети — более высокие значения подразумевают менее ожидаемое поведение условно.

Пример

examples/anomaly_detection/tabular.py
"""
Example usage script for the Tabular Detector class defined in tabular_detector.py.

This script demonstrates how to:
1. Load the E.coli Adult dataset (as an example).
2. Create and configure the Tabular Detector.
3. Detect anomalies in the E.coli dataset, get scores, plot the result.

Run this script to see how the methods can be chained together for end-to-end analysis.
"""

import pandas as pd
from sklearn.metrics import classification_report
from applybn.anomaly_detection.static_anomaly_detector.tabular_detector import (
    TabularDetector,
)


def main():
    # run from applybn root or change path here
    data = pd.read_csv("applybn/anomaly_detection/data/tabular/ecoli.csv")

    detector_default = TabularDetector(target_name="y")
    detector_iqr = TabularDetector(target_name="y", model_estimation_method="iqr")
    detector_IF = TabularDetector(target_name="y", additional_score="IF")

    detector_default.fit(data)
    detector_iqr.fit(data)
    detector_IF.fit(data)

    preds_default = detector_default.predict(data)
    preds_iqr = detector_iqr.predict(data)
    preds_IF = detector_IF.predict(data)

    # let's compare the result of different methods
    print(classification_report(data["y"], preds_default))
    print("___")
    print(classification_report(data["y"], preds_iqr))
    print("___")
    print(classification_report(data["y"], preds_IF))


if __name__ == "__main__":
    main()