上一篇文章中,我在最后有说到,K-means算法由于初始“聚类中心”点是随机选取的,因此最终求得的簇的划分与随机选取的“聚类中心”有关,也就是说,可能会造成多种 k 个簇的划分情况。这是因为K-means算法收敛到了局部最小值,而非全局最小值。
为了改进这一缺点,我们可以对算法加以改进。下面,我将为大家介绍两种改进的算法——K-means++ 和二分K-means。
一)K-means++
K-means++这个算法只是对初始聚类中心的选择有改进而已,其他步骤和K-means是一样的。初始聚类中心选取的基本思路就是,初始的聚类中心之间的相互距离要尽可能的远。
算法步骤如下:
步骤一:随机选取一个样本点作为第一个聚类中心 C1;
步骤二:计算每个样本与当前最近一个聚类中心的距离,用 D(x)表示;这个值越大,表示被选取作为聚类中心的概率较大。
概率P(x)公式如下:
步骤三:用轮盘法选出下一个聚类中心。
步骤四:重复步骤二和步骤三,直到选出 k 个聚类中心[C1,C2…,Ck]。
选出初始点后,就继续使用标准的 k-means 算法了。
通过k-means方法, 能显著的改善分类结果的最终误差。
举例:如下图所示,开始选择了A点为第一个聚类中心点。
那么其他样本与当前已有聚类中心最短距离 D(x)以及被选取作为下一个聚类中心的概率P(x);
用轮盘法选择出第二个聚类中心,大致过程是这样:随机产生出一个0~1之间的随机数,判断它属于哪个区间,那么该区间对应的序号就是被选择出来的第二个聚类中心了。
此时,B的区间为[0,0.022),A的区间为[0.022,0.044),C的区间为[0.044,0.444),D的区间为[0.444,1)
我们可以看到P(D)+P(E)=0.956。
D,E两个点被选为第二个聚类中心的概率最大。通过图,可以观察到D,E也是距离第一个初始聚类中心A点最远的两个点。
以上就是整个K-means++算法原理以及过程。
说到这里,我们在回过头来,了解下sklearn中的Kmeans方法中的参数。
sklearn.cluster.KMeans(n_clusters=8,
init='k-means++',
n_init=10,
max_iter=300,
tol=0.0001,
precompute_distances='auto',
verbose=0,
random_state=None,
copy_x=True,
n_jobs=1,
algorithm='auto'
)
n_clusters:簇的个数,默认为8。
init: 初始簇中心的获取方法,参数为’k-means++’,‘random’或一个numpy的矩阵,默认为’k-means++’。
n_init: 获取初始簇中心的更迭次数,为了弥补初始质心的影响,算法默认会初始10次质心,实现算法,然后返回最好的结果。
max_iter: 每一次k-means算法迭代的最大次数,默认为300。
n_jobs: 进程个数。默认为-1。
若值为 -1,则用所有的CPU进行运算。
若值为1,则不进行并行运算,这样的话方便调试。
若值小于-1,则用到的CPU数为(n_cpus + 1 + n_jobs)。因此如果 n_jobs值为-2,则用到的CPU数为总CPU数减1。
注意,并行计算只是针对与不同初始值的计算。比如n_init=10,n_jobs=-1,
假设服务器上面有CPU可以开40个进程,最终也只会开10个进程
以上几个参数,是模型中较为重要的参数。其他的参数,可以参考这篇博客
https://blog.csdn.net/fengzhizi76506/article/details/79640997
通过对参数的分析,我们会发现sklearn.cluster.KMeans方法中,参数init默认为‘k-means++’,也就是说初始簇中心的获取方法默认为是‘K-means++’方法了。所以大家在调用这个方法的时候,不用担心初始聚类中心的选取问题了。
在这里,我不得不说,python的第三方库真的太强大了。
二)二分K-means
其原理如下:
步骤一:将所有点作为一个簇,然后将该簇一分为二。
步骤二:选择下一个簇继续进行划分。选择哪一个簇进行划分取决于:该簇的SSE(误差平方和)的值最大。而划分的方法还是K-means的方法,只是簇的个数k=2。
误差平方和的公式如下所示,其中Wi表示权重值,y^表示该簇所有点的平均值。
步骤三:通过不断重复步骤二,直到达到需要的簇数量。
注意:之所以取SSE(误差平方和)的值最大的簇,进行划分,是因为聚类的误差平方和能够衡量聚类性能,该值越小,表示数据点越接近于它们的质心,聚类效果就越好。该值越大,表示数据点距离它们的质心越远,聚类效果就越差,所以就需要进行划分。
二分k-means通过这种逐渐分裂的方式选择初始聚类中心,可以有效的避免了k-means的局部最优解问题了。
二分K-means算法在sklearn库中,并没有接口,所以,如果你要使用这种算法,需要自己编写源码,可以参考以下博客:
https://blog.csdn.net/qq_36523839/article/details/82118090