深入理解Local Outlier Factor(LOF)局部异常因子算法

这篇具有很好参考价值的文章主要介绍了深入理解Local Outlier Factor(LOF)局部异常因子算法。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

一、概述

首先,写这篇文章的初衷是为了记录自身对LOF的理解,另一个原因是个人在学习该算法的时候,也查阅过不少的文章或者视频,有一些知识点(如可达距离、局部可达密度等概念)可能并没有清晰的表达出来,因此该文章本着个人对该算法的理解记录学习该算法的过程,如有错误,请直接私信tinstone,希望对刚接触该算法的同学有所帮助,让知识传播下去。

Local Outlier Factor(LOF)是基于密度的经典算法,文章发表于 SIGMOD 2000。在LOF之前的异常检测算法大多是基于统计的方法(3α原则、箱型图等),或者是借用一些聚类算法的异常识别(如DBSCAN),而这些方法都有一些不完美的地方:

  • 基于统计的方法:通常需要假设数据服从某些特定的概率分布
  • 聚类方法:通常只能给出0/1的判断(即是否为异常点),不能量化每个数据点异常程度,而且DBSCAN算法是一个全局性指标算法,对于所有数据使用相同的模型参数。

相比较而言,基于密度的LOF算法要更简单、直观。它不需要对数据的分布做太多的假设,还能量化的给出每个数据点的异常程度

二、LOF算法

1. 直观理解

首先,基于密度的离群点检测方法有一个假设:非离群点对象周围的密度与其相邻点的周围的密度类似,而离群点对象周围的密度显著不同于其邻域周围点的密度
通过下面的图片,可以直观的感受下:
深入理解Local Outlier Factor(LOF)局部异常因子算法
聚集簇C1的点的分布间距比较大,即密度较小,但该簇内的点的密度都类似,而聚集簇C2 的点的分布间距更紧密,即密度更大,但该簇内的点的密度也都是类似的,再来观察O1、O2两个数据点,其周边的点数量较少或者密度较低,因此这两个点判定为异常点,因为基于假设得到:这两个点周围的密度显著不同于周围点的密度。

2. 核心思想

LOF,又称局部异常因子算法,从这个算法名称中我们先剧透一些信息:

  • 局部:如何定义局部??联想KNN中的k近邻
  • 异常因子:如何定义异常?如何计算异常因子?LOF使用密度的概念定义了点与周围点的相对密度来确定点是否异常

有了上面的理解,这里一句话总结LOF的核心思想:通过计算一个score来反映一个样本的异常程度(该score是一个相对值,注意区别使用KNN进行异常检测的平均距离),如何理解score:一个样本点周围的样本的所处位置的平均密度比上该样本点所在位置的密度,比值越大于1,则该点所在位置的密度越小于其周围样本所在位置的密度, 这个点就越有可能是异常点。

3.深入理解LOF

在了解LOF之前,必须知道几个基本的概念,因为LOF是基于这几个概念来定义“局部”、“密度”、“异常因子”等相关概念的。

3.1. k邻近距离

在距离数据点P最近的几个点中,第 k 个最近的点跟点 P 之间的距离称为点 P的 k邻近距离,记为k-distance(p),定义了局部异常因子算法中“局部”的概念,公式如下:
深入理解Local Outlier Factor(LOF)局部异常因子算法
:点 O 为距离点 P 最近的第 k 个点(k 为正整数,与KNN中的 k 的概念相同)。
深入理解Local Outlier Factor(LOF)局部异常因子算法
比如上图中,距离点 P 最近的第 4 个点是 点4、5、6(即可能存在距离相等的点)。
这里的距离计算可以采用欧氏距离、汉明距离、马氏距离等等,通常采用欧氏距离(公式省略。。。)。

3.2. k距离邻域

以点 P 为圆心,以 k邻近距离深入理解Local Outlier Factor(LOF)局部异常因子算法为半径画圆,这个圆以内的范围就是 k 距离邻域,公式如下:深入理解Local Outlier Factor(LOF)局部异常因子算法
还是以上图所示,假设 k=4,则 1-6均是邻域范围内的点。

3.3. 可达距离

点 P 到点 O 的第 k 可达距离(注意:该距离公式通常容易理解错误),公式如下:
深入理解Local Outlier Factor(LOF)局部异常因子算法
这个可达距离需要特别注意:

  • 此处的点 O 为点 P 的 k邻域内的点
  • 可达距离是p的邻域点 Nk(p)到p的可达距离,不是p到Nk(p)的可达距离,一定要弄清楚关系,因为该距离不具有对称性(点 P 的 k 近邻与点 O的 k近邻可能不同(密度不同))

通俗理解:点P到点O的可达距离实际上包含两层含义:

  • (1) 点O是点P的K邻域内的点
  • (2) 可达距离是以点O为对象,对比O的K邻近距离与OP实际距离的大小,然后选择较大的距离作为点P到点O的可达距离

而可达距离代表的数学含义为

  • (1) 此时存在点O的k邻近距离可能小于P的k邻近距离,即点O的密度大导致其k距离范围小,点O的k邻近距离并不包含点P,此时的点P到点O的第k可达距离为OP的距离
  • (2) 点P到点O的第k可达距离是以O为对象,选择O的k邻近距离或者OP的实际距离表示了对点P周边点的密度的衡量:P点周边的密度要小于O点周边的密度,然后通过求得点P的K邻域内所有点的可达距离,可以大致判断点P周边的点平均密度(通过理解局部可达密度的概念再来看可达距离更容易理解)。

3.4. 局部可达密度

点 P 的局部可达密度就是借助点 P到其 k邻域(“局部”)内的点(如点O,或者同心圆图例中的1-6的点)的可达距离的平均距离的倒数,具体公式如下:
深入理解Local Outlier Factor(LOF)局部异常因子算法

取倒数的意义:使得距离与密度能达成认知上的一致性:距离越大,密度越小

3.5. 局部异常因子

根据局部可达密度的定义,如果一个数据点与周围数据点的平均密度相似(现在就只考虑密度,暂时忘记距离的概念,不然容易混),则其比值应该趋近于1,因此LOF算法衡量一个数据点的异常程度,并不是看它的绝对局部密度,而是看它跟周围邻近点的相对密度,即比值的概念,因此局部异常因子即是用局部密度来定义的,数据点 P 的局部异常因子为点 P 的 k邻域内的点的平均局部可达密度与点 P 的局部可达密度的比值,公式如下:深入理解Local Outlier Factor(LOF)局部异常因子算法
公式理解:

  • 点 O 是点 P的 k邻域内的点,lrd§,即为点 P的局部可达密度,而 lrd(O) 表示的则是点 P的 k邻域内的点,基于这些点再去求得点的局部可达密度,即lrd(O)其实就是点P周围点的局部可达密度
  • lrd(O) / lrd§ 不就是点P 的 k邻域内某个点的密度与点 P的密度的比值:点周边的密度与点的密度的比值
  • 对于标号1变换为标号2,其实就是项的拆分,因为 lrd§是个固定值,直接提出来即可,而且通过这种变形,更容易立即LOF§的含义:点周边的密度的平均值与点的密度的比值

注:取相对密度的好处是可以允许数据分布不均匀、密度不同的情况存在,比如直观理解中C1、C2的点的分布

4.LOF算法流程

了解了LOF的相关概念之后,整个算法也就清晰明了了:

  1. 对于每个数据点,计算它与其他点的距离,并按从近到远排序;
  2. 对于每个数据点,找到它的 k邻域点,并计算LOF得分;
  3. 如果LOF值越大,说明越异常,反之越小,说明越正常;
    深入理解Local Outlier Factor(LOF)局部异常因子算法

5.LOF算法优缺点

优点:

  • LOF 的一个优点是它同时考虑了数据集的局部和全局属性。异常值不是按绝对值确定的,而是相对于它们的邻域点密度确定的。当数据集中存在不同密度的不同集群时,LOF表现良好,比较适用于中等高维的数据集。

缺点:

  • LOF中 k参数的选择及调优
  • LOF算法中关于局部可达密度的定义其实暗含了一个假设,即:不存在大于等于 k 个重复的点
    当这样的重复点存在的时候,这些点的平均可达距离为零,局部可达密度就变为无穷大,会给计算带来一些麻烦。在实际应用时,为了避免这样的情况出现,可以把 k-distance 改为 k-distinct-distance,不考虑重复的情况。或者,还可以考虑给可达距离都加一个很小的值,避免可达距离等于零。
    另外,LOF 算法需要计算数据点两两之间的距离,造成整个算法时间复杂度为 。为了提高算法效率,后续有算法尝试改进。FastLOF (Goldstein,2012)先将整个数据随机的分成多个子集,然后在每个子集里计算 LOF 值。对于那些 LOF 异常得分小于等于 1 的,从数据集里剔除,剩下的在下一轮寻找更合适的 nearest-neighbor,并更新 LOF 值。

三、Python代码实现

Python实现LOF代码主要基于sklearn库,主要的代码参数如下:

from sklearn.neighbors import LocalOutlierFactor
主要参数:
    n_neighbors:设置k, default=20
    contamination: 设置样本中异常点的比例, default=0.1
主要属性:
    negative_outlier_factor_: numpy array, shape(n_samples)
    和LOF相反的值,值越小,越有可能是异常点,(注:上面提到的LOF的值越接近1, 越可能是正样本, LOF的值越大于1, 则越可能是异常样本)
主要方法:
    fit_predict(x): 返回一个数组, -1,表示异常点, 1表示正常点

完整代码

# !/usr/bin/python
# -*- coding:utf-8 -*-
 
import numpy as np
import matplotlib
import matplotlib.pyplot as plt
from sklearn.neighbors import LocalOutlierFactor

print(__doc__)

np.random.seed(42)

xx, yy = np.meshgrid(np.linspace(-5, 5, 500), np.linspace(-5, 5, 500))
# Generate normal (not abnormal) training observations
X = 0.3 * np.random.randn(100, 2)
X_train = np.r_[X + 2, X - 2]
# Generate new normal (not abnormal) observations
X = 0.3 * np.random.randn(20, 2)
X_test = np.r_[X + 2, X - 2]
# Generate some abnormal novel observations
X_outliers = np.random.uniform(low=-4, high=4, size=(20, 2))

# fit the model for novelty detection (novelty=True)
clf = LocalOutlierFactor(n_neighbors=20, novelty=True, contamination=0.1)
clf.fit(X_train)
# DO NOT use predict, decision_function and score_samples on X_train as this
# would give wrong results but only on new unseen data (not used in X_train),
# e.g. X_test, X_outliers or the meshgrid
y_pred_test = clf.predict(X_test)
y_pred_outliers = clf.predict(X_outliers)
n_error_test = y_pred_test[y_pred_test == -1].size
n_error_outliers = y_pred_outliers[y_pred_outliers == 1].size

# plot the learned frontier, the points, and the nearest vectors to the plane
Z = clf.decision_function(np.c_[xx.ravel(), yy.ravel()])
Z = Z.reshape(xx.shape)

plt.title("Novelty Detection with LOF")
plt.contourf(xx, yy, Z, levels=np.linspace(Z.min(), 0, 7), cmap=plt.cm.PuBu)
a = plt.contour(xx, yy, Z, levels=[0], linewidths=2, colors='darkred')
plt.contourf(xx, yy, Z, levels=[0, Z.max()], colors='palevioletred')

s = 40
b1 = plt.scatter(X_train[:, 0], X_train[:, 1], c='white', s=s, edgecolors='k')
b2 = plt.scatter(X_test[:, 0], X_test[:, 1], c='blueviolet', s=s,
                 edgecolors='k')
c = plt.scatter(X_outliers[:, 0], X_outliers[:, 1], c='gold', s=s,
                edgecolors='k')
plt.axis('tight')
plt.xlim((-5, 5))
plt.ylim((-5, 5))
plt.legend([a.collections[0], b1, b2, c],
           ["learned frontier", "training observations",
            "new regular observations", "new abnormal observations"],
           loc="upper left",
           prop=matplotlib.font_manager.FontProperties(size=11))
plt.xlabel(
    "errors novel regular: %d/40 ; errors novel abnormal: %d/40"
    % (n_error_test, n_error_outliers))
plt.show()

深入理解Local Outlier Factor(LOF)局部异常因子算法文章来源地址https://www.toymoban.com/news/detail-459573.html

四、参考文档

  • 一文读懂异常检测 LOF 算法(Python代码)
  • 异常点/离群点检测算法——LOF
  • 基于LOF的异常检测算法

到了这里,关于深入理解Local Outlier Factor(LOF)局部异常因子算法的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 带你深入理解Java异常

    💕“人生就像一盘棋,有时候你慢一步,就输掉了一局。但只要你不停止思考和行动,就永远有机会翻盘。”💕 🐼作者:不能再留遗憾了🐼 🎆专栏:Java学习🎆 🏀本文章主要内容:详细讲解Java异常🏀 Java是一种面向对象编程语言,提供了一种强大的异常处理机制。Jav

    2024年02月04日
    浏览(19)
  • 深入理解Java中的java.lang.ArithmeticException异常

    在Java中,异常处理是一种重要的编程机制。异常是指在程序执行过程中发生的错误或异常情况,它打破了正常的程序流程,需要进行相应的处理。Java提供了丰富的异常类和异常处理语法,使开发人员能够更好地处理和管理异常情况。 本篇博客将着重介绍Java中的 java.lang.Ari

    2024年02月08日
    浏览(29)
  • 深入理解 JVM 之——Java 内存区域与溢出异常

    更好的阅读体验 huge{color{red}{更好的阅读体验}} 更好的阅读体验 本篇为深入理解 Java 虚拟机第二章内容,推荐在学习前先掌握基础的 Linux 操作、编译原理、计算机组成原理等计算机基础以及扎实的 C/C++ 功底。 该系列的 GitHub 仓库:https://github.com/Doge2077/learn-jvm Java 虚拟机在

    2024年02月09日
    浏览(51)
  • “深入理解SpringMVC的JSON数据返回和异常处理机制“

    在现代Web开发中,SpringMVC是一个广泛使用的框架,它提供了丰富的功能和灵活的配置选项。本文将深入探讨两个重要的主题:SpringMVC中的JSON数据返回和异常处理机制。我们将逐步介绍相关的配置和使用方法,并通过案例和综合实例来加深理解。 1.1 导入依赖 1.2 配置弹簧-MVC

    2024年02月08日
    浏览(23)
  • 深入理解Java虚拟机(二)Java内存区域与内存溢出异常

            对于Java程序员来说,在虚拟机自动内存管理机制的帮助下,不再需要为每一个new操作去写配对的delete/free代码,不容易出现内存泄漏和内存溢出问题,看起来由虚拟机管理内存一切都很美好。不过,也正是因为Java程序员把控制内存的权力交给了Java虚拟机,一旦出

    2024年02月16日
    浏览(60)
  • 《深入理解计算机系统(CSAPP)》第8章 异常控制流 - 学习笔记

    写在前面的话:此系列文章为笔者学习CSAPP时的个人笔记,分享出来与大家学习交流,目录大体与《深入理解计算机系统》书本一致。因是初次预习时写的笔记,在复习回看时发现部分内容存在一些小问题,因时间紧张来不及再次整理总结,希望读者理解。 《深入理解计算机

    2024年02月08日
    浏览(50)
  • 关于行列式因子,不变因子,初等因子的理解

    行列式因子可以由矩阵行列式计算得到,不变因子可以通过计算出的行列式因子间相除得到,初等因子可以由不变因子的分式得到。 其中行列式因子和不变因子包含了特征矩阵的全部信息,而初等因子丢失了秩信息,只有秩和初等因子都相同才能说明特征矩阵等价,而另外两

    2024年02月11日
    浏览(26)
  • 深入理解JVM虚拟机第十五篇:虚拟机栈常见异常以及如何设置虚拟机栈的大小

    😉😉 学习交流群: ✅✅1:这是 孙哥suns 给大家的福利! ✨✨2:我们免费分享Netty、Dubbo、k8s、Mybatis、Spring...应用和源码级别的视频资料 🥭🥭3:QQ群: 583783824   📚📚  工作微信: BigTreeJava 拉你进微信群,免费领取! 🍎🍎4:本文章内容出自上述:Spring应用课程!💞💞

    2024年02月06日
    浏览(33)
  • 《深入理解Java虚拟机(第三版)》读书笔记:Java内存区域与内存溢出异常、垃圾收集器与内存分配策略

    下文是阅读《深入理解Java虚拟机(第3版)》这本书的读书笔记,如有侵权,请联系删除。 Java虚拟机在执行Java程序的过程中会把它所管理的内存划分为若干个不同的数据区域。这些区域有各自的用途,以及创建和销毁的时间,有的区域随着虚拟机进程的启动而一直存在,有

    2024年02月03日
    浏览(30)
  • SpringBoot 如何使用 @ExceptionHandler 注解进行局部异常处理

    在开发 Web 应用程序时,异常处理是非常重要的一部分。SpringBoot 提供了多种方式来处理异常,其中之一是使用 @ExceptionHandler 注解进行局部异常处理。使用 @ExceptionHandler 注解,我们可以在 Controller 层或方法级别上处理异常,而不用在整个应用程序中处理。 在本文中,我们将介

    2024年02月13日
    浏览(27)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包