LOF 算法背景:
基于密度的离群点检测方法的关键步骤在于给每个数据点都分配一个离散度,其主要思想是:针对给定的数据集,对其中的任意一个数据点,如果在其局部邻域内的点都很密集,那么认为此数据点为正常数据点,而离群点则是距离正常数据点最近邻的点都比较远的数据点。通常有阈值进行界定距离的远近。在基于密度的离群点检测方法中,最具有代表性的方法是局部离群因子检测方法 (Local Outlier Factor, LOF)。
算法简介:
在众多的离群点检测方法中,LOF 方法是一种典型的基于密度的高精度离群点检测方法。在 LOF 方法中,通过给每个数据点都分配一个依赖于邻域密度的离群因子 LOF,进而判断该数据点是否为离群点。若 LOF >> 1, 则该数据点为离群点;若 LOF 接近于 1,则该数据点为正常数据点。
距离邻域
定义 设 为点
的第
距离邻域,满足:
注 此处的邻域概念与国内高数教材略有不同(具体的点,而非区间)。该集合中包含所有到点 距离小于点
第
邻域距离的点。易知有
,如上图,点
的第 5 距离邻域为:
可达距离
定义 点 到点
的第
可达距离定义为:
注 即点 到点
的第
可达距离至少是点
的第
距离。距离
点最近的
个点,它们到
的可达距离被认为是相当的,且都等于
局部可达密度
定义 局部可达密度定义为:
注 表示点 的第
邻域内所有点到
的平均可达距离,位于第
邻域边界上的点即使个数大于1,也仍将该范围内点的个数计为
。如果
和周围邻域点是同一簇,那么可达距离越可能为较小的
,导致可达距离之和越小,局部可达密度越大。如果
和周围邻域点较远,那么可达距离可能会取较大值
,导致可达距离之和越大,局部可达密度越小。
局部离群因子
注 表示点 的邻域
内其他点的局部可达密度与点
的局部可达密度之比的平均数。如果这个比值越接近1,说明
的邻域点密度差不多,
可能和邻域同属一簇;如果这个比值小于1,说明
的密度高于其邻域点密度,
为密集点;如果这个比值大于1,说明
的密度小于其邻域点密度,
可能是异常点。
代码:
import pandas as pd
from sklearn.neighbors import LocalOutlierFactor
def lof(data, predict=None, k=5, method=1, plot=False):
# 判断是否传入测试数据,若没有传入则测试数据赋值为训练数据
try:
if predict == None:
predict = data.copy()
except Exception:
pass
predict = pd.DataFrame(predict)
# 计算 LOF 离群因子
clf = LocalOutlierFactor(n_neighbors=k + 1, algorithm='auto', contamination=0.1, n_jobs=-1)
clf.fit(data)
# 记录 k 邻域距离
predict['k distances'] = clf.kneighbors(predict)[0].max(axis=1)
# 记录 LOF 离群因子,做相反数处理
predict['local outlier factor'] = -clf._decision_function(predict.iloc[:, :-1])
# 根据阈值划分离群点与正常点
outliers = predict[predict['local outlier factor'] > method].sort_values(by='local outlier factor')
inliers = predict[predict['local outlier factor'] <= method].sort_values(by='local outlier factor')
return outliers, inliers
参考资料:
https://zhuanlan.zhihu.com/p/37753692
问题:参考资料的算法,在PyCharm中即使没有运行也会导致笔记本CPU暴涨,所以不要写多个函数,直接一个函数就可以了,具体原因,我这个辣鸡也不懂,而且跑的好慢,我五百万的数据跑了40分钟,吐血!!!可能我真的是个盖世辣鸡吧!!!!!