前言

K-Means聚类算法的手写Python代码请移步:利用python实现K-Means聚类算法。同时本篇博客的PDF笔记请移步:K-Means聚类算法


K-Means算法理论

在聚类问题中,指定一个训练集{x(1),,x(m)} ,我们想要将数据分组为几个有凝聚力的“集群”。在这里,通常x(i)Rn ;但是和监督学习问题不同,K-Means聚类算法属于无监督学习算法,因此标签y(i) 没有给定。
首先,我们先定义距离函数:

(1)J(c,μ)=i=1mx(i)μc(i)2

其中, c(i)表示训练数据x(i) 对应的聚类标签, μ代表聚类质心数组。那么,距离函数计算的是每组训练数据x(i) 与其对应的聚类质心μc(i) 之间距离的平方和。因此K-Means算法的核心思想就是寻找合适的聚类质心,使得训练数据集尽可能靠近聚类质心。因此K-Means聚类算法的主要任务就是:
(2)μ=argminJJ(c,μ)=argminJi=1mx(i)μc(i)2

因此,我们定义如下最大似然函数:
(3)(c,μ)=j=1klogJ(c,μj)(4)=j=1klog[i=1mx(i)μc(i)2]1{c(i)==j}(5)=j=1k1{c(i)==j}logi=1mx(i)μc(i)2

那么我们对上述最大似然函数求导并令其为0有:
(6)μj=1{c(i)==j}2i=1m(x(i)μc(i))i=1mx(i)μc(i)2=0

那么我们可以求得:
(7)μj=i=1m1{c(i)==j}x(i)i=1m1{c(i)==j}

因此K-Means聚类算法的具体流程为:
(8)1. Initialize cluster centroids μ1,,μkRn randomly. (9)2. Repeat until convergence:{(10)For every i, set (11)c(i):= arg minjx(i)μj2(12)For each j, set(13)μj:=i=1m1{c(i)==j}x(i)i=1m1{c(i)==j}(14)} 

上述算法的内循环重复执行两个步骤:首先分配每个训练样例x(i) 到最近的聚类质心μj ,接着将每个聚类质心μj 移动到附近聚类点的平均值。具体地,K-Means聚类算法首先保持μ 不变,重复迭代更新c 重复来最小化 J,然后在保持c不变,更新参数μ 来最小化J 。因此, J一定单调递减,即J 一定收敛。理论上,K-Means聚类算法可能在几个不同的聚类质心之间振荡,即不同c 和(或)μ 可能得到相同的J 值。下图显示了K-Means的实验结果。图a表达了初始的数据集,假设k=2 。在图b中,我们随机选择了两个k类所对应的类别质心,即图中的红色质心和蓝色质心,然后求出样本集中所每组样本到这两个质心的距离,并标记每个样本的类别为和该样本距离最小的质心的类别,如图c所示,经过计算样本和红色质心和蓝色质心的距离,我们得到了所有样本点的第一轮迭代后的类别。此时我们对我们当前标记为红色和蓝色的点分别求其新的质心,如图d所示,新的红色质心和蓝色质心的位置已经发生了变动。图e和图f重复了我们在图c和图d的过程,即将每组样本的类别标记为距离最近的质心的类别并求新的质心。最终我们得到的两个类别如图f。
斯坦福机器学习笔记(六)——K-Means聚类算法
距离函数J 是非凸函数,因此在函数J 上的坐标下降不能保证收敛到全局最小值。换句话说,K-Means聚类算法可能陷入局部最优解。如果担心陷入局部最小值,常见手段一个常见的事情就是多次运行K-Means聚类算法,每次运行采用不同聚类质心μ 。然后,在所有不同聚类中,选择J 值最小对应的聚类结果。


缺点与改进

根据自己实验的结果来看,虽然K-Means算法理论推导简单,代码也容易实现,但是K-Means聚类算法也存在如下缺点:

  1. 对于离群点和孤立点非常敏感。
  2. 由于K-Means聚类算法属于无监督学习算法,没有训练样本分类输入,因此,K值的选择非常重要。
  3. 初始聚类质心的选择也极大影响聚类结果。
  4. 由于距离函数是训练集与对应聚类质心的之间差值的二范式的平方和,那么最终聚类形成的大部分是球状簇。

针对上述缺点,对应的改进策略如下:

  1. 针对缺点1,首先利用离群点检测的LOF算法检测出离群点,去除离群点后再聚类,可以减少离群点和孤立点对于聚类效果 的影响。
  2. 针对缺点2和3,可以使用K-Means++或者二分K-Means算法来自适应随机初始化聚类质心的位置与个数。
  3. 针对缺点4,通过寻找更好度量距离的函数加以改进。或者采用基于密度的聚类算法如DESCAN算法。

相关文章: