Обнаружение аномалий - это выявление редких элементов, событий или наблюдений, вызывающих подозрения, поскольку они значительно отличаются от большинства данных. Обычно аномальные элементы приводят к возникновению каких-либо проблем, таких как мошенничество с кредитными картами, вторжение в сеть, медицинская диагностика, мониторинг состояния системы.

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

  • Аномалии в данных встречаются очень редко.
  • Их особенности существенно отличаются от обычных экземпляров.

Методы обнаружения аномалий

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

Самый простой подход к выявлению нарушений в данных - это пометить точки данных, которые отклоняются от общих статистических свойств распределения, включая среднее значение, медианное значение, режим и квартили.

Один из самых популярных способов - это Межквартильный диапазон (IQR). IQR - это понятие в статистике, которое используется для измерения статистической дисперсии и изменчивости данных путем разделения набора данных на квартили.

Проще говоря, любой набор данных или любой набор наблюдений делится на четыре определенных интервала, основанных на значениях данных и их сравнении со всем набором данных. Квартиль - это то, что делит данные на три точки и четыре интервала.

Источник изображения: Википедия

Межквартильный размах (IQR) важен, потому что он используется для определения выбросов. Это разница между третьим квартилем и первым квартилем (IQR = Q3 -Q1). Выбросы в данном случае определяются как наблюдения ниже (Q1 - 1,5x IQR) или выше (Q3 + 1,5x IQR).

Источник изображения: Википедия

Реализация

np.percentile - это запеченная функциональность в Python

q75, q25 = np.percentile(x, [75 ,25])
iqr = q75 - q25

Недостатки

Методика IQR не работает в следующих сценариях

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

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

Обнаружение аномалий на основе кластеризации

Кластеризация - одна из самых популярных концепций в области обучения без учителя. Основная предпосылка заключается в том, что аналогичные точки данных обычно принадлежат схожим группам или кластерам, что определяется их расстоянием от локальных центроидов.

K-means - широко используемый алгоритм кластеризации. Он создает «k» похожих кластеров точек данных. Экземпляры данных, которые не входят в эти группы, потенциально могут быть отмечены как аномалии. Другие алгоритмы кластеризации, такие как иерархическая кластеризация и сканирование БД, также могут использоваться для обнаружения выбросов.

Алгоритм K-средних работает следующим образом:

  1. Укажите количество кластеров K.
  2. Инициализируйте центроиды, сначала перетасовывая набор данных, а затем случайным образом выбирая K точек данных для центроидов без замены.
  3. Рассчитайте расстояния между центроидами и точками данных.
  4. Продолжайте повторять до тех пор, пока центроиды не останутся без изменений. то есть назначение точек данных кластерам не меняется.

Реализация

  1. Инициализировать случайные центроиды

Вы начинаете процесс с взятия трех (поскольку мы решили, что K равняется 3) случайным точкам (в форме (x, y)). Эти точки называются центроидами, что является просто причудливым названием для обозначения центров. Назовем эти три точки C1, C2, и C3, чтобы вы могли ссылаться на них позже.

2. Вычислить расстояния между центроидами и точками данных

Затем вы измеряете расстояния между точками данных от этих трех случайно выбранных точек. Очень популярным выбором функции измерения расстояния в данном случае является Евклидово расстояние.

Вкратце, если есть n точек в 2D-пространстве (как на рисунке выше) и их координаты обозначены (x_i, y_i), то евклидово расстояние между любыми двумя точками ((x1, y1) и (x2, y2)) на этом пространстве определяется как:

Предположим, что координаты C1, C2 и C3 - (-1, 4), (-0,2, 1,5), и (2, 2,5) соответственно. Давайте теперь напишем несколько строк кода Python, который будет вычислять евклидовы расстояния между точками данных и этими случайно выбранными центроидами. Начнем с инициализации центроидов.

# Initialize the centroids
c1 = (-1, 4)
c2 = (-0.2, 1.5)
c3 = (2, 2.5)

Затем мы пишем небольшую вспомогательную функцию для вычисления евклидовых расстояний между точками данных и центроидами.

# A helper function to calculate the Euclidean distance between the data points and the centroids
def calculate_distance(centroid, X, Y):
    distances = []
        
    # Unpack the x and y coordinates of the centroid
    c_x, c_y = centroid
        
    # Iterate over the data points and calculate the distance using the           # given formula
    for x, y in list(zip(X, Y)):
        root_diff_x = (x - c_x) ** 2
        root_diff_y = (y - c_y) ** 2
        distance = np.sqrt(root_diff_x + root_diff_y)
        distances.append(distance)
        
    return distances

Теперь мы можем применить эту функцию к точкам данных и соответствующим образом назначить результаты.

# Calculate the distance and assign them to the DataFrame accordingly
data['C1_Distance'] = calculate_distance(c1, data.X_value, data.Y_value)
data['C2_Distance'] = calculate_distance(c2, data.X_value, data.Y_value)
data['C3_Distance'] = calculate_distance(c3, data.X_value, data.Y_value)
# Preview the data
print(data.head())

3. Сравнить, назначить, усреднить и повторить

По сути, это последний шаг алгоритма кластеризации K-средних. Когда у вас есть расстояния между точками данных и центроидами, вы сравниваете расстояния и выбираете наименьшие. Центроид, до которого расстояние для конкретной точки данных является наименьшим, этот центроид назначается как кластер для этой конкретной точки данных.

Давайте сделаем это программно.

# Get the minimum distance centroids
    data['Cluster'] = data[['C1_Distance', 'C2_Distance', 'C3_Distance']].apply(np.argmin, axis =1)
    
# Map the centroids accordingly and rename them
    data['Cluster'] = data['Cluster'].map({'C1_Distance': 'C1', 'C2_Distance': 'C2', 'C3_Distance': 'C3'})
    
# Get a preview of the data
    print(data.head(10))

Теперь наступает самая интересная часть обновления центроидов путем определения средних значений координат точек данных (которые к настоящему времени должны принадлежать какому-либо центроиду). Отсюда и название K-Means. Вот как выглядит расчет среднего:

Следующие строки кода сделают это за вас:

# Calculate the coordinates of the new centroid from cluster 1
x_new_centroid1 = data[data['Cluster']=='C1']['X_value'].mean()
y_new_centroid1 = data[data['Cluster']=='C1']['Y_value'].mean()
# Calculate the coordinates of the new centroid from cluster 2
x_new_centroid2 = data[data['Cluster']=='C3']['X_value'].mean()
y_new_centroid2 = data[data['Cluster']=='C3']['Y_value'].mean()
# Print the coordinates of the new centroids
print('Centroid 1 ({}, {})'.format(x_new_centroid1, y_new_centroid1))
print('Centroid 2 ({}, {})'.format(x_new_centroid2, y_new_centroid2))

Этот процесс повторяется до тех пор, пока координаты центроидов больше не обновляются.

Недостатки

Алгоритм K-средних популярен и используется во множестве приложений, таких как сжатие изображений, классификация документов. Цель K-среднего - сгруппировать точки данных в отдельные неперекрывающиеся подгруппы. Это очень хорошо работает, когда кластеры имеют сферическую форму. Однако он страдает, поскольку геометрические формы кластеров отклоняются от сферических. Более того, он также не узнает количество кластеров из данных и требует, чтобы оно было предварительно определено.

Изолированный лес

Isolation Forest - это алгоритм обучения без учителя, который принадлежит к семейству ансамблевых деревьев решений. Этот подход отличается от всех предыдущих методов. Все предыдущие пытались найти нормальную область данных, а затем идентифицировали все, что находится за пределами этой определенной области, как выброс или аномальное. Этот метод работает иначе. Он явно изолирует аномалии вместо профилирования и построения нормальных точек и областей, присваивая оценку каждой точке данных. Он использует тот факт, что аномалии являются меньшими точками данных и что они имеют значения атрибутов, которые сильно отличаются от значений для нормальных экземпляров.

IsolationForest «изолирует» наблюдения, случайным образом выбирая объект, а затем случайным образом выбирая значение разделения между максимальным и минимальным значениями выбранного объекта.

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

Эта длина пути, усредненная по лесу таких случайных деревьев, является мерой нормальности и нашей решающей функцией.

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

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

В этой статье подробно рассказывается о том, как работает изоляционный лес.

Реализация

import numpy as np
import matplotlib.pyplot as plt
from sklearn.ensemble import IsolationForest
rng = np.random.RandomState(42)
# Generate train data
X = 0.3 * rng.randn(100, 2)
X_train = np.r_[X + 2, X - 2]
# Generate some regular novel observations
X = 0.3 * rng.randn(20, 2)
X_test = np.r_[X + 2, X - 2]
# Generate some abnormal novel observations
X_outliers = rng.uniform(low=-4, high=4, size=(20, 2))
# fit the model
clf = IsolationForest(max_samples=100, random_state=rng)
clf.fit(X_train)
y_pred_train = clf.predict(X_train)
y_pred_test = clf.predict(X_test)
y_pred_outliers = clf.predict(X_outliers)
# plot the line, the samples, and the nearest vectors to the plane
xx, yy = np.meshgrid(np.linspace(-5, 5, 50), np.linspace(-5, 5, 50))
Z = clf.decision_function(np.c_[xx.ravel(), yy.ravel()])
Z = Z.reshape(xx.shape)
plt.title("IsolationForest")
plt.contourf(xx, yy, Z, cmap=plt.cm.Blues_r)
b1 = plt.scatter(X_train[:, 0], X_train[:, 1], c='white',
                 s=20, edgecolor='k')
b2 = plt.scatter(X_test[:, 0], X_test[:, 1], c='green',
                 s=20, edgecolor='k')
c = plt.scatter(X_outliers[:, 0], X_outliers[:, 1], c='red',
                s=20, edgecolor='k')
plt.axis('tight')
plt.xlim((-5, 5))
plt.ylim((-5, 5))
plt.legend([b1, b2, c],
           ["training observations",
            "new regular observations", "new abnormal observations"],
           loc="upper left")
plt.show()

Источник: scikit-learn.org

Заключение

В этом посте представлен обзор различных методов обнаружения аномалий в данных. Он варьируется от использования простых статистических методов, таких как стандартное отклонение, до алгоритмов обучения без учителя, таких как Isolation Forest. У каждого метода есть свои преимущества и недостатки. Например. Межквартильный (IQR) не работает для сезонных моделей, кластеризация K-средних хороша для группирования данных в отдельные неперекрывающиеся подгруппы. Это очень хорошо работает, когда кластеры имеют сферическую форму. Isolation Forest предлагает противоположный подход к обнаружению аномалий. Он использует тот факт, что аномалии являются меньшими точками данных и что они имеют значения атрибутов, которые сильно отличаются от значений для нормальных экземпляров. Чтобы быть хорошим практиком, хорошо знать предположения, лежащие в основе алгоритмов / методов, чтобы иметь довольно хорошее представление о сильных и слабых сторонах каждого метода. Это поможет вам решить, когда использовать каждый метод и при каких обстоятельствах.