【机器学习】K-Means聚类算法
K-Means简介
K-Means算法是一种无监督的聚类算法,由于算法实现相对简单,且聚类效果也不错,因此其被广泛应用于各个领域。此外,K-Means算法还有许多相关的变体算法,本文首先介绍传统的K-Means算法,然后在其基础上讲述K-Means的变体算法,包括K-Means++, K-Modes以及K-Prototype等等,本文将会简单介绍这几种变体算法。
K-Means原理
K-Means算法原理非常简单,对于给定的样本集,分别计算样本与样本之间的距离,根据样本的远近程度将样本集划分为
k
k
k个簇。K-Means算法的核心思想就是令处于同一簇的样本之间的距离都相对较近,此外,还要远离其他簇的样本,即让处于不同簇的样本之间的距离相对较远。
给定样本集
D
=
{
x
1
,
x
2
,
…
,
x
m
}
D=\{x_1,x_2,\ldots,x_m\}
D={x1,x2,…,xm},K-Means算法针对聚类所得到的簇划分
C
=
{
C
1
,
C
2
,
…
,
C
k
}
C=\{C_1,C_2,\ldots,C_k\}
C={C1,C2,…,Ck}最小化平方误差
E
=
∑
i
=
1
k
∑
x
∈
C
i
∥
x
−
μ
i
∥
2
2
E=\sum_{i=1}^k \sum_{x\in C_i} \left \| x-\mu_i \right \|_2^2
E=i=1∑kx∈Ci∑∥x−μi∥22其中,
μ
i
=
1
∣
C
i
∣
∑
x
∈
C
i
x
\mu_i=\frac{1}{|C_i|}\sum_{x\in C_i} x
μi=∣Ci∣1∑x∈Cix是簇
C
i
C_i
Ci 均值向量。直观来看
E
E
E在一定程度上表示样本围绕簇均值向量的紧密程度,其中
E
E
E的值越小说明簇内样本越紧密。
为了求出
E
E
E的最小值,需要初始化后迭代更新求解,其具体算法过程见下一节。
K-Means算法过程
在上一节通过对K-Means算法原理的介绍,接下来将介绍其算法实现的过程。传统的K-Means算法过程如下所示:
输入: 样本集
D
=
{
x
1
,
x
2
,
…
,
x
m
}
D=\{x_1,x_2,\ldots,x_m\}
D={x1,x2,…,xm}
聚类簇的数目
k
k
k
输出: 簇划分 C = { C 1 , C 2 , … , C k } C=\{C_1,C_2,\ldots,C_k\} C={C1,C2,…,Ck}
过程:
- 从 D D D中随机选择 k k k个样本作为初始的均值向量 { μ 1 , μ 2 , … , μ k } \{\mu_1,\mu_2,\ldots,\mu_k\} {μ1,μ2,…,μk}
- 对于
n
=
1
,
2
,
…
,
N
n=1,2,\ldots,N
n=1,2,…,N
- 令 C t = ∅ ( 1 ≤ t ≤ k ) C_t=\varnothing(1\leq t \leq k) Ct=∅(1≤t≤k)
- 对于 i = 1 , 2 , … , m i=1,2,\ldots,m i=1,2,…,m计算样本 x i x_i xi和各个质心向量 μ j ( j = 1 , 2 , … , k ) \mu_j(j=1,2,\ldots,k) μj(j=1,2,…,k)的距离 d i j = ∥ x i − μ j ∥ 2 d_{ij}=\left\| x_i-\mu_j \right \|_2 dij=∥xi−μj∥2
- 根据最近的均值向量确定 x i x_i xi簇标记 λ i = arg min i ∈ { 1 , 2 , … , k } d i j \lambda_i=\arg\min_{i\in\{1,2,\ldots,k\}}d_{ij} λi=argmini∈{1,2,…,k}dij。将样本 x i x_i xi划入对应的簇: C λ j = C λ j ∪ x i C_{\lambda_j}=C_{\lambda_j}\cup{x_i} Cλj=Cλj∪xi
- 对于 j = 1 , 2 , … , k j=1,2,\ldots,k j=1,2,…,k,对 C j C_j Cj中所有的样本点重新计算新的均值向量 μ j = 1 ∣ C j ∣ ∑ x ∈ C j x \mu_j=\frac{1}{|C_j|}\sum_{x\in C_j} x μj=∣Cj∣1∑x∈Cjx
- 如果所有的 k k k个质心向量都没有发生变化,则跳出循环
- 输出簇划分
C
=
{
C
1
,
C
2
,
…
,
C
k
}
C=\{C_1,C_2,\ldots,C_k\}
C={C1,C2,…,Ck}
K-Means的变体算法
通过K-Means聚类过程可以看到其操作非常简单,但是其也存在一定的局限性。为了可以更好的处理不同形式的聚类,各种变体算法一一被提出。
K-Means++
从K-Means聚类过程可以看到初始化的
k
k
k个均值向量选择对聚类结果和算法迭代次数都会产生很大的影响,因此如果可以设计一种策略来更好地初始化
k
k
k个均值向量,用以代替传统的随机初始化,那么对算法将会有极大的提升。
K-Means++算法就是对传统K-Means算法中随机初始化均值向量进行了改进优化。K-Means++中初始化均值向量策略具体如下:
- 对于给定的样本集 D D D,从中随机选择一个样本作为第一个聚类中心 μ 1 \mu_1 μ1
- 对于数据集中的每一个点 x i x_i xi,计算 x i x_i xi与已选择的聚类中心中最近的聚类中心的距离 d i s t ( x i ) = arg min ∣ ∣ x i − μ r ∣ ∣ 2 2 dist(x_i)=\arg\min||x_i−\mu_r||_2^2 dist(xi)=argmin∣∣xi−μr∣∣22
- 选择一个新的数据点作为新的聚类中心,选择的准则是:对应 d i s t ( x ) dist(x) dist(x)较大的点 x x x,被选取作为聚类中心的概率较大,其被选中的概率为 P ( x ) = d i s t ( x ) 2 ∑ x ∈ D d i s t ( x ) 2 P(x)=\frac{dist(x)^2}{\sum_{x\in D} {dist(x)^2}} P(x)=∑x∈Ddist(x)2dist(x)2
- 重复第2步直到选择出 k k k个聚类质心
- 利用这 k k k个均值向量作为传统的K-Means算法的初始化聚类中心
K-Means++算法虽然在初始化聚类中心时消耗了多余的时间,但是其可以加速K-Means的收敛,相对而言,还是降低了总体的计算的时间。
K-Modes
传统的K-Means算法往往只能适用于对数值型属性的样本集进行聚类,但是如果样本集中的样本属性是分类型的,那么原本K-Means算法中计算簇的均值向量以及样本之间的欧式距离就无法有效地实现。于是,变种算法K-Modes诞生了,其可以适用于分类型属性的样本集。
给定一个样本集
D
D
D,其中
D
=
{
x
1
,
x
2
,
…
,
x
n
}
D=\{x_1,x_2,\ldots,x_n\}
D={x1,x2,…,xn},对于任一样本
x
t
x_t
xt,都有
m
m
m个离散属性,即
x
t
=
[
x
t
1
,
x
t
2
,
…
,
x
t
m
]
x_t=[x_t^1,x_t^2,\ldots,x_t^m]
xt=[xt1,xt2,…,xtm]。
- 随机确定 k k k个聚类中心 C 1 , C 2 , … , C k C_1,C_2,\ldots,C_k C1,C2,…,Ck
- 对于样本 x i ( i = 1 , 2 , … , N ) x_i(i=1,2,\ldots,N) xi(i=1,2,…,N),分别计算其与 k k k个聚类中心的距离 (这里的距离表示两个样本中,其中不同属性值的个数。例如, x i = [ 1 , 0 , 2 , 3 ] x_i=[1,0,2,3] xi=[1,0,2,3], C 1 = [ 1 , 1 , 2 , 9 ] C_1=[1,1,2,9] C1=[1,1,2,9],其第二、第四属性不同,即 x i x_i xi到 C 1 C_1 C1的距离为2)
- 将 x i x_i xi划分到与聚类中心距离最小的簇,在全部的样本都被划分完毕之后,重新确定簇中心,与传统K-Means不同的是,聚类中心 C i C_i Ci中对应每一个属性都更新为所在簇中样本对应属性的众数。
- 重复步骤2和3,直到总距离(各个簇中样本与对应的聚类中心的距离和)不再降低,返回最后的聚类结果
K-Modes算法与K-Means算法总体上是类似的,其算法也是相对比较简单,容易实现,只是在样本间距离的计算和聚类中心的更新这两方面有着一定的差别。
K-Prototype
K-Means算法只能应用于全是数值型属性的样本集,而K-Modes算法只能应用于全是分类型属性的样本集,然而在实际问题中,我们的样本集中的样本往往是既存在数值型属性,又存在分类型属性。
为了处理混合属性聚类的样本集,研究人员提出了K-Prototype,其结合了K-Means算法和K-Modes算法两者的思想,并且针对混合属性提出了描述样本簇的原型和混合属性样本之间的相异度。
对于K-Prototype,需要对样本集的定义稍作修改:
D
=
{
x
1
,
x
2
,
…
,
x
n
}
D=\{x_1,x_2,\ldots,x_n\}
D={x1,x2,…,xn},其中包含
n
n
n个样本
对于
x
i
x_i
xi的
m
m
m个属性,有
x
i
=
[
x
i
,
1
r
,
x
i
,
2
r
,
…
,
x
i
,
p
r
,
x
i
,
p
+
1
c
,
x
i
,
p
+
2
c
,
…
,
x
i
,
m
c
]
x_i=[x_{i,1}^r,x_{i,2}^r,\ldots,x_{i,p}^r,x_{i,p+1}^c,x_{i,p+2}^c,\ldots,x_{i,m}^c]
xi=[xi,1r,xi,2r,…,xi,pr,xi,p+1c,xi,p+2c,…,xi,mc]。
其中
r
r
r代表数值型属性,
c
c
c代表类别型属性,并且定义前
p
p
p个属性为数值型属性,后
m
−
p
m-p
m−p个属性为分类型属性。
K-Prototype算法提出了混合属性簇的原型,我们可以理解原型就是数值属性聚类的聚类中心。混合属性中存在数值型属性和分类型属性,其中对于数值型属性使用属性对应取值的均值,对于分类型属性是在分类型属性中选取属性值众数。
K-Prototype的相异度: 数值型属性选用欧氏距离,分类型属性选用汉明距离,两者分别计算再相加,就是K-Prototype的相异度距离。汉明距离是指两个相同维度的向量中对应属性值不同的个数。例如,
[
1
,
1
,
1
,
1
]
[1,1,1,1]
[1,1,1,1]和
[
1
,
0
,
0
,
1
]
[1,0,0,1]
[1,0,0,1]这两者的汉明距离是2。
综上可以计算样本与原型(聚类中心)的相异度距离为:
d
(
x
i
,
Q
c
)
=
∑
j
=
1
p
(
x
i
j
r
−
q
c
j
r
)
2
+
μ
l
∑
j
=
p
+
1
m
δ
(
x
i
j
c
−
q
c
j
c
)
d(x_i,Q_c)=\sum_{j=1}^p{(x_{ij}^r-q_{cj}^r)^2}+\mu_l \sum_{j=p+1}^m{\delta(x_{ij}^c-q_{cj}^c)}
d(xi,Qc)=j=1∑p(xijr−qcjr)2+μlj=p+1∑mδ(xijc−qcjc)其中,在等号右侧部分,左边部分表示数值型属性的距离计算,右边部分表示分类型属性的距离计算。
Q
c
Q_c
Qc表示某一簇的原型(聚类中心),
q
c
j
q_{cj}
qcj表示对应的原型中第
j
j
j个属性,
μ
l
\mu_l
μl表示分类属性的权重因子,
δ
(
⋅
)
\delta( \cdot )
δ(⋅)代表汉明距离的计算。
同时K-Prototype还定义了一个目标函数,随着算法不断迭代,直到目标函数值不变。
E
=
∑
c
=
1
k
∑
i
=
1
n
y
i
c
d
(
x
i
,
Q
c
)
E=\sum_{c=1}^k\sum_{i=1}^ny_{ic}d(x_i,Q_c)
E=c=1∑ki=1∑nyicd(xi,Qc)其中
y
i
c
y_{ic}
yic表示在簇
c
c
c中有没有这个样本,如果有的话,
y
i
c
=
1
y_{ic}=1
yic=1,没有的话,
y
i
c
=
0
y_{ic}=0
yic=0。
有了目标函数后,就可以得出K-Prototype算法的算法过程。算法的步骤是:
- 对于给定的样本集 D D D,从中随机选取 k k k个样本作为初始的 k k k个簇的原型
- 对于数据集中的每一个样本 x i x_i xi,计算 x i x_i xi与 k k k个簇原型的相异度距离
- 将该样本分配到相异度距离最小的对应簇中,分配完毕后,更新簇的原型
- 重复步骤2和步骤3,直到目标函数直到目标函数值不再变化,聚类结束
如有错误,欢迎批评指出,谢谢!