K-Means聚类算法详解

声明

部分参考K-Means聚类算法原理

聚类算法

聚类算法是一种无监督学习算法,它主要用于将相似的样本自动归到一个类别中.
聚类算法与分类算法的区别:聚类算法是无监督学习,而分类是监督学习,在聚类算法中我们根据样本之间的相似度(或者说距离),将样本归到不同的类别中,对于不同的相似度我们得到的聚类结果可能是不通的.
K-Means是一种聚类算法,它实现起来比较简单,而且聚类的效果也不错,所以应用比较广泛.K-Means也有很多变体,如K-Means++,距离计算优化elkan K-Means算法和大数据情况下的优化Mini Batch K-Means算法。

K-Means原理

K-Means算法的思想很简单,对于给定的样本集,按照样本之间的距离大小,将样本集划分为K个簇.让簇内的点尽量的紧密连在一起,而让簇间的距离尽可能大.
如果用目标函数来表示,假设簇划分为(C1,C2,..Ck)(C_1,C_2,..C_k),则我们的目标是最小化平方误差函数:
E=i=1kxCixμi22 E = \sum\limits_{i=1}^k\sum\limits_{x \in C_i} ||x-\mu_i||_2^2
其中μi\mu_i是簇CiC_i的均值向量,也叫做质心,计算如下:
μi=1CixCix \mu_i = \frac{1}{|C_i|}\sum\limits_{x \in C_i}x
如果我们想直接求上式的最小值并不容易,这是一个NP难的问题,因此只能采用启发式的迭代方法。
其启发式方法可以用下图概括:(该图来自Andrew Ng machine learning):
{% asset_img 1.png %}
过程如下:
假设我们现在k=2k=2.在图(b)中我们首先随机选择两个k类所对应类别的质心.接近我们让每个点分别计算到两个质心的距离,并将该点的类别标注为距离最近的那个质心的类别,如图©.接着我们在每个类别内分别重新计算质心μi\mu_i,如图(d).在得到新的质心后,我们继续重复上述图©的过程,图(e).知道我们的每个类别的质心不发生变化,图(f).

K-Means的过程

k值的选择

对于k-means算法我们只有一个超参数,那就是如何选择k?
一般来说我们会根据自己的需求以及先验知识选择一个合适的k值,也可以通过交叉验证来选择一个合适的k值.
Andrew Ng介绍了一种方法叫做Elbow Method(肘方法).如下:
对于你]
个点的数据集,迭代计算k从1-n,每次聚类完成后计算每个点到其聚类质心的距离的平方和(也就是目标函数值),然后描述图像.可以想象平方和是逐渐减少的,知道k==n目标函数值为0.在这个目标函数值逐渐变小的过程中,可能会出现一个"肘"点,如下图:
{% asset_img 2.png %}
那么此时我们就认为这个"肘"点处是最优的k值.
但是其实大多数情况下,我们得到的都是如下图像,而并不是存在"肘"点的,所以这种方法可能就无法使用了.
{% asset_img 3.png %}

随机初始化

在确定了k的值之后,我们就需要选择k个质心,如何选择呢?
一般我们是随机选择k个样本,然后将质心的值设为这k个样本的值.但是由于我们使用的是启发式方法,所以初始值的选择对我们的聚类结果是有影响的,可能我们得到的就是局部最优质,而不是全局最优了,因此我们需要选择合适的k个质心.
通常情况下,我们的做法就是进行多次聚类(如100次),每次随机选择k个质心.每次聚类完成后计算目标函数J的值,从其中确定的最优的方案.(经验表明,在k=1~10,这种方法一般会找到全局最优解)

算法流程

输入是样本集D={x1,x2,...xm}D=\{x_1,x_2,...x_m\},聚类的簇数k,最大迭代次数N
输出是簇划分C={C1,C2,...Ck}C=\{C_1,C_2,...C_k\}
1.从数据集D中随机选择k个样本作为初始的k个质心向量:{μ1,μ2,...,μk}\{\mu_1,\mu_2,...,\mu_k\}
2.对于n=1,2,...Nn = 1,2,...N:
1)将簇划分C初始化为Ct=    t=1,2...kC_t = \varnothing \;\; t =1,2...k
2)对于i = 1,2,…m计算样本xix_i和各个质心向量μj\mu_j的距离:dij=xiμj22d_{ij} = ||x_i - \mu_j||_2^2,将xix_i标记为最小的为dijd_{ij}所对应的类别λi\lambda_i,此时更新Cλi=Cλi{xi}C_{\lambda_i} = C_{\lambda_i} \cup \{x_i\}
3)对于j = 1,2,…k 对CjC_j中所有的样本点重新计算新的质心μj=1CjxCjx\mu_j = \frac{1}{|C_j|}\sum\limits_{x \in C_j}x
如果所有的k个质心的向量都无变化则跳到3.
3.结束依次k-means聚类,计算目标函数JJ
4.重复1-3多次,找到最优的聚类

K-Means初始化优化K-Means++

在上节我们提到,k个初始化的质心的位置选择对最后的聚类结果和运行时间都有很大的影响,因此需要选择合适的k个质心。如果仅仅是完全随机的选择,有可能导致算法收敛很慢。K-Means++算法就是对K-Means随机初始化质心的方法的优化。
K-Means++的对于初始化质心的优化策略也很简单,如下:
1.从输入的数据集中随机选择一个点作为第一个聚类中心μ1\mu_1
2.对于数据集中的每一个点xix_i,计算它与已选择的聚类中心中最近聚类中心点的距离
D(xi)=arg  minxiμr22    r=1,2,...kselectedD(x_i) = arg\;min||x_i- \mu_r||_2^2\;\;r=1,2,...k_{selected}
3.选择一个新的数据点作为新的聚类中心,选择的原则是:D(x)D(x)较大的点,被选取作为聚类中心的概率较大
4.重复2,3直到选择出k个聚类质心
5.利用这k个质心作为初始化质心去运行标准的K-Means聚类方法

K-Means距离计算优化elkan K-Means

在传统的K-Means算法中,我们在每轮迭代时,要计算所有的样本点到所有的质心的距离,这样会比较的耗时。那么,对于距离的计算有没有能够简化的地方呢?elkan K-Means算法就是从这块入手加以改进。它的目标是减少不必要的距离的计算。那么哪些距离不需要计算呢?
elkan K-Means利用了两边之和大于等于第三边,以及两边之差小于第三边的三角形性质,来减少距离的计算。
第一种规律是对于一个样本点xx和两个质心μj1,μj2\mu_{j_1}, \mu_{j_2}.如果我们预先计算出了这两个质心之间的距离D(j1,j2)D(j_1,j_2),则如果计算发现2D(x,j1)D(j1,j2)2D(x,j_1) \leq D(j_1,j_2),我们立即就可以知道D(x,j1)D(x,j2)D(x,j_1) \leq D(x, j_2).此时我们不需要再计算D(x,j2)D(x, j_2).
第二种规律是对于一个样本点x和两个质心μj1,μj2\mu_{j_1}, \mu_{j_2}.我们可以得到D(x,j2)max{0,D(x,j1)D(j1,j2)}D(x,j_2) \geq max\{0, D(x,j_1) - D(j_1,j_2)\}.
利用上边的两个规律,elkan K-Means比起传统的K-Means迭代速度有很大的提高。但是如果我们的样本的特征是稀疏的,有缺失值的话,这个方法就不使用了,此时某些距离无法计算,则不能使用该算法。

大样本优化Mini Batch K-Means

在统的K-Means算法中,要计算所有的样本点到所有的质心的距离。如果样本量非常大,比如达到10万以上,特征有100以上,此时用传统的K-Means算法非常的耗时,就算加上elkan K-Means优化也依旧。在大数据时代,这样的场景越来越多。此时Mini Batch K-Means应运而生。

顾名思义,Mini Batch,也就是用样本集中的一部分的样本来做传统的K-Means,这样可以避免样本量太大时的计算难题,算法收敛速度大大加快。当然此时的代价就是我们的聚类的精确度也会有一些降低。一般来说这个降低的幅度在可以接受的范围之内。
 在Mini Batch K-Means中,我们会选择一个合适的批样本大小batch size,我们仅仅用batch size个样本来做K-Means聚类。那么这batch size个样本怎么来的?一般是通过无放回的随机采样得到的。
 为了增加算法的准确性,我们一般会多跑几次Mini Batch K-Means算法,用得到不同的随机采样集来得到聚类簇,选择其中最优的聚类簇。

K-Means小结

K-Means的主要优点有:

  1. 原理比较简单,实现也很容易,收敛速度快
  2. 聚类效果比较好,算法的可解释性强
  3. 主要的超参数就是k

缺点:

  1. k值的选取不好把握
  2. 对于不是凸的数据集比较难收敛
  3. 如果各隐含类别的数据不平衡,比如各隐含类别的数据量严重失衡,或者各隐含类别的方差不同,则聚类效果不佳
  4. 采用迭代方法,得到的结果只是局部最优
  5. 对噪音和异常点比较敏感
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章