
Недавно я узнал о нескольких методах обнаружения аномалий в Python. Эти методы идентифицируют аномалии (выбросы) более математическим способом, чем просто построение диаграммы рассеяния или гистограммы и их визуального наблюдения. Если точка является выбросом по отношению к своим значениям по 30 характеристикам (многомерный выброс), вы не можете идентифицировать ее с помощью описанных выше методов, и именно здесь они пригодятся.
Формат сообщения в блоге (большинство техник имеют следующий формат):
- Объяснение техники
- Базовая реализация в sklearn
- Визуализация, показывающая аномалии, выявленные с помощью техники
- Источники, использованные выше
Охватываемые методы:
- DBSCAN
- Изоляционные леса
- Фактор местного выброса
- Эллиптический конверт
- Одноклассные машины опорных векторов
Некоторые определения:
- выброс - это наблюдение, в котором по крайней мере одна переменная имеет необычное значение.
- Одномерный выброс - это наблюдение с переменной, имеющей необычное значение.
- Многомерный выброс - это наблюдение, в котором по крайней мере две переменные имеют необычные значения.
Эти методы идентифицируют выбросы, так что выбросы могут быть одномерными или многомерными.
Несколько учебников с обсуждаемыми методами:
1. Практическое машинное обучение с помощью scikit-learn и Scientific Python Toolkits (выпущено 24.07.2020)
Обсуждает DBSCAN, Isolation Forests, LOF, Elliptic Envelope (легко читать )
2. Начало обнаружения аномалий с использованием глубокого обучения на основе Python: с Keras и PyTorch 1-е изд. 2019
Обсуждает изолированные леса, одноклассную SVM и многое другое (легко читается)
3. Анализ выбросов 2-е изд. Издание 2017 г.
Обсуждает изолированные леса, LOF, одноклассную SVM и многое другое (труднее читать)
Набор данных, используемый в примерах кода:
https://www.kaggle.com/akram24/mall-customers
Предварительная обработка данных:
data=data.drop(‘CustomerID’,axis=1)
data=data.rename(columns={
‘Annual Income (k$)’:’Income’,
‘Spending Score (1–100)’:’Spend_Score’})
df=pd.get_dummies(data)
from sklearn.preprocessing import MinMaxScaler
scaler = MinMaxScaler()
num2 = scaler.fit_transform(num)
num2 = pd.DataFrame(num2, columns = num.columns)
DBSCAN (Пространственная кластеризация приложений с шумом на основе плотности)
Это алгоритм кластеризации (альтернатива K-средних), который объединяет точки в кластеры и идентифицирует любые точки, не принадлежащие кластеру, как выбросы. Это похоже на K-средство, за исключением того, что количество кластеров не нужно указывать заранее.
Пошаговый метод:
- Произвольно выберите точку, которая еще не включена в кластер или не обозначена как выброс. Определите, является ли это центральной точкой, посмотрев, есть ли вокруг нее хотя бы min_samples точек на расстоянии эпсилон.
- Создайте кластер из этой базовой точки и всех точек на расстоянии эпсилон от нее (все непосредственно достижимые точки).
- Найдите все точки, которые находятся на расстоянии эпсилон от каждой точки в кластере, и добавьте их в кластер. Найдите все точки, которые находятся на расстоянии эпсилон от всех вновь добавленных точек, и добавьте их в кластер. Промыть и повторить. (т. е. выполнить «скачки по соседству», чтобы найти все точки, достижимые по плотности, и добавить их в кластер).
Язык, лежащий в основе вышеизложенного:
- Любая точка, имеющая не менее min_samples точек на расстоянии эпсилон от нее, образует кластер. Эта точка называется центральной точкой. Сама основная точка будет учитываться при выполнении требования min_samples.
- Любая точка на расстоянии эпсилон от базовой точки, но не имеет точек min_samples, находящихся на расстоянии эпсилон от самой себя, называется пограничной точкой и не образует собственного кластера.
- Граничная точка, которая находится на расстоянии эпсилон от нескольких основных точек (нескольких шариков эпсилон), произвольно окажется только в одном из этих результирующих кластеров.
- Любая случайно выбранная точка, которая не является основной или пограничной, называется шумовой точкой или выбросом и не назначается ни одному кластеру. Таким образом, он не содержит по крайней мере min_samples точек, которые находятся на расстоянии эпсилон от него или не находятся на расстоянии эпсилон от базовой точки.
- Эпсилон-окрестность точки p - это все точки в пределах эпсилон расстояния от p, которые считаются непосредственно достижимыми из p.
- Точка, содержащаяся в окрестности точки, непосредственно достижимой из p, не обязательно напрямую достижима из p, но достижима по плотности.
- Любая точка, которую можно достичь, перескакивая из соседства в район от исходной базовой точки, является достижимой по плотности.
Рекомендации по реализации:
1. Возможно, вам сначала потребуется стандартизировать / масштабировать / нормализовать ваши данные.
2. Помните о типе данных и измерении расстояния. Я читал, что показатель расстояния Гоуэра можно использовать для смешанных типов данных. Здесь я реализовал евклидову систему, для которой нужны непрерывные переменные, поэтому я удалил пол.
3. Вам нужно оптимизировать epsilon и min_samples.
Реализация DBSCAN в Sklearn:
from sklearn.cluster import DBSCAN outlier_detection = DBSCAN( eps = .2, metric=”euclidean”, min_samples = 5, n_jobs = -1) clusters = outlier_detection.fit_predict(num2)
DBSCAN выведет массив из -1 и 0, где -1 означает выброс. Ниже я визуализирую выведенные выбросы красным цветом, нанося на график две переменные.
from matplotlib import cm cmap = cm.get_cmap(‘Set1’) num.plot.scatter(x=’Spend_Score’,y=’Income’, c=clusters, cmap=cmap, colorbar = False)

Дополнительная информация о DBSCAN:
Ссылки на учебники
1. Практическое машинное обучение с помощью наборов инструментов scikit-learn и Scientific Python (выпущено 24.07.2020)
2. Практическое машинное обучение с помощью Scikit-Learn, Keras и TensorFlow… (от 10/2019)
3. «Принципы и алгоритмы обнаружения аномалий, 2017 г. Версия"
Веб-ссылки
- Https://mikulskibartosz.name/outlier-detection-with-scikit-learn-d9246b33d352
- Https://blog.dominodatalab.com/topology-and-de density-based-clustering/
- Http://mccormickml.com/2016/11/08/dbscan-clustering/
- Https://www.naftaliharris.com/blog/visualizing-dbscan-clustering/
- Https://www.quora.com/How-does-DBSCAN-algorithm-work
- Https://towardsdatascience.com/how-dbscan-works-and-why-should-i-use-it-443b4a191c80
- Https://medium.com/@elutins/dbscan-what-is-it-when-to-use-it-how-to-use-it-8bd506293818
- Https://medium.com/@soroush.hashemi76/kmeans-vs-dbscan-d9d5f9dbee8b
Изоляционные леса
Для каждого наблюдения сделайте следующее:
- Случайным образом выберите функцию и случайным образом выберите значение для этой функции в пределах ее диапазона.
- Если значение объекта наблюдения падает выше (ниже) выбранного значения, то это значение становится новым минимальным (максимальным) диапазоном этого объекта.
- Убедитесь, что хотя бы одно другое наблюдение имеет значения в диапазоне каждого объекта в наборе данных, где некоторые диапазоны были изменены на шаге 2. Если нет, то наблюдение изолировано.
- Повторяйте шаги 1–3, пока наблюдение не станет изолированным. Количество раз, которое вам пришлось пройти через эти шаги, и есть число изоляции. Чем меньше число, тем аномальнее наблюдение.
Внедрение Isolation Forests в Sklearn:
from sklearn.ensemble import IsolationForest rs=np.random.RandomState(0) clf = IsolationForest(max_samples=100,random_state=rs, contamination=.1) clf.fit(df) if_scores = clf.decision_function(df) if_anomalies=clf.predict(df) if_anomalies=pd.Series(if_anomalies).replace([-1,1],[1,0]) if_anomalies=num[if_anomalies==1];
Ниже я строю гистограмму значений if_scores . Более низкие значения указывают на более аномальные наблюдения.
plt.figure(figsize=(12,8)) plt.hist(if_scores); plt.title(‘Histogram of Avg Anomaly Scores: Lower => More Anomalous’);

Ниже я привожу наблюдения, идентифицированные как аномалии. Эти наблюдения имеют значения if_scores ниже значения clf.threshold_.
cmap=np.array(['white','red'])
plt.scatter(df.iloc[:,1],df.iloc[:,2],c='white',s=20,edgecolor='k')
plt.scatter(if_anomalies.iloc[:,0],if_anomalies.iloc[:,1],c='red')
plt.xlabel('Income')
plt.ylabel('Spend_Score')
plt.title('Isolation Forests - Anomalies')

Дополнительная информация о изолированных лесах:
Учебники
1. Практическое машинное обучение с помощью scikit-learn и Scientific Python Toolkits (выпущено 24.07.2020)
2. Начало обнаружения аномалий с использованием глубокого обучения на основе Python: с Keras и PyTorch 1-е изд. 2019
3 . Анализ выбросов 2-е изд. Издание 2017 г.
Веб-ссылки
- Https://www.depends-on-the-definition.com/detecting-network-attacks-with-isolation-forests/
- Https://stackoverflow.com/questions/45223921/what-is-the-range-of-scikit-learns-isolationforest-decision-function-scores
- Https://quantdare.com/isolation-forest-algorithm/
- Https://medium.com/@hyunsukim_9320/isolation-forest-step-by-step-341b82923168
- Http://www.ncsa.illinois.edu/Conferences/LSST18/assets/pdfs/hariri_forest.pdf
- Https://scikit-learn.org/stable/modules/generated/sklearn.ensemble.IsolationForest.html
Фактор местного выброса
LOF использует обнаружение выбросов на основе плотности для выявления локальных выбросов, точек, которые являются выбросами по отношению к их локальному соседству, а не по отношению к глобальному распределению данных. Чем выше значение LOF для наблюдения, тем более аномальным является наблюдение.
Это полезно, потому что не все методы не идентифицируют точку, которая является выбросом относительно ближайшего кластера точек (локального выброса), если весь этот регион не является удаленным регионом в глобальном пространстве точек данных.
Точка помечается как выброс, если плотность вокруг этой точки значительно отличается от плотности вокруг ее соседей.
В приведенном ниже пространстве функций LOF может идентифицировать P1 и P2 как выбросы, которые являются локальными выбросами для кластера 2 (в дополнение к P3).
Пример локальных и глобальных выбросов:

Пошаговый метод:
Для каждой точки P выполните следующие действия:
- Рассчитайте расстояния между P и любой другой точкой (манхэттен = | x1-x2 | + | y1-y2 |) = dist (p1, p2)
- Найдите K-ю ближайшую точку (расстояние K-го ближайшего соседа = K-Dist (P))
- Найдите K ближайших точек (те, чьи расстояния меньше, чем K-я точка), K-расстояние окрестности P, Nk (P).
- Найдите его плотность (Local Reachability Density = LRDk (p) - мера того, насколько близко к нему находятся его соседи), в основном обратное среднему расстоянию между точкой p и ее соседями. Чем ниже плотность, тем дальше p от своих соседей.
- Найдите его локальный коэффициент выброса, LOFk (p), как сумму (расстояния достижимости соседей до P) x сумму (плотности соседей). LOFk (P) - это в основном сумма расстояний между P и соседними точками, взвешенная по сумме плотностей этих точек (насколько далеко они находятся от своих k соседних точек).
Дополнительная информация
** Для шага 2: если 2 точки имеют одинаковое расстояние до P, просто выберите одну как следующую ближайшую, а другую как следующую ближайшую.
** Для шага 4 LRD = Local Reachability Density = inverse (среднее расстояние достижимости между P и его соседями) ‹= 1. Слово« достижимость »используется, потому что если сосед ближе к P, чем Kth сосед, тогда расстояние до K-го соседа используется вместо этого как средство сглаживания
** Для шага 4 каждое расстояние достижимости k соседей точки P равно distancedistk (n1 ‹-p) = max (distk (n1), dist (n1, p))
< br /> ** Для шага 4 общие расстояния до соседних точек делятся на количество соседних точек (или || Nk (P) ||), вычисленное с использованием результатов шага 3.
Сценарии, влияющие на значения LOF:
Более высокие значения LOF указывают на больший уровень аномалии и что
LOFk (p) =
sum (расстояния достижимости его соседей до P) x sum (плотности соседей)
LOF для точки P будет иметь:
- Высокое значение, если → P находится далеко от своих соседей, а его соседи имеют высокую плотность (близки к своим соседям) (LOF = (сумма больших расстояний) x (сумма высокой плотности) = высокое значение)
- Менее высокое значение, если - ›P находится далеко от своих соседей, но его соседи имеют низкую плотность (LOF = (высокая сумма) x (низкая сумма) = среднее значение)
- Менее высокое значение, если - ›P находится близко к своим соседям, а его соседи имеют низкую плотность (LOF = (низкая сумма) x (низкая сумма) = низкое значение)
Регулировка K:
- Если слишком сильно увеличить K, вы просто ищете выбросы по всему набору данных, поэтому точки, далекие от регионов с самой высокой плотностью, могут быть ошибочно классифицированы как выбросы, даже если они сами находятся в группе точек.
- Если слишком сильно уменьшить K, вы будете искать выбросы в очень маленьких локальных областях точек. Это также может привести к ошибочной классификации как выбросы.
Наблюдение за результатами LOF с переменным K:
Приведенный ниже код отображает оценки LOF в виде красных кружков вокруг точек для каждого из K = 5, 30 и 70. Чем больше LOF, тем больше радиус круга и тем более аномальным является наблюдение.
def LOF_plot(k):
import seaborn as sns
from sklearn.neighbors import LocalOutlierFactor
var1,var2=1,2
clf = LocalOutlierFactor(n_neighbors=k, contamination=.1)
y_pred = clf.fit_predict(df)
LOF_Scores = clf.negative_outlier_factor_
plt.title(“Local Outlier Factor (LOF), K={}”.format(k))
plt.scatter(df.iloc[:, var1], df.iloc[:, var2], color=’k’, s=3., label=’Data points’)
radius = (LOF_Scores.max() — LOF_Scores) / (LOF_Scores.max() — LOF_Scores.min())
plt.scatter(df.iloc[:, var1], df.iloc[:, var2], s=1000 * radius, edgecolors=’r’,
facecolors=’none’, label=’Outlier scores’)
plt.axis(‘tight’)
plt.ylabel(“{}”.format(df.columns[var1]))
plt.xlabel(“{}”.format(df.columns[var2]))
legend = plt.legend(loc=’upper left’)
legend.legendHandles[0]._sizes = [10]
legend.legendHandles[1]._sizes = [20]
plt.show();
LOF_plot(5)
LOF_plot(30)
LOF_plot(70)



Из вышесказанного обратите внимание, как слишком маленькое значение K приводит к тому, что слишком много точек имеют высокие значения LOF (радиус круга не колеблется так сильно, как можно было бы подумать). Слишком высокое значение K приводит к тому, что точки в четырех внешних кластерах имеют высокие LOF из-за того, что они находятся слишком далеко от основного кластера точек.
K = 30 предлагает баланс двух крайностей. Это значение выбирается при реализации метода ниже:
Реализация локального выброса в Sklearn:
from sklearn.neighbors import LocalOutlierFactor clf = LocalOutlierFactor(n_neighbors=30, contamination=.1) y_pred = clf.fit_predict(df) LOF_Scores = clf.negative_outlier_factor_ LOF_pred=pd.Series(y_pred).replace([-1,1],[1,0]) LOF_anomalies=df[LOF_pred==1]
Наблюдения, предсказанные как аномалии, имеют значение -1 в clf.fit_predict (). Эти наблюдения имеют оценки LOF меньше порогового значения (clf.negative_outlier_factor_ ‹clf.threshold_). Sklearn выводит отрицательные значения LOF.
cmap=np.array([‘white’,’red’]) plt.scatter(num.iloc[:,1],num.iloc[:,2],c=’white’,s=20,edgecolor=’k’) plt.scatter(LOF_anomalies.iloc[:,1],LOF_anomalies.iloc[:,2],c=’red’) #,marker=’x’,s=100) plt.title(‘Local Outlier Factor — Anomalies’) plt.xlabel(‘Income’) plt.ylabel(‘Spend_Score’)

Дополнительная информация о LOF:
Учебники
1 . Практическое машинное обучение с помощью scikit-learn и Scientific Python Toolkits (выпущено 24.07.2020)
2. Анализ выбросов 2-е изд. Издание 2017 г.
3 . Принципы и алгоритмы обнаружения аномалий, издание 2017 г.
4. Обнаружение выбросов: методы и приложения 1-е изд. Издание 2019 г.
Веб-ссылки
- Http://www.cse.ust.hk/~leichen/courses/comp5331/lectures/LOF_Example.pdf
- Https://towardsdatascience.com/local-outlier-factor-for-anomaly-detection-cc0c770d2ebe
- Https://medium.com/@mtngt/local-outlier-factor-example-by-hand-b57cedb10bd1
- Https://medium.com/@mtngt/local-outlier-factor-simple-python-example-8925dad97fe6
- Https://scikit-learn.org/stable/auto_examples/neighbors/plot_lof_outlier_detection.html#sphx-glr-auto-examples-neighbors-plot-lof-outlier-detection-py
Эллиптический конверт
Метод Elliptic Envelope соответствует многомерному гауссовскому распределению для набора данных. Используйте гиперпараметр загрязнение, чтобы указать процент наблюдений, которые алгоритм будет назначать как выбросы.
Реализация эллиптического конверта в Sklearn:
from sklearn.covariance import EllipticEnvelope clf = EllipticEnvelope(contamination=.1,random_state=0) clf.fit(df) ee_scores = pd.Series(clf.decision_function(df)) ee_predict = clf.predict(df)
ee_scores содержит подобранные значения плотности.
ee_predict содержит метки, где -1 указывает выброс, а 1 - нет. Ярлыки рассчитываются на основе clf.threshold_ и ee_scores.
cmap=np.array(['white','red'])
plt.scatter(num.iloc[:,1],num.iloc[:,2],c='white',s=20,edgecolor='k')
plt.scatter(ee_anomalies.iloc[:,1],ee_anomalies.iloc[:,2],c='red')#,marker='x',s=100)
plt.title('Elliptic Envelope - Anomalies')
plt.xlabel('Income')
plt.ylabel('Spend_Score')

Дополнительная информация об эллиптическом конверте:
Учебники
1. Практическое машинное обучение с инструментами scikit-learn и Scientific Python (выпущено 24.07.2020)
Веб-ссылки
- Http://sdsawtelle.github.io/blog/output/week9-anomaly-andrew-ng-machine-learning-with-python.htm
- Https://chrisalbon.com/machine_learning/preprocessing_structured_data/detecting_outliers/
- Https://scikit-learn.org/stable/modules/generated/sklearn.covariance.EllipticEnvelope.html
Одноуровневые машины опорных векторов
Я не полностью изучил этот метод, но вот базовая реализация. Гиперпараметр nu похож на гиперпараметр загрязнения в других методах. Он устанавливает% наблюдений, которые алгоритм будет идентифицировать как выбросы.
Реализация одноклассной SVM в Sklearn:
from sklearn import svm clf=svm.OneClassSVM(nu=.2,kernel=’rbf’,gamma=.001) clf.fit(df) y_pred=clf.predict(df)
Ниже я привожу наблюдения, идентифицированные как аномалии:
num.plot.scatter(x=’Income’,y=’Spend_Score’, c=y_pred, cmap=cmap, colorbar = False) plt.title(‘One-Class SVM — Anomalies’);

Дополнительная информация о одноклассной SVM:
Учебники
I. Начало обнаружения аномалий с использованием глубокого обучения на основе Python: с Keras и PyTorch 1-е изд. 2019
2. Анализ выбросов 2-е изд. Издание 2017 г.
Веб-ссылки
1. http://rvlasveld.github.io/blog/2013/07/12/introduction-to-one-class-support-vector-machines/
2. https: // scikit-learn .org / стабильный / модули / сгенерированный / sklearn.svm.OneClassSVM.html
Использование кластеризации K-средних для обнаружения аномалий:
Http://amid.fish/anomaly-detection-with-k-means-clustering
https://towardsdatascience.com/time-series-of-price-anomaly-detection-13586cd5ff46
Ссылки на учебники - это партнерские ссылки, по которым я могу заработать небольшую комиссию.
Не стесняйтесь оставлять комментарии.