局部离群因子LOF

基于密度的离群点检测方法的关键步骤在于给每个数据点都分配一个离散度,其主要思想是:
针对给定的数据集,对其中的任意一个数据点,如果在其局部邻域内的点都很密集,那么认为此数据点为正常数据点

而离群点则是距离正常数据点最近邻的点都比较远的数据点。通常有阈值进行界定距离的远近。在基于密度的离群点检测方法中,最具有代表性的方法是局部离群因子检测方法 (Local Outlier Factor, LOF)。

  • 核心:样本点跟周围邻居的密度对比

LOF通过计算一个数值score来反映一个样本的异常程度。这个数值的大致意思是:一个样本点周围的样本点所处位置的平均密度比上该样本点所在位置的密度。比值越大于1,则该点所在位置的密度越小于其周围样本所在位置的密度,这个点就越有可能是异常点。

逐步公式理解

第k距离

luaif函数例子 lof函数_算法

意思是离p点第k远的点

第k距离领域

  • 意思是离p点第k远的点,以p为圆心,到第k远的点的距离为半径,画圆,这个圆就是第k距离领域

    这个圆很重要
  1. 如果数据点密,这个圆的半径就小
  2. 如果数据点稀疏,这个圆的半径就很大
  3. 由于圆的大小不同,所以在算距离的时候,有不同的结果

第k可达距离

luaif函数例子 lof函数_邻域_02

luaif函数例子 lof函数_算法_03

  1. 数据点p落在o2的第k距离领域内,那么o2到p的距离等于o2的第k距离。也就是说,距离o2点最近的k个点,它们到o2点的距离被认为是相当的,等于luaif函数例子 lof函数_邻域_04,即都等于o2的第k距离
  2. 数据点p落在第k距离领域范围外, 那么o1到p的距离等于o1到p的直接距离luaif函数例子 lof函数_测试数据_05

局部可达密度

luaif函数例子 lof函数_luaif函数例子_06

luaif函数例子 lof函数_算法_07是p点的k距离邻域, 也就是要计算p点与第k距离邻域内每一个点的距离,按照上述的两种情况计算(圈内还是圈外)

luaif函数例子 lof函数_人工智能_08

luaif函数例子 lof函数_测试数据_09

  • 表示的意义是:p点的k距离邻域内的点到p点的平均可达距离

局部离群因子

luaif函数例子 lof函数_算法_10

luaif函数例子 lof函数_算法_11


结果分析

给每个数据点都分配一个依赖于邻域密度的离群因子 LOF,进而判断该数据点是否为离群点。

  • 若异常分数 LOF 接近1,则说明样本点p的局部密度跟邻居的接近。
  • 若异常分数 LOF 小于1,表明p处于一个相对密集的区域,不像一个异常点。
  • 若异常分数 LOF 远大于1,表明p跟其他点比较疏远,很可能是一个异常点

代码:

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
clf.fit(data)

#获取第 k 距离邻域内的每一个点到中心点的距离
clf.kneighbors(data)

#获取每一个样本点的 LOF 值,该函数范围 LOF 值的相反数,需要取反号
-clf._decision_function(data)

clf._predict(data) 则按照原先设置的 contamination 输出判断结果(按比例给出判断结果,异常点返回-1,非异常点返回1)

致命缺点:

  • 必须不存在大于等于 k 个重复的点。当这样的重复点存在的时候,这些点的平均可达距离为零,局部可达密度就变为无穷大
  • 所有k diantance计算要去重