异常检测Task04
本次学习参照Datawhale开源学习地址:https://github.com/datawhalechina/team-learning-data-mining/tree/master/AnomalyDetection
本次学习分为五个章节:
一、概述
二、基于统计学的方法
三、线性模型
四、基于邻近度的方法
五、集成方法
本章主要内容包括:
- 基于距离的度量(kNN,k-means等)
- 基于密度的度量(LOF,DBSCAN等)
概述
“异常值”通常指具有特定业务意义的一类特殊值。噪声和异常之间、正常数据和噪声之间的边界都是模糊的。噪声可以视作特性较弱的异常值,而异常值通常具有更高的离群程度分数值,同时也更具有可解释性。
在异常检测中,我们弱化了“噪声”和“正常数据”之间的区别,专注于那些具有价值特性的异常值。基于邻近度的方法适用于数据点的聚集程度高、离群点较少的情况。它是一种相似度算法,需要对每一个数据分别进行相应计算,所以这类算法通常计算量较大。
基于相邻近度的方法大致可以分为两类:
- 基于距离的度量,如kNN(k近邻)分类算法,k-means(k均值)聚类算法等
- 基于密度的度量,如LOF(局部离群因子)算法,DBSCAN聚类算法等
1、基于距离的度量
基于距离的方法是以最近邻距离来定义异常值。 基于距离的异常检测假设异常点的 k k k 近邻距离要远大于正常点(kNN)或异常点离各分类簇中心距离远大于正常点(k-means)。
1.1 kNN
1.1.1 算法原理
KNN算法是一种分类算法。该算法的思想是: 一个样本与数据集中的
k
k
k个样本最相似, 如果这
k
k
k个样本中的大多数属于某一个类别, 则该样本也属于这个类别。该方法在确定分类决策上只依据最邻近的一个或者几个样本的类别来决定待分样本所属的类别。
在KNN中,通过计算对象间
L
p
Lp
Lp距离来作为各个对象之间的非相似性指标:
当p=1时,就是曼哈顿距离(L1范数)
当p=2时,就是欧氏距离(L2范数)
当p→∞时,就是切比雪夫距离
1.1.2 算法流程
- 1)计算当前点与训练数据集中所有点的距离
- 2)数据集中点按距离递增次序排序
- 3)选取数据集中与当前点距离最小的k个点
- 4)统计前k个点所在的类别出现的频率
- 5)返回前k个点出现频率最高的类别作为当前点的预测分类
1.1.3 用于异常检测
- 1)计算当前点与训练数据集中所有点的距离
- 2)数据集中点按距离递增次序排序
- 3)选取数据集中与当前点距离最小的k个点
- 4)计算与最近k个近邻点的平均距离
- 5)重复步骤1)-4)得到每个点与k个近邻点的平均距离分布
- 6)根据3sigma或箱线图确定平均距离阈值,超过阈值的点为异常点
代码实现
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from sklearn.preprocessing import scale
"""生成测试数据"""
X = np.array([[1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0],
[2.0, 4.0, 6.0, 8.0, 10.0, 12.0, 14.0, 5.0, 18.0, 20.0]])
X = pd.DataFrame(X.T,columns = ['x1','x2'])
plt.scatter(X['x1'],X['x2'])
plt.show()
"""K近邻算法异常检测函数"""
def knn_outliner_detector(data, K):
std_data = scale(data) # 数据标准化
std_data = pd.DataFrame(std_data)
distance = [] # 存储距离
for i in range(std_data.shape[0]):
diff_i = np.array(std_data.loc[std_data.index != i, :]) \
- np.array(std_data.loc[std_data.index == i, :])
dist_i = np.sum(np.square(diff_i), axis=1) # 第i个数据样本点与其他样本点的距离
avg_dist_i = np.mean(np.sort(dist_i)[:K]) # 寻找最近的K个相邻点,计算平均距离
distance.append(avg_dist_i)
# 根据箱线图判断异常点阈值
Q1 = pd.Series(distance).quantile(0.25)
Q3 = pd.Series(distance).quantile(0.75)
threshold = Q3 + 3 * (Q3 - Q1)
label = pd.Series(distance) > threshold
data = pd.concat([data, pd.Series(distance, name='Distance'), pd.Series(label, name='Label')], axis=1)
# 返回数据结果
return data
"""异常检测结果"""
result = knn_outliner_detector(X, K=2)
error = result[result['Label']==True]
print("异常数据为:{}".format(np.array(error[['x1','x2']])))
"""可视化"""
plt.scatter(error['x1'],error['x2'])
plt.show()
异常数据为:[[8. 5.]]
1.2 k-means
1.2.1 算法原理
k-means是一种无监督的基于距离的聚类算法。该算法的思想是:先从样本集中随机选取 k 个样本作为簇中心,并计算所有样本与这 k 个“簇中心”的距离,对于每一个样本,将其划分到与其距离最近的“簇中心”所在的簇中。
1.2.2 算法流程
-
1)从数据中随机挑选k个样本点作为原始的簇中心。
-
2)计算剩余样本与簇中心的距离,并把各样本标记为离k个簇中心最近的类别。
-
3)重新计算各簇中样本点的均值,并以均值作为新的k个簇中心。
-
4)不断重复(2)和(3),直到簇中心的变化趋于稳定,形成最终的k个簇
1.2.3 用于异常检测
- 1)由上一小节得到k个簇和训练数据集中每一个点与其对应簇中心的距离分布
- 2)根据3sigma或箱线图确定各簇中点的距离阈值
- 3)新数据点先判断属于哪一簇,若新数据点距离该簇的距离超过该簇阈值则为异常点
代码实现
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from sklearn.cluster import KMeans
from sklearn.preprocessing import scale
"""生成测试数据"""
np.random.seed(0)
X = np.random.multivariate_normal(mean=[0.5, 0.5], cov=np.array([[0.3, 0], [0, 0.1]]), size=5000)
X = pd.DataFrame(X,columns = ['x1','x2'])
plt.scatter(X['x1'], X['x2'])
plt.show()
"""Kmeans算法异常检测函数"""
def kmeans_outliner_detector(data, K):
kmeans = KMeans(n_clusters=K)
std_data = scale(data) # 数据标准化
cluster_res = []
kmeans.fit(std_data)
labels = kmeans.labels_
centers = kmeans.cluster_centers_
for label in set(labels):
diff = std_data[np.array(labels) == label,] - \
- np.array(centers[label])
dist = np.sum(np.square(diff), axis=1) # 计算簇内样本点与簇中心的距离
UCL = dist.mean() + 3*dist.std() # 3sigma原则计算判断异常的阈值
OutLiner = np.where(dist > UCL, 1, 0)
raw_data = data.loc[np.array(labels) == label,]
new_data = pd.DataFrame({'Label':label,'Distance':dist,'OutLiner_lalbe':OutLiner})
raw_data.index = new_data.index = range(raw_data.shape[0])
cluster_res.append(pd.concat([raw_data,new_data], axis = 1))
data = pd.concat(cluster_res)
return data
"""异常检测结果"""
result = kmeans_outliner_detector(X, K=2)
error = result[result['OutLiner_lalbe']==True]
print("异常数据为:{}".format(np.array(error[['x1','x2']])))
"""可视化"""
plt.scatter(error['x1'],error['x2'])
plt.show()
异常数据为:[[ 1.01652761e+00 -3.66361990e-01]
[ 9.72463293e-01 -3.39780493e-01]
[ 1.09055298e+00 -3.09285250e-01]
[ 2.85079694e-01 -4.63275013e-01]
[ 1.86777299e+00 -2.10033049e-01]
[ 2.23681441e+00 5.59925047e-01]
[ 2.10433208e+00 5.70473990e-01]
[ 2.31108536e+00 2.24329403e-02]
[ 2.58225506e+00 1.23212124e+00]
[ 2.07824103e+00 3.12204373e-01]
[ 1.01421931e+00 -3.58963254e-01]
[-2.36964934e-01 -5.72739449e-01]
[-7.74881239e-01 -2.73248827e-01]
[ 6.22093257e-01 -4.14695081e-01]
[ 9.94641918e-01 -4.51035149e-01]
[ 1.02483219e+00 -3.27052905e-01]
[ 1.46588314e+00 -1.64293215e-01]
[ 2.05650008e+00 -5.25289694e-02]
[ 1.84356146e+00 -9.24952014e-02]
[ 1.99176264e+00 1.47145114e-01]
[ 6.22807823e-01 -4.28907598e-01]
[ 1.98985203e+00 -1.03232769e-02]
[ 1.33418446e+00 -2.54208354e-01]
[-8.34773507e-02 -4.70568419e-01]
[ 2.11928629e+00 -1.14481066e-03]
[ 2.11621736e+00 -1.08759997e-01]
[ 1.94215484e+00 2.23663264e-01]
[ 2.14648224e+00 5.22497300e-01]
[ 2.30348295e+00 3.41135167e-01]
[ 2.25920131e+00 4.47474173e-01]
[ 1.09609482e+00 -4.42792610e-01]
[ 2.06955466e+00 2.86383416e-01]
[ 2.19519009e+00 5.26459526e-02]
[-6.52771188e-01 -3.07366890e-01]
[ 2.15394115e+00 6.90513293e-01]
[ 1.03182613e+00 -3.61577969e-01]
[ 1.65558340e-01 -4.42278302e-01]
[-7.59958379e-01 -4.54336919e-01]
[ 1.61962766e+00 -1.39829128e-01]
[ 7.29000878e-01 -3.77986550e-01]
[ 8.97731743e-01 -3.68255637e-01]
[-6.12251690e-01 1.15284997e+00]
[-9.56488619e-01 6.91735069e-01]
[-1.02122225e+00 8.64210262e-01]
[-3.66767923e-01 1.20948921e+00]
[-3.71342797e-03 1.33576966e+00]
[-1.14021701e+00 7.78576917e-01]
[-8.35108985e-01 8.52570103e-01]
[-1.20717266e+00 7.03793627e-01]
[ 5.24709410e-01 1.58388286e+00]
[-1.14672717e+00 4.85084843e-01]
[-1.54853749e+00 8.07872015e-01]
[-6.48331826e-01 1.01283542e+00]
[-1.30212661e-01 1.30778783e+00]
[-3.50438157e-01 1.16728913e+00]
[-2.55220113e-01 1.42504514e+00]
[-3.97008676e-01 1.33313456e+00]
[-8.57767383e-02 1.33214524e+00]
[ 5.14842721e-01 1.44235121e+00]
[-7.97447085e-01 9.18114505e-01]
[ 1.26252116e+00 1.39358709e+00]
[-9.30583170e-01 1.06300159e+00]
[ 9.84088007e-02 1.32226894e+00]
[-1.01021560e+00 7.39111147e-01]
[ 5.82846095e-01 1.43128581e+00]
[ 7.63276107e-01 1.44967097e+00]
[-1.21229107e+00 5.86798833e-01]
[-3.00644540e-01 1.22951569e+00]
[-4.47224544e-01 1.23721453e+00]
[-1.10336671e+00 7.08944307e-01]
[-6.50505184e-01 1.26075403e+00]
[-6.63740928e-01 1.02884991e+00]
[-5.41636091e-01 1.15118108e+00]
[-1.48338913e-01 1.23494664e+00]
[-1.10162464e+00 1.03206278e+00]
[-9.39496738e-01 1.00177138e+00]
[-6.85095235e-01 9.98639708e-01]
[-1.10044466e-02 1.40605691e+00]]
2、基于密度的度量
基于距离的检测适用于各个集群的密度较为均匀的情况。在下图中,离群点B容易被检出,而若要检测出较为接近集群的离群点A,则可能会将一些集群边缘的点当作离群点丢弃。而LOF等基于密度的算法则可以较好地适应密度不同的集群情况。
2.1 DBSCAN
2.1.1 算法原理
DBSCAN是一种基于密度的聚类算法,这类密度聚类算法一般假定类别可以通过样本分布的紧密程度决定。同一类别的样本,他们之间的紧密相连的。
2.1.2 算法流程
输入:样本集D=(x1,x2,…,xm),邻域参数(ϵ,MinPts), 样本距离度量方式
- 1)初始化核心对象集合Ω=∅, 初始化聚类簇数k=0,初始化未访问样本集合Γ = D, 簇划分C = ∅
- 2)对于j=1,2,…m, 按下面的步骤找出所有的核心对象:
a) 通过距离度量方式,找到样本xj的ϵ-邻域子样本集Nϵ(xj)
b) 如果子样本集样本个数满足|Nϵ(xj)|≥MinPts, 将样本xj加入核心对象样本集合:Ω=Ω∪{xj} - 3)如果核心对象集合Ω=∅,则算法结束,否则转入步骤4.
- 4)在核心对象集合Ω中,随机选择一个核心对象o,初始化当前簇核心对象队列Ωcur={o}, 初始化类别序号k=k+1,初始化当前簇样本集合Ck={o}, 更新未访问样本集合Γ=Γ−{o}
- 5)如果当前簇核心对象队列Ωcur=∅,则当前聚类簇Ck生成完毕, 更新簇划分C={C1,C2,…,Ck}, 更新核心对象集合Ω=Ω−Ck, 转入步骤3。否则更新核心对象集合Ω=Ω−Ck。
- 6)在当前簇核心对象队列Ωcur中取出一个核心对象o′,通过邻域距离阈值ϵ找出所有的ϵ-邻域子样本集Nϵ(o′),令Δ=Nϵ(o′)∩Γ, 更新当前簇样本集合Ck=Ck∪Δ, 更新未访问样本集合Γ=Γ−Δ, 更新Ωcur=Ωcur∪(Δ∩Ω)−o′,转入步骤5.
输出结果为: 簇划分C= {C1,C2,…,Ck}
2.1.3 用于异常检测
在DBSCAN聚类技术中,所有数据点都被定义为核心点(Core Points)、边界点(Border Points)或噪声点(Noise Points)。
- 核心点是在距离ℇ内至少具有最小包含点数(minPTs)的数据点;
- 边界点是核心点的距离ℇ内邻近点,但包含的点数小于最小包含点数(minPTs);
- 所有的其他数据点都是噪声点,也被标识为异常值;
异常检测取决于所要求的最小包含点数、距离ℇ和所选择的距离度量,比如欧几里得或曼哈顿距离。
代码实现
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from sklearn.cluster import DBSCAN
from sklearn.preprocessing import scale
"""生成测试数据"""
np.random.seed(0)
X1 = np.random.multivariate_normal(mean=[0.5, 0.5], cov=np.array([[0.3, 0], [0, 0.1]]), size=5000)
X2 = np.random.multivariate_normal(mean=[0, 5], cov=np.array([[0.8, 0], [0, 2]]), size=100)
X = np.concatenate([X1,X2],axis=0)
X = pd.DataFrame(X,columns = ['x1','x2'])
plt.scatter(X['x1'], X['x2'])
plt.show()
"""DBSCAN算法异常检测函数"""
def DBSCAN_outliner_detector(data, S):
model = DBSCAN(eps=0.5, min_samples=S)
std_data = scale(data) # 数据标准化
model.fit(std_data)
labels = model.labels_
core_indices = np.zeros_like(labels, dtype=bool)
core_indices[model.core_sample_indices_] = True
data['label'] = labels
return data
"""异常检测结果"""
result = DBSCAN_outliner_detector(X, S=10)
error = result[result['label']==-1]
print("异常数据为:{}".format(np.array(error[['x1','x2']])))
"""可视化"""
plt.scatter(error['x1'],error['x2'])
plt.show()
异常数据为:[[ 2.58225506e+00 1.23212124e+00]
[-1.54853749e+00 8.07872015e-01]
[-7.45264463e-01 4.71416336e+00]
[ 1.70521653e-01 7.45168098e+00]
[-9.70475969e-01 4.74853813e+00]
[ 1.28034720e+00 6.37498658e+00]
[-5.57455155e-01 4.65341438e+00]
[-1.21509938e+00 4.43997303e+00]
[ 3.08035218e-03 6.87044243e+00]
[ 1.37178652e+00 4.99972173e+00]
[-3.58893326e-01 3.90669660e+00]
[ 9.04762699e-01 4.83686090e+00]
[ 8.20251111e-01 7.14003820e+00]
[ 4.93752559e-01 6.03081047e+00]
[ 1.16350100e+00 3.99146262e+00]
[ 1.85226695e+00 4.21812970e+00]
[-8.02864717e-01 4.48252748e+00]
[ 1.54683897e-01 7.04344877e+00]
[ 9.75703399e-01 5.39978191e+00]
[-6.08823848e-01 4.71525070e+00]
[-3.06040633e-01 6.13600243e+00]
[-6.19173393e-01 4.33179987e+00]
[-5.54169278e-01 4.93399687e+00]
[-1.31376017e-01 6.22969547e+00]
[-1.21914317e+00 5.46399182e+00]
[ 5.90915872e-01 6.14245023e+00]
[ 1.34818822e+00 6.10146030e+00]
[ 5.83103515e-01 5.53680182e+00]
[-4.32669213e-01 5.49780340e+00]
[-1.20722116e-01 4.80803059e+00]
[-7.64131948e-01 6.42176011e+00]
[ 8.79142018e-01 2.46181837e+00]
[-4.18052010e-01 6.13529524e+00]
[-1.00175259e+00 2.99997261e+00]
[ 6.82287405e-02 6.25468557e+00]
[-5.95363223e-01 6.72976531e+00]
[-4.51378036e-01 4.51736604e+00]
[ 1.02178181e+00 5.46325868e+00]
[ 1.60196931e+00 6.05575490e+00]
[ 1.11596066e+00 4.89741704e+00]
[-1.65269885e+00 5.10061136e+00]
[-2.15623025e-01 7.78022347e+00]
[ 4.69983562e-01 4.77683103e+00]
[ 8.36115379e-01 2.29648904e+00]
[ 1.05958018e-01 6.19634861e+00]
[-1.77344412e-01 5.71122846e+00]
[ 8.11548634e-01 6.08263115e+00]
[ 1.22880719e+00 5.27915327e+00]
[-8.84680063e-01 3.60087603e+00]
[-7.67121539e-01 4.87819862e+00]
[-2.21102709e-01 5.90392797e+00]
[ 7.78879825e-01 5.33004855e+00]
[ 1.45547183e+00 5.95297513e+00]
[-7.05113761e-01 6.06305941e+00]
[-1.22858848e+00 3.85700318e+00]
[ 9.19527537e-01 4.42781031e+00]
[-4.32724018e-01 2.85211729e+00]
[ 7.34879679e-01 5.86984487e+00]
[ 5.14519279e-01 5.17912269e+00]
[ 8.00055811e-01 7.97867000e+00]
[-1.24971117e+00 3.88680054e+00]
[ 7.10760539e-01 5.46289986e+00]
[ 6.36183147e-01 4.41165901e+00]
[-1.52451147e+00 4.94267061e+00]
[-9.01213957e-01 5.82555210e+00]
[ 8.46771157e-01 6.02556662e+00]
[ 1.47128733e+00 5.71662852e+00]
[ 2.91591782e-01 5.72564730e+00]
[ 1.44872031e-01 5.73046787e+00]
[ 6.12869541e-01 7.70719539e+00]
[-1.12839429e+00 8.77802006e+00]
[-5.47613842e-01 5.08962652e+00]
[-1.33330032e-01 5.99905080e+00]
[-3.06493700e-01 5.45460023e+00]
[-4.18842613e-01 5.48893019e+00]
[ 4.15954054e-01 5.41279708e+00]
[ 5.00819790e-01 5.17674126e+00]
[-3.61844657e-01 5.95971872e+00]
[ 4.41688269e-01 5.94645430e+00]
[ 9.27413108e-02 6.72666941e+00]
[-5.98900528e-01 5.98650539e+00]
[ 1.74289241e-01 3.17437631e+00]
[-6.03583537e-01 5.27467592e+00]
[ 2.15178665e+00 2.17576822e+00]
[ 3.37465736e-01 5.87692337e+00]
[-1.31080731e+00 7.19557107e+00]
[-1.38838408e-02 5.51547242e+00]
[-3.73703803e-01 6.69502319e+00]
[ 7.34391230e-01 2.60267818e+00]
[-9.47601215e-01 2.49164791e+00]
[ 1.03680627e+00 6.03018835e+00]
[-3.52864418e-01 5.39817729e+00]
[-3.95642917e-01 2.19229092e+00]
[-2.86500838e-01 3.67122177e+00]
[-4.73833506e-01 3.69564736e+00]
[-2.25974077e+00 7.35250996e+00]
[-9.59462186e-01 4.46300792e+00]
[ 1.60771786e-01 3.16281436e+00]
[ 6.88875924e-01 5.37890037e+00]]
2.2 LOF
2.2.1 算法原理
如果样本集的密度不均匀、聚类间距差相差很大时,聚类质量较差,这时用DBSCAN聚类一般不适合,可以采用LOF算法。LOF通过计算一个样本点周围的样本点所处位置的平均密度比上该样本点所在位置的密度,比值越大于1,则该点所在位置的密度越小于其周围样本所在位置的密度,这个点就越有可能是异常点。
2.2.2 算法流程
- 1)计算点p的局部可达密度:
表示点p的第k邻域内点到p的平均可达距离的倒数。
- 2)计算点p的局部离群因子:
表示点p的邻域点 Nk§的局部可达密度与点p的局部可达密度之比的平均数。 - 3)如果局部离群因子接近1,说明点p的其邻域点密度差不多,p可能和邻域同属一簇;如果这个比值小于1,说明点p的密度高于其邻域点密度,p为密集点;如果这个比值大于1,说明点p的密度小于其邻域点密度,p越可能是异常点(一般根据异常点比例选择阈值)。
2.2.3 用于异常检测
代码实现
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from sklearn.neighbors import LocalOutlierFactor
from scipy import stats
"""生成测试数据"""
n_samples = 100 #样本总数
outliers_fraction = 0.25 #异常样本比例
n_inliers = int((1. - outliers_fraction) * n_samples)
n_outliers = int(outliers_fraction * n_samples)
rng = np.random.RandomState(42)
X = 0.3 * rng.randn(n_inliers // 2, 2)
X_train = np.r_[X + 2, X - 2] #正常样本
X_train = np.r_[X_train, np.random.uniform(low=-6, high=6, size=(n_outliers, 2))]
"""训练LOF模型"""
clf = LocalOutlierFactor(n_neighbors=35, contamination=outliers_fraction)
y_pred = clf.fit_predict(X_train)
scores_pred = clf.negative_outlier_factor_
"""根据异常点比例选择阈值"""
threshold = stats.scoreatpercentile(scores_pred, 100 * outliers_fraction) # 根据异常样本比例得到阈值
X = pd.DataFrame(X_train,columns = ['x1','x2'])
X['label'] = y_pred
error = X[X['label']==-1]
print("异常数据为:{}".format(np.array(error[['x1','x2']])))
"""可视化"""
xx, yy = np.meshgrid(np.linspace(-7, 7, 50), np.linspace(-7, 7, 50))
Z = clf._decision_function(np.c_[xx.ravel(), yy.ravel()]) # 类似scores_pred的值,值越小越有可能是异常点
Z = Z.reshape(xx.shape)
plt.title("Local Outlier Factor (LOF)")
plt.contourf(xx, yy, Z, levels=np.linspace(Z.min(), threshold, 7), cmap=plt.cm.Blues_r) # 绘制异常点区域,值从最小的到阈值的那部分
a = plt.contour(xx, yy, Z, levels=[threshold], linewidths=2, colors='red') # 绘制异常点区域和正常点区域的边界
plt.contourf(xx, yy, Z, levels=[threshold, Z.max()], colors='palevioletred') # 绘制正常点区域,值从阈值到最大的那部分
b = plt.scatter(X_train[:-n_outliers, 0], X_train[:-n_outliers, 1], c='white',
s=20, edgecolor='k')
c = plt.scatter(X_train[-n_outliers:, 0], X_train[-n_outliers:, 1], c='black',
s=20, edgecolor='k')
plt.axis('tight')
plt.xlim((-7, 7))
plt.ylim((-7, 7))
plt.legend([a.collections[0], b, c],
['learned decision function', 'true inliers', 'true outliers'],
loc="upper left")
plt.show()
异常数据为:[[-2.18051198e+00 -1.44431654e+00]
[-5.99491716e+00 3.42225123e+00]
[ 3.77966277e-01 -8.92749807e-02]
[ 1.42659166e+00 -5.94945025e+00]
[-1.62161557e+00 5.69498546e+00]
[-3.51353993e+00 -2.06216350e+00]
[-4.63121597e+00 4.80456377e-03]
[-1.19193312e+00 -1.14739914e+00]
[-9.41658428e-01 2.42513575e+00]
[-5.77042171e-01 -2.87303019e+00]
[-8.26000490e-02 5.34826767e+00]
[-3.45993032e-01 -4.33185963e+00]
[ 3.88141794e+00 5.00974647e+00]
[-1.91411794e+00 -5.73516487e+00]
[ 3.66847161e+00 -2.09878585e+00]
[ 5.72878858e-01 3.41565277e+00]
[-2.78420163e-01 -2.49121963e+00]
[ 4.27952094e+00 5.07697507e+00]
[ 2.60330219e+00 -5.85483558e+00]
[-5.48229369e+00 9.32682766e-01]
[ 3.30962689e+00 -4.30277525e+00]
[ 4.83023411e+00 5.00421601e+00]
[ 3.50636726e+00 1.78204038e+00]
[-1.59208102e+00 -4.88825615e+00]
[ 5.26750440e+00 -2.58803773e+00]]
总结
基于邻近度算法本质上是一种基于相似度的算法,它利用异常值和正常值在与其它点距离或密度上的不同来进行异常检测。这种方法理论上不需要各种分布假设(有时确定阈值时会用上),还可以对高维数据进行分析,但运算开销也非常大。
参考资料
[1]《Outlier Analysis》——Charu C. Aggarwal
[2] LOF: Identifying Density-Based Local Outliers
[3] https://blog.csdn.net/sinat_30353259/article/details/80901746
[4] https://www.sohu.com/a/333572966_654419
[5] https://www.cnblogs.com/pinard/p/6208966.html
[6] https://www.cnblogs.com/webRobot/p/11965155.html
[7] https://blog.csdn.net/wangyibo0201/article/details/51705966
[8] https://blog.csdn.net/YE1215172385/article/details/79766906