除了利用盒形图来寻找异常值(这里理解为虚假交易),还可以用Local Outlier Factor(简称LOF)方法。下面首先介绍LOF方法。
简单地使用盒形图是不够的,在某些情况下,它不能识别出异常值。如下图所示:
这个数据样本的特点是有两个中心,而中间有一块稀疏区域(红色),这里密度很低,极少有样本点落在这个区域内。如果突然有一些样本点落在了该区域内,我们有理由怀疑,这些样本点是异常值。但是,使用盒形图来判断异常值的话,显然这块红色区域落在了盒形图的“肚子”里了,是不能识别这部分出现的异常值的。怎么办呢?
异常值的定义:有些观测与其他观测差异如此明显,以至于我们认为该观测来自于另外一个“机制”(可以看做分布)。而红色区域的这些值确实与其他观测有明显差异,可以看做是异常值。一般来说,出现异常值的区域是密度非常低的区域:如果我们进行密度估计,发现某些地方密度非常低,而这些区域的观测就可以认为是异常值。那么如何估计一个观测附近的密度呢?这就是LOF方法的要解决的了。
LOF方法下的密度是通过距离定义的。我们设定一个参数k,计算离某一个观测最近的k个观测与该观测的平均距离。试想,是不是那些越稀疏(密度低的区域)的观测所对应的平均距离越大呢?没错,距离越大,密度越小,越有可能是异常值。
已经强调过的是,我们不是直接判断某一个观测是或者不是异常值,我们只是给出一个度量值,用来度量该观测是异常值的“程度”。值越大,就越有可能是异常值。以上的“距离”就可以作为这么一个度量值。
以经典的鸢尾花数据集为例(iris),我们寻找其中的异常值。其实里面没有虚假的值,这些值都是当年真时的调查数据。里面的鸢尾花有三种类型(iris setosa,iris versicolor,iris virginica),每种类型有50次观测,每次观测包括花萼的长度、宽度,花瓣的长度、宽度。最后得到的是150行记录。这批数据快被人们用烂了,动不动就被人分析一顿,可喜的是,总会得到你想得到的东西。
现在我们假设其中有些异常值,并用LOF方法寻找这些异常值,方法如下:
> library(DMwR)
> iris2 <- iris[, 1:4]
> outlier.score <- lofactor(iris2, k = 5)
对于每一行观测,我们都给了它一个异常程度的度量LOF(也就是outlier.score),LOF越大,说明对应观测为异常值的可能性越大。我们找出5行最有可能是异常值的观测:
> (outliers <- order(outlier.score, decreasing = T)[1:5])
[1] 42 107 23 110 63
也就是说,如果你非要说数据里面有异常值的话,那么这几行观测应该是你的选择。我们画出数据的散点图,如下。那五个所谓的异常值,我们用红颜色“+”标识出来。发现,所谓的异常值确实处在了一些稀疏的区域,它们的邻近区域“朋友”稀少,把它们当做是“异常值”是合理的。
利用LOF方法对也可以识别虚假交易,主要针对的还是单价这个变量。分析后的PR曲线和累积查全率曲线如下:
通过两种方法(Box Plot和LOF)的对比,可以更深刻地理解这两幅图。看左边,在同样的查准率下,BOX方法有更大的查全率;看右边,在同样的查询工作量下,LOF方法会查找到更多的虚假记录。二者各执一词,这时就要看审计人员的目标了,你要是查准率一定的话,那么就是用BOX方法;你要是查询工作量一定,就是用LOF方法。