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

Введение в алгоритм изолированного леса

Обнаружение аномалий — это процесс обнаружения необычных или аномальных точек данных в наборе данных. Это важный метод мониторинга и предотвращения мошенничества, а также обнаружения ошибок в данных. К сожалению, аномалии бывает очень трудно обнаружить, учитывая, что: 1) они обычно возникают нечасто, 2) они могут не иметь четких закономерностей идентификации и 3) аномалии могут быть явно разными даже в пределах одного и того же набора данных.

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

Алгоритм работает путем построения нескольких деревьев решений для классификации точек данных. Каждое дерево решений будет построено с использованием различных подмножеств входных функций, которые затем объединяются для формирования окончательного дерева решений. Изолирующий лес работает, разделяя пространство данных на n сегментов как разбиения, которые ортогональны исходной точке (попробуйте визуализировать разделительные линии, проведенные через набор данных) и присвоит более высокие оценки аномалии точкам данных, которым требуется только несколько из них. расколы должны быть изолированы. Для получения более подробной информации об изолированном лесу вы можете просмотреть документацию scikit-learn здесь.

Зачем использовать изолированный лес для обнаружения аномалий?

Краткий обзор преимуществ использования изолированного леса для обнаружения аномалий заключается в следующем:

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

Возможные ограничения при использовании изолированного леса

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

Требования к алгоритму и входные параметры

Ключевыми требованиями для этого проекта являются установленные на вашем компьютере numpy, pandas и scikitlearn. Кроме того, для визуального изучения данных мы будем использовать matplotlib, seaborn и plotly express.

Для начала давайте проверим параметры алгоритма изолированного леса, используя функцию справки Python.

from sklearn.ensemble import IsolationForest
help(IsolationForest)

Важными параметрами в алгоритмах являются:

  • количество деревьев / оценщики: насколько велик лес
  • загрязнение: часть набора данных, которая содержит аномальные экземпляры, т.е. 0,1 или 10%. Алгоритм очень чувствителен к этому параметру, и невероятно полезно иметь первоначальное представление об ожидаемой частоте возникновения аномалий.
  • макс. выборки: количество выборок из обучающего набора для обучения каждого дерева изоляции.
  • максимальная глубина: насколько глубоким должно быть дерево, это можно использовать для обрезки дерева и ускорения работы.

Пример кода обнаружения мошенничества с кредитными картами

В этом примере мы проанализируем набор данных транзакций по кредитным картам на наличие аномалий, используя алгоритм изолированного леса. Набор данных содержит транзакции, совершенные по кредитным картам в сентябре 2013 года держателями карт из Европы. Этот набор данных представляет транзакции, которые произошли за два дня, где у нас есть 492 мошенничества из 284 807 транзакций. Набор данных сильно несбалансирован, положительный класс (мошенничество = 1) составляет 0,172% всех транзакций и доступен здесь благодаря kaggle.

Импорт основных модулей

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
pd.set_option("display.float", "{:.2f}".format)
%matplotlib inline
sns.set_style("whitegrid")

загружать данные и проверять столбцы

data = pd.read_csv("creditcard.csv")
data.head()

data['Class'].value_counts()

Набор данных имеет 31 столбец, состоящий из 30 потенциальных признаков и 1 столбца меток «Класс» (аномалии = 1). Мы также подтверждаем, что класс содержит очень мало аномалий (492).

Исследование функции времени

Набор данных содержит столбец времени (в секундах), который потенциально может повлиять на то, как мы подходим к проблеме. В распределении времени между мошенническими и немошенническими транзакциями нет визуальной зависимости.

plt.figure(figsize=(14, 12))
plt.subplot(2, 2, 1)
data[data.Class == 1].Time.hist(bins=35, color='blue', alpha=0.6, label="Fraudulant Transaction")
plt.legend()
plt.subplot(2, 2, 2)
data[data.Class == 0].Time.hist(bins=35, color='blue', alpha=0.6, label="Non Fraudulant Transaction")
plt.legend()

Используйте PCA, чтобы попытаться визуализировать аномалии

Используя PCA, мы можем визуализировать проблемы высокой размерности в плоскости более низкого измерения. Из матрицы разброса видно, что аномалии имеют тенденцию занимать определенные области в разбросах, особенно для компонентов PC1 и PC3. Что мы хотели бы увидеть в конце этого упражнения, так это то, что изолированный лес идентифицирует похожие регионы после обучения.

import plotly.express as px
from sklearn.decomposition import PCA
n_components=3
pca = PCA(n_components=n_components)
components = pca.fit_transform(data)
total_var = pca.explained_variance_ratio_.sum() * 100
labels = {str(i): f"PC {i+1}" for i in range(n_components)}
labels['color'] = 'Class'
fig = px.scatter_matrix(
    components,
    color=data['Class'],
    dimensions=range(n_components),
    labels=labels,
    title=f'Total Explained Variance: {total_var:.2f}%',
)
fig.update_traces(diagonal_visible=False)
fig.show()

Подготовка данных

Дополнительные преобразования, такие как логарифмическая нормализация и минимальное-максимальное масштабирование, не требуются для изолированных лесов, поскольку они должны иметь минимальное влияние на количество «алгоритмических срезов», необходимых для изоляции точек данных.

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

X = data.drop('Class', axis=1)
y = data.Class
from sklearn.ensemble import IsolationForest
Iforest = IsolationForest(max_samples=100, 
                          random_state=1111,
                         contamination=0.05,
                         max_features=1.0,
                         n_estimators=100,
                         verbose=1,
                         n_jobs=-1)
Iforest.fit(X)

Алгоритм идентифицировал 14241 точку данных как аномальную (около 5%), что точно соответствует первоначально заданному входному параметру загрязнения.

y_pred = Iforest.predict(X)
y_pred_adjusted = [1 if x == -1 else 0 for x in y_pred]
sum(y_pred_adjusted)
Out: 14241

Оценка

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

Для оценки алгоритма мы будем вычислять метрики глобально, подсчитывая общее количество истинных срабатываний, ложноотрицательных и ложноположительных результатов. Sklearn имеет встроенные функции для поддержки вычисления показателей точности, отзыва, F-меры и поддержки каждого класса.

  • Точность — это отношение tp / (tp + fp), где tp — количество истинных срабатываний, а fp — количество ложных срабатываний. Точность — это интуитивно способность классификатора не маркировать отрицательный образец как положительный.
  • Отзыв представляет собой отношение tp / (tp + fn), где tp — количество истинных положительных результатов, а fn — количество ложноотрицательных результатов. Под отзывом понимается интуитивно способность классификатора находить все положительные образцы.
  • Показатель F1 можно интерпретировать как среднее гармоническое между точностью и полнотой, где показатель F1 достигает своего наилучшего значения при 1, а наихудший показатель при 0. F1 = 2 * (точность * полнота) / (точность + полнота)

Однако точность 88% с точки зрения обнаружения аномалий является очень обнадеживающим результатом и означает, что алгоритм точно выделяет аномальные данные.

from sklearn.metrics import precision_recall_fscore_support
precision_recall_fscore_support(y, y_pred_adjusted, average='macro')
Out:
(0.5140217751041775, 0.8862351802914121, 0.5148736994136962, None)

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

from sklearn.metrics import confusion_matrix
cm = confusion_matrix(y, y_pred_adjusted)
from sklearn.metrics import ConfusionMatrixDisplay
disp = ConfusionMatrixDisplay(confusion_matrix=cm, display_labels=[0, 1])
disp.plot()
plt.show()

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

data['predictions'] = Iforest.predict(X)
data['predictions'] = np.where(data['predictions']==-1,1,0)
n_components=3
pca = PCA(n_components=n_components)
components = pca.fit_transform(data)
total_var = pca.explained_variance_ratio_.sum() * 100
labels = {str(i): f"PC {i+1}" for i in range(n_components)}
labels['color'] = 'Class'
fig = px.scatter_matrix(
    components,
    color=data['predictions'],
    dimensions=range(n_components),
    labels=labels,
    title=f'Total Explained Variance: {total_var:.2f}%',
)
fig.update_traces(diagonal_visible=False)
fig.show()

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

Чувствительность лесов изоляции к параметру загрязнения

Я подтвердил чувствительность алгоритма к фактору загрязнения после проведения нескольких последовательных запусков моделирования. Фактор загрязнения 2% (что близко к ожидаемому) обеспечивает приемлемую точность, гарантируя, что ложные срабатывания сведены к минимуму.

Так, что дальше?

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

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

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

Вы можете получить доступ к примеру кода здесь.

Использованная литература: