通过组合两个向量检测异常值

数据挖掘 数据挖掘 特征提取 特征工程 异常检测 离群值
2022-03-04 23:48:50

我想以一种方式组合以下向量,即只有红点(数字 7)与其他点不一致(成为异常值并远离其他点)并且其他点彼此一致。请注意,我已经测试了两个向量之间的马氏距离和 Kullback-Leibler 散度,但它们并不是那么好并且可以检测到。

a=[1.3269 1.3354 1.3318 1.3282 1.34666 1.3460 1.36084 1.3526 1.3539 1.3510 1.3480 1.3479 1.34893]

b=[0.0352,0.0992,0.1570,0.1431,0.1634,0.1629,0.1046,0.1655,0.1635,0.1642,0.1658,0.1666,0.15735]

在此处输入图像描述 在此处输入图像描述

提前致谢。

3个回答

从第二张图中,识别异常值似乎很容易。您可能只适合一个简单的多项式(或其他一些函数),然后标记与拟合曲线的距离大于 2 个标准差(或任何看起来合适的)的所有点。

在此处输入图像描述

import numpy as np
import matplotlib.pyplot as plt

b=np.array([0.0352,0.0992,0.1570,0.1431,0.1634,0.1629,0.1046
            ,0.1655,0.1635,0.1642,0.1658,0.1666,0.15735])
x = np.arange(13)
p = np.poly1d(np.polyfit(x,b,4))
y = p(x)

plt.plot(x,b,'ro')
plt.plot(x,y,'b-')
plt.show()

我真的不同意“想要”一个点成为异常值然后按摩算法使其成为异常值的想法。您有 2 个维度,它要么是异常值,要么不是。

如果将数据标准化,然后破译马氏距离,则点 6 只是位于某个阈值之外的两个点之一(点 0 是另一个点)。除此之外,由于您对特定现象有一些确定性的知识,除了某种非线性变换之外,您无能为力。

无论如何......这是两个异常值版本,以防您没有首先标准化您的数据:

from pandas import DataFrame, read_csv
dfR = read_csv('~/Machine_Learning/ipython_notebooks/AB_outlier.csv')
df=(dfR-dfR.mean())/dfR.std()

import numpy as np
import matplotlib.pyplot as plt
from sklearn.covariance import EmpiricalCovariance, MinCovDet
emp_cov = EmpiricalCovariance().fit(df)

fig = plt.figure()
plt.subplots_adjust(hspace=-.1, wspace=.4, top=.95, bottom=.05)

# Show data set
subfig1 = plt.subplot(3, 1, 1)
my_plot = subfig1.scatter(df.A,df.B)
subfig1.set_xlim(subfig1.get_xlim()[0], 11.)
subfig1.set_title("Mahalanobis distances")

# Show contours of the distance functions
xx, yy = np.meshgrid(np.linspace(plt.xlim()[0], plt.xlim()[1], 100),
                 np.linspace(plt.ylim()[0], plt.ylim()[1], 100))
zz = np.c_[xx.ravel(), yy.ravel()]

mahal_emp_cov = emp_cov.mahalanobis(zz)
mahal_emp_cov = mahal_emp_cov.reshape(xx.shape)
emp_cov_contour = subfig1.contour(xx, yy, np.sqrt(mahal_emp_cov),
                              cmap=plt.cm.PuBu_r,
                              linestyles='dashed')

subfig1.legend([emp_cov_contour.collections[1],
            my_plot],
           ['MLE dist'],
           loc="upper right", borderaxespad=0)
plt.xticks(())
plt.yticks(())

带有马氏距离线的标准化数据图

希望这可以帮助!

自动编码器解决方案

你可以试试自动编码器。自动编码器将采用输入向量,并尝试将其重新创建为输出。所以你接受你的输入,并使用你选择的度量来测量输入和预测输出变量之间的距离(欧几里得应该可以工作,但可以尝试各种)。更大的距离可以被认为是更不正常的。因此,您可以将您的观察结果从最奇怪到最正常进行排序。

不过,请确保您仅在正常数据上训练自动编码器。这当然会假设您有超过 13 个您正在查看的样本。如果不是,这可能不会很好地工作,只是因为样本太小。

KDE 解决方案

这个想法是使用核密度估计来生成数据集的非参数联合密度。然后你会发现找到一个极端值的概率是多少。下面是一些使用 python 的 sklearn 包的代码:

from sklearn.neighbors.kde import KernelDensity
import numpy as np
X=np.matrix([[1.3269, 1.3354, 1.3318, 1.3282, 1.34666, 1.3460, 1.36084, 1.3526, 1.3539, 1.3510, 1.3480, 1.3479, 1.34893],[0.0352, 0.0992, 0.1570, 0.1431, 0.1634, 0.1629, 0.1046, 0.1655, 0.1635, 0.1642, 0.1658, 0.1666, 0.15735]])
kde = KernelDensity(kernel='gaussian', bandwidth=.45).fit(X.T)
score=kde.score_samples(X.T)
prob=np.exp(score)
print(prob/prob[6])

这段代码表明,在最低概率密度区域的观测值是观测值 1,2 和 7。当然,这对于更大的样本会更好,并且您需要对带宽大惊小怪来校准它,但应该这样做。