写了一个系列的机器学习博客了,为了圆满,我转载了这篇基于spark的聚类算法,算法思想是我们主要参考的内容,对于是park代码不懂也没关系,如果你是纯粹学习机器学习人儿。
文章转载自:k-means、k-means++以及k-means||算法分析
本文会介绍一般的k-means算法、k-means++算法以及基于k-means++算法的k-means||算法。在spark ml,已经实现了k-means算法以及k-means||算法。 本文首先会介绍这三个算法的原理,然后在了解原理的基础上分析spark中的实现代码。
1.K-means算法原理分析
k-means算法是聚类分析中使用最广泛的算法之一。它把nnn个对象根据它们的属性分为kkk个聚类以便使得所获得的聚类满足:同一聚类中的对象相似度较高;而不同聚类中的对象相似度较小。
k-means算法的基本过程如下所示:
1)任意选择kkk个初始中心c1,c2,...,ckc_{1},c_{2},...,c_{k}c1,c2,...,ck 。
2)计算XXX中的每个对象与这些中心对象的距离;并根据最小距离重新对相应对象进行划分;
3)重新计算每个中心对象CiC_{i}Ci的值:Ci:ci=1ci∑x∈CixC_i :c_i=\frac{1}{c_i}\sum_{x \in C_i}xCi:ci=ci1x∈Ci∑x
4)计算标准测度函数,当满足一定条件,如函数收敛时,则算法终止;如果条件不满足则重复步骤(2),(3)。
1.1K-means算法的缺点
k-means算法虽然简单快速,但是存在下面的缺点:
聚类中心的个数kkk需要事先给定,但在实际中kkk值的选定是非常困难的,很多时候我们并不知道给定的数据集应该分成多少个类别才最合适。
k-means算法需要随机地确定初始聚类中心,不同的初始聚类中心可能导致完全不同的聚类结果。
第一个缺陷我们很难在k-means算法以及其改进算法中解决,但是我们可以通过k-means++算法来解决第二个缺陷。
2.k-means++算法原理分析
k-means++算法选择初始聚类中心的基本原则是:初始的聚类中心之间的相互距离要尽可能的远。它选择初始聚类中心的步骤是:
1)从输入的数据点集合中随机选择一个点作为第一个聚类中心c1c_{1}c1 ;
2)对于数据集中的每一个点x,计算它与最近聚类中心(指已选择的聚类中心)的距离D(x)D(x)D(x),并根据概率选择新的聚类中心cic_{i}ci ;
3)重复过程(2)直到找到kkk个聚类中心。
第(2)步中,依次计算每个数据点与最近的种子点(聚类中心)的距离,依次得到D(1),D(2),⋯,D(n)D(1),D(2),\cdots,D(n)D(1),D(2),⋯,D(n)构成的集合DDD,其中nnn表示数据集的大小。在DDD中,为了避免噪声,不能直接选取值最大的元素,应该选择值较大的元素,然后将其对应的数据点作为种子点。 如何选择值较大的元素呢,下面是spark中实现的思路。
求所有的距离和Sum(D(x))Sum(D(x))Sum(D(x))
取一个随机值,用权重的方式来取计算下一个“种子点”。这个算法的实现是,先用Sum(D(x)Sum(D(x)Sum(D(x))乘以随机值RandomRandomRandom得到值rrr,然后用currSum+=D(x)currSum += D(x)currSum+=D(x),直到其currSum>rcurrSum > rcurrSum>r,此时的点就是下一个“种子点”。
为什么用这样的方式呢?我们换一种比较好理解的方式来说明。把集合DDD中的每个元素D(x)D(x)D(x)想象为一根线L(x)L(x)L(x),线的长度就是元素的值。将这些线依次按照L(1),L(2),⋯,L(n)L(1),L(2),\cdots ,L(n)L(1),L(2),⋯,L(n)的顺序连接起来,组成长线LLL。L(1),L(2),⋯,L(n)L(1),L(2),\cdots ,L(n)L(1),L(2),⋯,L(n)称为LLL的子线。 根据概率的相关知识,如果我们在LLL上随机选择一个点,那么这个点所在的子线很有可能是比较长的子线,而这个子线对应的数据点就可以作为种子点。
2.1K-means++算法的缺点
虽然k-means++算法可以确定地初始化聚类中心,但是从可扩展性来看,它存在一个缺点,那就是它内在的有序性特性:下一个中心点的选择依赖于已经选择的中心点。 针对这种缺陷,k-means||算法提供了解决方法。
3.K-means II算法原理分析
k-means||算法是在k-means++算法的基础上做的改进,和k-means++算法不同的是,它采用了一个采样因子lll,并且l=A(k)l=A(k)l=A(k),在