K-Means是无监督聚类算法,实现简单且效果不错。只看名字容易与可以分类回归的K-近邻搞混。
原理
它将样本按照距离的大小,将其划分为K个簇。簇内的点尽量紧密,簇间距离越大越好。
假设簇有k个,分别为,为簇Ci的均值向量,称为质心或者簇心,表示为:
于是我们的目标可以设为,使所有簇内数据到它对应的簇心的距离最小:
求E的最小值是一个NP难问题,于是采用迭代方法如下图,红点和蓝点分别对应两个簇的簇心,随着簇心的迭代更新,每个簇对应的数据在发生改变,直到最后收敛
算法流程
K-means的效果非常依赖选取的K值,这也是算法唯一需要进行调参的地方。如果没有合适的先验,一般来说可以通过交叉验证得到一个合适的k值。
质心的位置选择也很重要,初始化k个质心,质心的距离不要太近。
预处理:数据归一化和离群点处理。
均值和方差大的维度将对数据的聚类结果产生决定性的影响,所以未做归一化处理和统一单位的数据是无法直接参与运算和比较的。同时离群点或者少量的噪声数据就会对均值产生较大的影响,导致中心偏移。
(1)从数据集中随机选择k个样本作为初始的k个质心向量:
(2)对每个数据xi,分别计算它与每个质心的距离,找到最小的距离对应的质心,将这个数据划入对应的簇
(3)对于上一步得到的所有簇,重新计算新的质心
(4)如果所有质心向量都没有发生变化,则进行输出,否则退回第二步
算法优化
K-means的收敛快慢和聚类结果主要由初始的质心位置决定。由此提出了K-means++,目的是尽可能地分散各个初始点。通过初始一个点,然后在剩余点中找到与它距离尽可能大的点,距离越大被选为初始点的概率越大。重复步骤直到找满规定数量的质心。然后利用这k个质心来运行标准的K-Means算法。
ISODATA算法,当遇到高纬度、海量的数据集时,往往很难估计K的大小。ISODATA算法很直观,当属于某个类别的样本数过少时,把该类别去除;当某个类别样本过多、分散程度较大时,分为两个子类别。
同时也无法很好地解决数据簇分布差别较大的情况(比如一类是另一类样本数量的100倍)。
K-means算法的计算复杂度其中之一主要体现在计算距离上。而elkan K-means通过三角形两边之和大于第三边这个公理,可以有效减少计算距离的次数。我们可以先算出两个质心之间的距离a,如果数据点与其中一个质心的距离的两倍小于a,则说明数据点到另一个质心的距离一定大于这边的距离,就可以省略了计算另外一条边的步骤。
K-means算法的复杂度也体现数据点的数量和特征的维度数量上(与计算距离本质相同),这可能导致运算时间过长。解决的办法是Mini Batch K-means,选择一个合适的batch size,仅仅通过这个batch来做K-means。一般通过无放回的随机采样得到这样的batch。一般会多跑几次Mini Batch K-means,用得到不同的随机采样集来得到聚类簇,选择最优的聚类簇。
K均值聚类在大数据集上,计算复杂度O(NKt)接近于线性,其中N是样本数量,K是簇的数目,t是迭代的轮数。
小结
优点:
(1)原理简单,实现容易,收敛快
(2)聚类效果较优
(3)算法可解释性比较强
(4)仅需调K值这个超参数
缺点:
(1)K值不好把握,一般只能基于经验和多次实验,比如可以尝试不同的K值,并将不同K值对应的损失函数画成折线
手肘法认为拐点就是K的最佳值,如上图中K=3。
(2)对于不是凸的数据集难以收敛
(3)数据类别不均衡时,聚类效果不佳
(4)可能得到局部最优
(5)对噪音和异常点较敏感