"An outlier is an observation which deviates so much from other observations as to arouse suspicions that it was generated by a different mechanism."
— D. M. Hawkins, Identification of Outliers, Chapman and Hall, 1980.
Local Outlier Factor(LOF)是基于密度的经典算法(Breuning et. al. 2000), 文章发表于 SIGMOD 2000, 到目前已经有 3000+ 的引用。在 LOF 之前的异常检测算法大多是基于统计方法的,或者是借用了一些聚类算法用于异常点的识别(比如 ,DBSCAN,OPTICS)。但是,基于统计的异常检测算法通常需要假设数据服从特定的概率分布,这个假设往往是不成立的。而聚类的方法通常只能给出 0/1 的判断(即:是不是异常点),不能量化每个数据点的异常程度。相比较而言,基于密度的LOF算法要更简单、直观。它不需要对数据的分布做太多要求,还能量化每个数据点的异常程度(outlierness)。 算法介绍
LOF 是基于密度的算法,其最核心的部分是关于数据点密度的刻画。如果对 distanced-based 或者 density-based 的聚类算法有些印象,你会发现 LOF 中用来定义密度的一些概念似曾相识。了解了这些核心概念,整个算法也就显而易见了。而整个算法,最主要的是下面四个概念:
K-邻近距离(k-distance):在距离数据点 p 最近的几个点中,第 k 个最近的点跟点 p 之间的距离称为点 p 的 K-邻近距离,记为 k-distance (p) 。
可达距离(rechability distance):可达距离的定义跟K-邻近距离是相关的,给定参数k时, 数据点 p 到 数据点 o 的可达距离 reach-dist(p, o)为数据点 o 的K-邻近距离 和 数据点p与点o之间的直接距离的最大值。即:
局部可达密度(local rechability density):局部可达密度的定义是基于可达距离的,对于数据点 p,那些跟点p的距离小于等于 k-distance(p)的数据点称为它的 k-nearest-neighbor,记为 ,数据点 p 的局部可达密度为它与邻近的数据点的平均可达距离的倒数,即:
局部异常因子(local outlier factor):根据局部可达密度的定义,如果一个数据点跟其他点比较疏远的话,那么显然它的局部可达密度就小。但LOF算法衡量一个数据点的异常程度,并不是看它的绝对局部密度,而是看它跟周围邻近的数据点的相对密度。这样做的好处是可以允许数据分布不均匀、密度不同的情况。局部异常因子即是用局部相对密度来定义的。数据点 p 的局部相对密度(局部异常因子)为点p的邻居们的平均局部可达密度跟数据点p的局部可达密度的比值,即:
根据局部异常因子的定义,如果数据点 p 的 LOF 得分在1附近,表明数据点p的局部密度跟它的邻居们差不多;如果数据点 p 的 LOF 得分小于1,表明数据点p处在一个相对密集的区域,不像是一个异常点;如果数据点 p 的 LOF 得分远大于1,表明数据点p跟其他点比较疏远,很有可能是一个异常点。下面这个图来自 Wikipedia 的 LOF 词条,展示了一个二维的例子。上面的数字标明了相应点的LOF得分,可以让人对LOF有一个直观的印象。
了解了 LOF 的定义,整个算法也就显而易见了:
1. 对于每个数据点,计算它与其它所有点的距离,并按从近到远排序;
2. 对于每个数据点,找到它的 k-nearest-neighbor,计算 LOF 得分。
算法应用
LOF算法中关于局部可达密度的定义其实暗含了一个假设,即:不存在大于等于 k 个重复的点。当这样的重复点存在的时候,这些点的平均可达距离为零,局部可达密度就变为无穷大,会给计算带来一些麻烦。在实际应用时,为了避免这样的情况出现,可以把 k-distance 改为 k-distinct-distance,不考虑重复的情况。或者,还可以考虑给可达距离都加一个很小的值,避免可达距离等于零。
LOF 算法需要计算数据点两两之间的距离,造成整个算法时间复杂度为 。为了提高算法效率,后续有算法尝试改进。FastLOF (Goldstein,2012)先将整个数据随机的分成多个子集,然后在每个子集里计算 LOF 值。对于那些 LOF 异常得分小于等于 1 的,从数据集里剔除,剩下的在下一轮寻找更合适的 nearest-neighbor,并更新 LOF 值。这种先将数据粗略分成多个部分,然后根据局部计算结果将数据过滤来减少计算量的想法,并不罕见。比如,为了改进 K-means 的计算效率, Canopy Clustering 算法也采用过比较相似的做法。
异常检测算法(三):Principal Component Analysis
Principal Component Analysis(PCA)是最常见的数据降维的方法。根据 Wikipedia 的介绍,它最早是由 Karl Pearson(同时也是卡方检验的发明者) 在1901年提出,到现在已经一百多年了。作为一种降维的方法,PCA可以将原数据进行线性变换,并找出数据中信息含量最大的主要成分,去除信息含量较低的成分,从而减少冗余,降低噪音。通常在异常检测的语境里,噪音(noise)、离群点(outlier)和 异常值(anomaly)是同一件事情的不同表述。所以,PCA既然可以识别噪音,自然也可以检测异常。
高斯混合模型在实际求解过程中,运行的代码很容易出现奇异矩阵的问题。尽管算法为了防止协方差矩阵不可逆,在目标函数中增加了正则项,但是在代码实际实现过程中还是需要对可能出现奇异矩阵的情况做特别处理,保障算法平稳运行,比如,可以在对角线添加一个极小值之类(光靠这个可能还不够)。这篇文章对这个问题描述的还比较清楚,有兴趣的可以看看:《Regularized Gaussian Covariance Estimation》(https://freemind.pluskid.org/machine-learning/regularized-gaussian-covariance-estimation/)。
基于深度学习的异常检测算法最近几年层出不穷,后面有机会会继续介绍。还有一些经典的算法,也有好玩的地方。比如,之前一直有一个让我很困惑的问题,为什么 One-Class SVM (不是 SVDD)要找一个可以把坐标原点跟其他数据点分隔开的超平面?并且通过这种方式就可以识别异常。这里的“原点”非常奇怪,原文章也没有给任何直观的解释,只说是受 1963 年的一篇老文章的启发,网上也几乎找不到其他人的解释,大部分人只是把这个当作是作者的一个假设(假设坐标原点是唯一的异常点)。这个问题困扰了我好几年,最近突然看到一篇 2014 年的 Paper,完美答疑, 感觉这个也值得写篇文章。
参考文献1.F. T. Liu, K. M. Ting and Z. H. Zhou,Isolation-based Anomaly Detection,TKDD,20112.M. M. Breunig, H. P. Kriegel, R. T. Ng, J. Sander. LOF: Identifying Density-based Local Outliers. SIGMOD, 2000.3.M. Goldstein. FastLOF: An Expectation-Maximization based Local Outlier detection algorithm. ICPR, 20124.Veeramachaneni, K., Arnaldo, I., Korrapati, V., Bassias, C., Li, K.: AI^2 : training a big data machine to defend. In: 2016 IEEE 2nd International Conference on Big Data Security on Cloud (BigDataSecurity), IEEE International Conference on High Performance and Smart Computing (HPSC), and IEEE International Conference on Intelligent Data and Security (IDS), pp. 49–54 (2016)5.Shyu M L, Chen S C, Sarinnapakorn K, et al. A novel anomaly detection scheme based on principal component classifier. ICDM, 2003.