"Clustering by fast search and find of density peaks"是今年6月份在《Science》期刊上发表的的一篇论文,论文中提出了一种非常巧妙的聚类算法。经过几天的努力,终于用python实现了文中的算法,下面与大家分享一下自己对算法的理解及实现过程中遇到的问题和解决办法。
首先,该算法是基于这样的假设:类簇中心被具有较低局部密度的邻居点包围,且与具有更高密度的任何点有相对较大的距离。对于每一个数据点,要计算两个量:点的局部密度和该点到具有更高局部密度的点的距离,而这两个值都取决于数据点间的距离。
数据点的局部密度定义为式(1):
其中,如果,那么;否则,是一个截断距离。基本上,等于与点的距离小于的点的个数。算法只对不同点的的相对大小敏感,这意味着对于大数据集,分析结果对于的选择有很好鲁棒性。
数据点的是点到任何比其密度大的点的距离的最小值式(2):
对于密度最大的点,我们可以得到。
图1.中的简单示例展示了算法的核心思想。图1.A展示了二维空间中的28个点。可以发现点1和点10的密度最大,故将其作为类簇中心。图1.B展示了对于每一个点的作为的
图1.算法在二维空间的展示。(A)点的分布 数据点按照密度降序排列。(B)(A)中数据的决策图 不同的颜色代表不同的类簇。
函数的图示,称其为决策图。点9和点10的相似,但值却有很大差别:点9属于点1的类簇,其它几个有更高的的点距其很近,然而点10的有更高密度的最近邻属于其它的类簇。所以,正如预期的那样,只有具有高和相对较高的的点才是类簇中心。因为点26、27、28是孤立的,所以有相对较高的值和低值,它们可以被看作是由单个点做成的类簇,也就是异常点。
类簇中心找到后,剩余的每个点被归属到它的有更高密度的最近邻所属类簇。类簇分配只需一步即可完成,不像其它算法要对目标函数进行迭代优化。
在聚类分析中,定量的衡量分配的可信度是很重要的。在该算法中,首先为每个类簇定义一个边界区域(即分配到该类簇但于其它类簇的点的距离小于的点的集合),然后为每个类簇的找到其边界区域中密度最高的点,并以来表示该点的密度。类簇中局部密度值比大的点被看作是类簇的核心部分(即分配到该类簇的可靠性较高),其他点被看作是类簇的光晕部分(亦可以被看作是噪声)。
图2.合成点分布的结果。(A)绘制的点分布的概率分布。(B和C)分别为4000和1000样本点的点分布。每个点以其颜色表示所属类簇,黑色点属于光晕类簇。(D和E) 相应的决策图,彩色的点表示类簇中心。(F)被归属到错误的类簇的点的比例作为样本维度的函数。误差线表明均值的标准差。
从图2.(F)中可以看到,错分点的比例即使在只有1000个点的小样本中仍保持在1%以下,说明算法有很好的鲁棒性。
为图2.B中数据赋予不同的值,却得到几乎一样的结果。一般来说,我们可以选择使得点的平均邻居数大概是数据集中点的总数的1-2%。对于较小的数据集,可能会被大的统计误差影响,在这种情况下,需要通过更准确的方法估计密度(例如可以采取文章中提到的指数核的方法)。
从下图中可以看到,该算法对于各种数据级都能达到很好的聚类效果。
算法对于不严重影响以下的距离,也就是保持等式(1)的密度估计量不变的度量标准的变化有很好的鲁棒性。很明显,等式(2)中的距离将会被这种度量标准的改变所影响,但很容易意识到决策图的结构(尤其是有较大的值的点的个数)是一个按密度值排序的结果,并不是距离较远的点的真实距离。
感兴趣的同学可以在这里下载算法的python实现代码。因为现在的实现并不能对所有的数据集都得到良好的效果,所以如果哪位同学有更好的想法,希望能不吝赐教。