k均值算法
k-means聚类又称k均值聚类。
给定N个数据点 {xn→∈RM,n=1,⋯,N} ,M是数据点的维度。现在希望把数据点聚类成K个簇。
算法:
(1)初始化:在给定的N个样本中随机选择K个作为初始聚类中心
(2)更新划分:对每个数据点,计算其到各个聚类中心的距离,并把它归到距离最近的类
(3)更新聚类中心:计算各个类簇中数据点在每个维度上的均值,将求得的均值点作为新的聚类中心
(4)判断是否收敛:如果聚类中心的改变不超过预先设置的阈值或者损失的改变不超过设定的阈值,那么认为收敛;否则,转到步骤(2)
从优化角度看待k均值算法
给定N个数据点 {xn→∈RM,n=1,⋯,N} ,M是数据点的维度。现在希望根据空间位置把数据点聚类成K个簇,使得损失函数
J(C,U)=ΣnΣkcnkDistance(xn→−uk→)
最小。其中,聚类矩阵
C∈RN∗K ,(n,k)位置上的元素
cnk∈{0,1} 表示数据点
xn→ 是否属于类k,
cnk=0 表示数据点
xn 不属于k类;
cnk=1 表示数据点
xn 属于k类。那么矩阵
C 的每一行有且仅有一个元素为0。聚类中心矩阵
U∈RK∗M ,第k行向量
uk→∈RM 表示第k个类的聚类中心。
代价函数也可以从无监督的目的出发来考虑。无监督学习是学习数据的组织方式,用更简单的方式来描述数据(比如用更低维的向量),在聚类问题中就可以看成用聚类中心来描述每个实例。但是描述的简化必然会带来信息的丢失,这里用距离来表示丢失的信息。
最常用距离是 L2 距离,那么现在代价函数可以写成:
J(C,U)=ΣnΣkcnk||xn→−uk→||2
固定聚类中心矩阵
U ,想一想此时聚类矩阵
C 应该是什么样才能使得损失函数最小呢?不难想到,当每个数据点
xn 属于最近的类别时,代价函数才最小。具体做法就是对每个数据点
xn 计算和各聚类中心之间的距离,将
xn 划分到距离最近的类别
k∗ ,也就是把对应的
cnk∗ 设为1,其他的
cnk 设为0。此时损失值为
J∗ 。不难验证,
J∗ 是最小的损失值。假设
xn 属于
k− 类,对应的损失值为
J− 。
J∗−J−=||xn→−uk∗→||2−||xn→−uk−→||2≤0
所以
J∗ 是最小损失。于是
算法的第二步骤——更新划分必然会使得损失变小。
固定聚类矩阵
C ,那么聚类中心
U 应该是什么样才能使得损失函数最小呢?可以通过求导得出:
J′ukm=2Σncnk(xnm−ukm)=0
那么:
ukm=ΣncnkxnmΣncnk
也就是聚类中心应该取成该类所有数据点的均值,而是是各个维度上的均值。这时每个类内的实例都由更好的点来表示,于是
算法的第三步——更新聚类中心不会增加损失。
总之,k均值算法会使得代价单调递减地变化。那么是否会收敛呢?以直观的方式在离散空间中进行解释:划分数是有限的(实例点数量有限,类别数有限),每个划分都有一个损失。那么从任意一个划分出发,k均值算法总是跳到损失不会增加的划分上去,而且永远不会回到已经经过的划分,所以必然会收敛到某一划分停止。但是如果初始化没做好,可能会导致陷入局部最优的划分。
k-means算法属于优化算法中的爬山法。
优缺点
优点:
缺点:
初始值敏感:当初始化的中心点不同时,结果也不同;而且可能收敛到局部最优。
怎么避免陷入局部最优呢?
可以在选择初始点的时候选择尽可能远的点作为中心点。