优美的聚类算法
Science作者(Alex Rodriguez, Alessandro Laio)提出一种优美的聚类算法, 据实际论文可以识别各种形状的类簇, 并且其超参数很容易确定。
算法思想
该算法的假设是类簇的中心由一些局部密度比较低的点围绕, 并且这些点距离其他有高局部密度的点的距离都比较大。 或者 类簇的中心是这样的一类点:它们被很多点围绕(导致局部密度大),且与局部密度比自己大的点之间的距离也很远。
该算法,即对所有坐标点,提出了基于相互距离概念,并将其应用到聚类算法中去。
在该类算法中,需要给每个点计算两个新的属性:
一个是每个点的局部密度db(即与该点距离在一定范围内的点的总数)
另一个是找到与自己最近的那个更局部高密度点的最短距离dis
是否为聚类中心点的判别规则?
那些有着比较大的局部密度 db 和较大 dis 的的点被认为是类簇的中心. 局部
密度较小但是dis较大的点是异常点
确定聚类中心后,其他点如何如何归属于某一类?
确定聚类中心后,让周围的点采取“跟随”策略,归类到密度比自己大的最近
邻居所在的簇,也就是和 kmean 策略归属判别策略是一模一样的。比如 A 点到底
归属于哪一个类,则计算A点到各个聚类中心的欧式距离,选择最小的那个欧式距
离最为最终类别的归属。
问题一:
计算每个点的局部密度,需要一个截断距离,也就是所谓的扫描半径r,因为r
是一个超参数(即训练前需要自定义的,而不是模型训练出来的参数) ,一种推荐做
法是选择扫描半径r使得平均每个点的邻居数为所有点的1%-2%。
问题二:
更局部高密度点的最短距离dis,算出来后,如何设定一个阈值,然后判断dis>
多少应该判别为高,最终才能实现db、dis都大的目标(该目标即为可选为中心点的特征) 。
Python实现
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
x=np.random.randint(1,50,20) # 1代表起点,50代表终点,20代表在1-50之间随机选择20个数
y=np.random.randn(20) #表示在-4,4之间随机选择20个数
plt.scatter(x,y,c='r',s=30)
plt.show()
#数据准备
data=np.array([x,y])
data=np.transpose(data)
lb=np.zeros(data.shape[0])
dataNew=np.c_[data,lb]
nrow=dataNew.shape[0]
disAll=np.zeros(20*nrow)
for i in range(nrow):
com=np.zeros(nrow)
temp=dataNew[i,0:2]
for j in range(nrow):
dist=np.sqrt(np.sum(np.square(temp-dataNew[j,0:2])))
com[j]=dist
disAll[i*20+j]=dist
result=np.sum([com<3])-1
dataNew[i,-1]=result
dataNew