【Educoder数据挖掘实训】异常值检测-值域法
开挖!
这个题中
l
o
f
lof
lof算法给的很抽象,先用比较通俗的方式说一下:
首要想法是找到不合群的点,也就是异常点。采用的方法是对局部可达密度进行判断。相较于其他普通的简单基于聚类的算法,这个算法有两个优点:
- 可以应对下列问题:
在上图中,显然p
p
p
p
p
p
C
2
C_2
p
p
C
2
C_2
C
1
C_1
p
p
l
o
f
lof
- 在
l
o
f
lof
l
o
f
lof
那么什么是
l
o
f
lof
lof算法呢?先定义几个函数:
d
(
p
,
q
)
d(p,q)
d(p,q)表示点到点的距离;
d
k
(
p
)
d_k(p)
dk(p):第
k
k
k距离,表示所有点到
p
p
p的距离里,从小到大排序的第
k
k
k个;
N
k
(
p
)
N_k(p)
Nk(p):第
k
k
k距离邻域:表示所有点到
p
p
p的距离里,不大于
d
k
(
p
)
d_k(p)
dk(p)的,不难看出
∣
N
k
(
p
)
∣
≥
k
|N_k(p)|ge k
∣Nk(p)∣≥k;
r
e
a
c
h
_
d
i
s
t
k
(
o
,
p
)
=
m
a
x
(
d
k
(
o
)
,
d
(
o
,
p
)
)
reach_dist_k(o,p)=max(d_k(o), d(o,p))
reach_distk(o,p)=max(dk(o),d(o,p)):第
k
k
k可达距离,显然在
o
o
o的第
k
k
k邻域里的点,点
o
o
o到这些点的第
k
k
k可达距离都为第
k
k
k距离。
l
r
d
k
p
)
=
1
/
(
∑
o
∈
N
k
(
p
)
r
e
a
c
h
_
d
i
s
t
k
(
o
,
p
)
∣
N
k
(
p
)
∣
)
lrd_k(p) = 1/(frac{sum_{oin N_k(p)} reach_dist_k(o,p)}{|N_k(p)|})
lrdk(p)=1/(∣Nk(p)∣∑o∈Nk(p)reach_distk(o,p)):点
p
p
p的第
k
k
k局部可达密度;
L
O
F
k
(
p
)
=
∑
o
∈
N
k
(
p
)
l
r
d
k
(
o
)
l
r
d
k
(
p
)
∣
N
k
(
p
)
服务器托管网 ∣
=
∑
o
∈
N
k
(
p
)
l
r
d
k
(
o
)
∣
N
k
(
p
)
∣
/
l
r
d
k
(
p
)
LOF_k(p) = frac{sum_{oin N_k(p)}frac{lrd_k(o)}{lrd_k(p)}}{|N_k(p)|} = frac{sum_{oin N_k(p)}lrd_k(o)}{|N_k(p)|} /lrd_k(p)
LOFk(p)=∣Nk(p)∣∑o∈Nk(p)lrdk(p)lrdk(o)=∣Nk(p)∣∑o∈Nk(p)lrdk(o)/lrdk(p):局部离群因子,即将点
p
p
p的
N
k
(
p
)
N_k(p)
Nk(p)邻域内所有点的平均局部可达密度与点的局部可达密度做比较,通过这个值来反应点
p
p
p是不是异常点。
所以其实我们要做的就是求出所有点的
L
O
F
k
(
p
)
LOF_k(p)
LOFk(p)。
显然有一种做法是
n
3
n^3
n3,即暴力枚举所有点和
k
k
k,这样当然是没问题的。
而且在数据挖掘中往往时间并不占据主要考虑对象,所以时间复杂度显得不是很重要。
但是显然有更优化的方法,比如用
K
D
T
r
e
e
KDTree
KDTree来优化这个过程或者
B
a
l
l
T
r
e
e
Ball_Tree
BallTree来优化,效果都是很好的。
当然这都不是我们考虑的范围,
P
y
t
h
o
n
Python
Python已经给出了相应的函数,我们只需要拿来用即可。
但是可能有一个问题,就是上述的
k
k
k到底取多少,题目里也并没有明确强调。经过实验取
10
10
10即可,
P
y
t
h
o
n
Python
Python函数中默认是
20
20
20。
在求出所有密度之后我们在用
f
i
t
_
p
r
e
d
i
c
t
fit_predict
fit_predict函数进行预测即可,其中为
−
1
-1
−1的点就是异常点。
代码:
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from sklearn.neighbors import LocalOutlierFactor
# 导入数据
abc = pd.read_csv('deaths.csv')
## 只分析其中的Population和Lat两个变量
abc = abc[["Population","Lat"]]
###begin###
lof = LocalOutlierFactor(n_neighbors = 10)
###将lof作用于数据集
score = lof.fit_predict(abc)
ans = 0
for scr in score :
if scr == -1 :
ans += 1
print("检测出的异常值数量为:", ans)
###end####
一些问题和思考:
- 首先,这些算法
P
y
t
h
o
n
Python
- 这里
n
_
n
e
i
g
h
b
o
r
s
=
10
n_neighbors = 10
f
i
t
_
p
r
e
d
i
c
t
fit_predict
k
k
10
10
k
k
- 对于
k
k
k
k
k
k
k
k
10
10
20
20
这其中的原因是:k
k
k
k
k
k
k
k
l
o
f
lof
服务器托管,北京服务器托管,服务器租用 http://www.fwqtg.net