K-Means 异常检测不聚类异常

数据挖掘 Python scikit-学习 k-均值 异常检测
2022-03-01 15:30:08

K-means 异常检测散点图

下面的代码从数据集中获取单个列,然后将 50 个异常添加到数据集中,这些异常比数据集的最大值要大得多。

import pandas as pd
import numpy as np
import pandas as pd
from sklearn.cluster import KMeans
import matplotlib.pyplot as plt
import seaborn as sns

X=pd.read_csv('C:/Files/dataset.csv', sep=';', encoding='latin1' )

#Adding the anomalies

for i in range(0, 50):
    X.append(X.my_column.max() * (10 + pd.np.abs(pd.np.random.normal())))
X = pd.np.array(X)

clf = KMeans(n_clusters=2, init='k-means++', max_iter=300, n_init=10, random_state=1)
clf.fit(X.my_column.values.reshape(-1, 1))
X_prd = clf.predict(X.my_column.values.reshape(-1, 1))

plt.scatter(X.index, X.my_column, c=X_prd)

在此处输入图像描述

下图显示了结果,我期望异常值集群与正常数据相比更清晰。

为什么这样 ?

因为为了创建异常,我取了my_column的最大值,即 9689。

我被困在这里,我不知道从哪里开始,所以我会很感激一些帮助。

目标是 K 意味着检测这些添加的异常。

3个回答

通过在循环中将最大值乘以 10,您将重复乘以,因此最后一点是(hrm,情节实际上并没有那么远?)。因此,最后添加的点与其他点相距甚远,在该集群中包含任何其他点变得过于昂贵。(这样做会将集群的平均值拖得很远,然后成本函数会爆炸;请参阅sklearn 手册。)101053

我认为试图在一个集群中捕获所有异常是没有意义的。异常是异常,因为它们不应该属于任何集群。

在您的情况下,最好将异常值聚类n_clusters=1并将其解释为异常。此外,k-means 可能不是您数据的最佳算法,因为到质心的距离仍会捕获异常值。可能,最好使用 DBSCAN 或其他东西,可能会更改距离度量,甚至编写自己的距离函数。

您的示例表明K均值(以及一般的聚类)不是检测异常的合适工具。

根据定义,异常是偏离正态的点(观察值),然而,正态性是被定义的。另一方面,集群是具有一些相似性的点的集合。

在您的情况下,您使用与集群质心的距离作为(不)相似性度量。但是,在与假设质心的距离相似的意义上,您人为创建的“异常”并不“相似”。

编辑:

如果您没有关于“正常”数据和异常的领域知识,通常从假设的高斯分布开始。但是,在你的情况下,这将无济于事,因为你的异常都在同一个方向上,并且在大小方面非常不同。

相反,您可以尝试计算中位数,因为它对异常值不敏感,并将其用作“正常”数据的中心。然后计算它与所有其他点之间的距离,并将超出某个阈值的点声明为异常值。

中位数的概念可以推广到多维数据