异常检测(4)—基于相似度的方法

1.基于距离的度量方法

基于距离的度量方法是基于最近邻距离来定义异常值。
基于距离的异常检测有这样一个前提假设:异常点的 k k k近邻距离要远大于正常点的近邻距离。解决问题的最简单方法是使用嵌套循环。 第一层循环遍历每个数据,第二层循环进行异常判断,需要计算当前点与其他点的距离,一旦已识别出多于 k k k个数据点与当前点的距离在 D D D之内,则将该点自动标记为非异常值。这样计算的时间复杂度为 O ( N 2 ) O\left(N^{2}\right) O(N2),当数据量比较大时,这样计算是及不划算的。 因此,需要修剪方法以加快距离计算。
基于距离的检测适用于各个集群的密度较为均匀的情况。

2.基于密度的度量

基于密度的算法主要有:局部离群因子(LOF),此算法以相对于其邻居的局部密度偏差来进行度量。它将相邻点之间的距离进一步转化为“邻域”,从而得到邻域中点的数量(即密度),认为密度远低于其邻居的样本为异常值。

下图中,离群点B容易被检出,而若要检测出较为接近集群的离群点A,则可能会将一些集群边缘的点当作离群点丢弃。而LOF等基于密度的算法则可以较好地适应密度不同的集群情况。
在这里插入图片描述
基于密度的度量值计算步骤:

  1. k-距离,就是以对象o为中心,对数据集D中的所有点到o的距离进行排序,距离对象o第k近的点p与o之间的距离就是k-距离。
    对于数据集D中的某一个对象o,与其距离最近的k个相邻点的最远距离表示为k-distance§,定义
    为给定点p和数据集D中对象o之间的距离d(p,o),满足:满足:
  • 在集合D中至少有k个点 o’,其中 o ′ ∈ D { p } o^{\prime} \in D\{p\} oD{p},满足 d ( p , o ′ ) ≤ d ( p , o ) d\left(p, o^{\prime}\right) \leq d(p, o) d(p,o)d(p,o)
  • 在集合D中最多有k-1个点o’,其中 o ′ ∈ D { p } o^{\prime} \in D\{p\} oD{p},满足 d ( p , o ′ ) ≤ d ( p , o ) d\left(p, o^{\prime}\right) \leq d(p, o) d(p,o)d(p,o)
    在这里插入图片描述
  1. k-领域,由k-距离,我们扩展到一个点的集合——到对象o的距离小于等于k-距离的所有点的集合。
    在二维平面上展示出来的话,对象o的k-邻域实际上就是以对象o为圆心、k-距离为半径围成的圆形区域。
  2. 可达距离
    有了邻域的概念,我们可以按照到对象o的距离远近,将数据集D内的点按照到o的距离分为两类:
  • 若在对象o的k-邻域内,则可达距离就是给定点p关于对象o的k-距离;
  • 若在对象o的k-邻域外,则可达距离就是给定点p关于对象o的实际距离。
    给定点p关于对象o的可达距离用数学公式可以表示为:reach − - dist k ( p , o ) = max ⁡ { k − distance ⁡ ( o ) , d ( p , o ) } _{k}(p, o)=\max \{k-\operatorname{distance}(o), d(p, o)\} k(p,o)=max{kdistance(o),d(p,o)}
    [可达距离=max{k-距离, d(p, o)}]
    这样的分类处理可以简化后续的计算,同时让得到的数值区分度更高。
  1. 局部可达密度
    “密度”可以直观地理解为点的聚集程度,点与点之间距离越短,则密度越大。
    给定点p的局部可达密度计算公式为 lrd ⁡ Min ⁡ P t s ( p ) = 1 / ( ∑ o ∈ N Min ⁡ P t s ( p ) reach ⁡ − dist ⁡ Min ⁡ P t s ( p , o ) ∣ N Min ⁡ P t s ( p ) ∣ ) \operatorname{lrd}_{\operatorname{Min} P t s}(p)=1 /\left(\frac{\sum_{o \in N_{\operatorname{Min} P t s}(p)} \operatorname{reach}-\operatorname{dist}_{\operatorname{Min} P t s}(p, o)}{\left|N_{\operatorname{Min} P t s}(p)\right|}\right) lrdMinPts(p)=1/(NMinPts(p)oNMinPts(p)reachdistMinPts(p,o))
    在这里,我们使用数据集D中给定点p与对象o的k-邻域内所有点的可达距离平均值的倒数(注意,不是导数)来定义局部可达密度。
  2. 局部异常因子
    点p的邻域 N k ( p ) N_{k}(p) Nk(p)内其他点的局部可达密度与点p的局部可达密度之比的平均数, L O F Min ⁡ P t s ( p ) = ∑ o ∈ N Min ⁡ P t s ( p ) lrd ⁡ Min ⁡ P t s ( o ) lrd ⁡ Min ⁡ P t s ( p ) ∣ N Min ⁡ P t s ( p ) ∣ L O F_{\operatorname{Min} P t s}(p)=\frac{\sum_{o \in N_{\operatorname{Min} P t s}(p)} \frac{\operatorname{lrd}_{\operatorname{Min} P t s}(\mathrm{o})}{\operatorname{lrd}_{\operatorname{Min} P t s}(p)}}{\left|N_{\operatorname{Min} P t s}(p)\right|} LOFMinPts(p)=NMinPts(p)oNMinPts(p)lrdMinPts(p)lrdMinPts(o)如果这个比值越接近1,说明o的邻域点密度差不多,o可能和邻域同属一簇;如果这个比值小于1,说明o的密度高于其邻域点密度,o为密集点;如果这个比值大于1,说明o的密度小于其邻域点密度,o可能是异常点。

最终得出的LOF数值,就是我们所需要的离群点分数。在sklearn中有LocalOutlierFactor库,可以直接调用。

LocalOutlierFactor库:可以用于对单个数据集进行无监督的离群检测,也可以基于已有的正常数据集对新数据集进行新颖性检测。在这里我们进行单个数据集的无监督离群检测。

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from sklearn.neighbors import LocalOutlierFactor
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus']=False
pd.set_option('display.max_columns', None)
pd.set_option('display.max_rows', None)
np.random.seed(61)
# 构造两个数据点集群
X_inliers1 = 0.2 * np.random.randn(100, 2)
X_inliers2 = 0.5 * np.random.randn(100, 2)
X_inliers = np.r_[X_inliers1 + 2, X_inliers2 - 2]
# 构造一些离群的点
X_outliers = np.random.uniform(low=-4, high=4, size=(20, 2))
# 拼成训练集
X = np.r_[X_inliers, X_outliers]
n_outliers = len(X_outliers)
ground_truth = np.ones(len(X), dtype=int)
# 打标签,群内点构造离群值为1,离群点构造离群值为-1
ground_truth[-n_outliers:] = -1
plt.title('构造数据集 (LOF)')
plt.scatter(X[:-n_outliers, 0], X[:-n_outliers, 1], color='b', s=5, label='集群
点')
plt.scatter(X[-n_outliers:, 0], X[-n_outliers:, 1], color='orange', s=5,
label='离群点')
plt.axis('tight')
plt.xlim((-5, 5))
plt.ylim((-5, 5))
legend = plt.legend(loc='upper left')
legend.legendHandles[0]._sizes = [10]
legend.legendHandles[1]._sizes = [20]
plt.show()

在这里插入图片描述

# 训练模型(找出每个数据的实际离群值)
clf = LocalOutlierFactor(n_neighbors=20, contamination=0.1)
# 对单个数据集进行无监督检测时,以1和-1分别表示非离群点与离群点
y_pred = clf.fit_predict(X)
# 找出构造离群值与实际离群值不同的点
n_errors = y_pred != ground_truth
X_pred = np.c_[X,n_errors]
X_scores = clf.negative_outlier_factor_
# 实际离群值有正有负,转化为正数并保留其差异性(不是直接取绝对值)
X_scores_nor = (X_scores.max() - X_scores) / (X_scores.max() - X_scores.min())
X_pred = np.c_[X_pred,X_scores_nor]
X_pred = pd.DataFrame(X_pred,columns=['x','y','pred','scores'])
X_pred_same = X_pred[X_pred['pred'] == False]
X_pred_different = X_pred[X_pred['pred'] == True]
# 直观地看一看数据
X_pred
plt.title('局部离群因子检测 (LOF)')
plt.scatter(X[:-n_outliers, 0], X[:-n_outliers, 1], color='b', s=5, label='集群
点')
plt.scatter(X[-n_outliers:, 0], X[-n_outliers:, 1], color='orange', s=5,
label='离群点')
# 以标准化之后的局部离群值为半径画圆,以圆的大小直观表示出每个数据点的离群程度
plt.scatter(X_pred_same.values[:,0], X_pred_same.values[:, 1],
s=1000 * X_pred_same.values[:, 3], edgecolors='c',
facecolors='none', label='标签一致')
plt.scatter(X_pred_different.values[:, 0], X_pred_different.values[:, 1],s=1000 * X_pred_different.values[:, 3], edgecolors='violet',facecolors='none', label='标签不同')
plt.axis('tight')
plt.xlim((-5, 5))
plt.ylim((-5, 5))
legend = plt.legend(loc='upper left')
legend.legendHandles[0]._sizes = [10]
legend.legendHandles[1]._sizes = [20]
plt.show()

在这里插入图片描述

  • 1
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论
基于密度的时序数据异常检测方法是一种常用的异常检测方法,其优缺点如下: 优点: 1. 适用性广:基于密度的方法适用于各种类型的数据,包括连续和离散的数据,可以用于时间序列、图像、文本等各种数据类型。 2. 精度高:基于密度的方法能够准确地检测出数据中的异常点,能够发现各种类型的异常。 3. 无需标签数据:基于密度的方法通常不需要标签数据,即可以进行无监督学习,从而节省了人力成本。 4. 可解释性强:基于密度的方法可以通过计算数据点的密度来判断其是否为异常点,因此可以直观地解释检测结果。 缺点: 1. 计算复杂度高:基于密度的方法需要计算每个数据点与其他数据点之间的距离相似度,因此对于大规模数据集,计算复杂度较高。 2. 敏感性差:基于密度的方法对于噪声点和局部异常点比较敏感,对于全局异常点的检测效果较差。 3. 数据分布要求高:基于密度的方法对数据的分布有一定的要求,如果数据分布较为稀疏或不均匀,可能会出现误判。 4. 参数选择困难:基于密度的方法需要选择合适的密度估计方法和参数,这对于非专业人员来说可能比较困难。 综上所述,基于密度的时序数据异常检测方法在实际应用中需要根据具体情况进行选择和调整,以充分发挥其优势,提高检测精度和鲁棒性。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Mrs.King_UP

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值