标签:
韩家炜书中在介绍基于聚类的异常值检测中的第二种方法提到: 如果某对象与最近的簇的距离非常远,则该对象为Outlier。这句话其实有两个意思,第一个意思假定某对象在cluster A中,则它必定距离A簇比较近( 一般指的是球型的cluster )。第二个意思假定某对象是未知的点,距离A簇最近。其实在使用中,大部分情况我们可以把这两个场景合二为一。在本文中,我们假定对象已经在cluster A中。
本文基于聚类的异常值检测的算法思路是:
1 ) 用聚类算法做cluster
2 ) 计算cluster中每个点到该cluster中心的距离( 假定是欧式距离 ), 再得出cluster中所有点到中心的平均距离l。
3 ) 用户设置一个spec参数。
4 ) 计算cluster中的每个点到cluster中心的距离s,如果s / l > spec,则该点判断为outlier。
所以这个方法依赖于聚类算法的结果以及后续那个spec参数的设置。
为了更好地说明问题,我在这里用了个测试数据集。它主要由3个cluster组成,密度差不多,每个cluster周围有些outlier,有两个global的outlier。
首先做聚类。这里就采用最简单的KMeans。KMeans实在太有名,原理就不描述了( 也许以后会分享KMeans++或者优化算法结合KMeans )。这里K设置为3,聚类结果如下:
三个cluster,两个global的outlier分别被分到两个不同的cluster里去了。每个cluster的中心用黄色的五角星标出。聚类完成后,接着对每个cluster做异常值检测,代码如下:
import numpy as np import scipy.spatial.distance as ssd def calClusterDiffOutlier( clusterSamples, clusterCenter, diffSpec = 2 ): dists = np.array( [ ssd.euclidean( sample, clusterCenter ) for sample in clusterSamples ] ) lco = np.mean( dists ) labels = np.array( dists / lco > diffSpec, np.int ) return labels
这里的spec我们设置为2。也就是说到中心的距离,超过平均中心距离的一倍。算法的结果如下( 绿色的为outlier ):
两个global的outlier抓到了。大部分的local outlier也抓到了,有几个没有检测到。有部分outlier处于灰色地带,不同的人会有不同的看法,有些人觉得是outlier,而有些人则认为不是。无论如何,这是一个思路,先用无监督的方法获取数据的大致结构,然后再这个结构上,去除那些global或者local的outlier。
刚刚我们用了KMeans, 我们换个思路用MeansShift也可以解决这个问题,只是MeanShift算法会给我们一些不同的见解。关于MeanShift方法,我以后会分享,当然读者可以参考http://www.cnblogs.com/liqizhou/archive/2012/05/12/2497220.html,这文章写得不错。MeanShift得结果如下:
由于MeansShift方法的特性,outlier有可能被当作单独一个cluster来处理。这个时候直接用前面的异常值处理方法就会出问题。但是这里的结果又给我们一个新的启发。我们发现如果出现很小的cluctser,则整个custer可能都是outlier! 所以基于这样的认识,我们可以将前面基于聚类的方法再扩充下,用来处理小簇或者说稀疏簇:
def detectOutliers( X, clusterLabels, clusterCenters, minPts = 3, diffSpec = 2 ): labels = np.zeros( len( clusterLabels ) ) uniqLabels = np.unique( clusterLabels ) for label in uniqLabels: mask = clusterLabels == label if np.sum( mask ) < minPts: # small cluster --> all are outliers labels[ mask ] = 1 continue clusterCenter = clusterCenters[ label ] results = calClusterDiffOutlier( X[ mask ], clusterCenter, diffSpec ) labels[ mask ] = results
return labels
我们给算法加一个参数minPts,意思是如果一个cluster中样本数小于这个minPts,则该簇全为outlier。这样就能处理像MeanShift或产生单样本cluster的情况。而且很小的簇,很可能就是outlier,该方法的结果如下:
基于MeanShift的方法的中心貌似比KMeans产生的中心更合理点,而且也消除了global outlier对簇的影响。所以cluster附近的outlier检测得更加合理了。
当我们欣喜结果不错得时候,我们用这个方法来看看上次文章中的数据。显然那篇文章只有一个cluster。
非球状的cluster的outlier检测显然不能直接用这个方法来完成。
前途是光明的,道路是曲折的。方法是死的,人是活的。我们已经介绍了一些方法,基于聚类的、基于近邻的,基于统计的。用合适的方法,或者加以组合、改进。任何方法都给我们一个idea!关键是idea!而不是算法固定的流程! 比如聚类算法CURE也包含了聚类过程中outlier的处理,以后我们会专门做分享。
如果文章中的测试数据有人感兴趣的话,可以留言联系。
标签:
原文地址:http://www.cnblogs.com/zhuyubei/p/4856363.html