问题
我有这么一些点,大概1300个左右。需要检测它的离群点。
如果我用IsolationForest(孤立森林来做),效果是这样(红色为离群点)
很明显,在低位维上,相对于一些基于距离的算法,Isolation Forest表现较差。
那接下换LOF
可以看到,LOF的表现比IsolationForest好很多,但仍旧不够完美,图右上角几个黄点没有被算作离群点。这是因为LOF对于不同密度区域之间的异常检测效果不佳。
那么有没有一种能以距离计算离群点的方法呢?
思路:
- 计算每个点距离其最近的k个点的距离并求和排序
- 对距离求差并找出相邻差值最大索引。这一步是边界,区分异常值和正常值
- 设置一个阈值T(我代码中没有设置),如果相邻差值最大的索引下的差值大于阈值T(避免出现没有离群点但分析出离群点的情况),将该索引后的点视为离群点,并将其从数据集中去除
离群点计算
import numpy as np
import matplotlib.pyplot as plt
from sklearn.neighbors import NearestNeighbors
from datetime import datetime
# 计算每个点距离其最近的k个点的距离
k = 6 #根据点数量来定
nbrs = NearestNeighbors(n_neighbors=k).fit(X)
distances, indices = nbrs.kneighbors(X)
nearest_distances = np.sort(distances[:, 1:], axis=1)
# 计算每个点距离最近k个点的距离之和
sum_distances = np.sum(nearest_distances, axis=1)
# 对距离求差并找出相邻差值最大的索引
diff = np.diff(np.sort(sum_distances))
max_diff_index = np.argmax(diff)
# 标记离群点
threshold = np.sort(sum_distances)[max_diff_index+1]
outliers = np.where(sum_distances > threshold)[0]
检测效果