我在MATLAB中编写了一个k-Means clustering算法,我想我会针对kmeans(X,k)
内置的MATLAB进行尝试。
然而,对于非常简单的四簇设置(见图),MATLAB kMeans并不总是收敛到最优解(左),而是(右)。
我写的那个并不总是这样做,但是内置函数不应该能够解决这么简单的问题,总能找到最佳解决方案吗?
答案 0 :(得分:11)
正如@Alexandre C.所解释的那样,K-means算法取决于初始聚类质心位置,并且无法保证它会收敛到最优解。
您可以做的最好的事情是使用随机起点重复实验几次。
MATLAB的实现提供了这样一个选项:replicates
,它重复聚类N次,并选择具有最低总簇内点到质心距离的聚类。
您还可以使用start
选项控制如何选择初始质心。
此外,MATLAB提供了多种距离测量(Euclidean,Manhattan,Cosine等)的选择。一个简洁的选项emptyaction
允许您控制在迭代期间集群丢失其所有已分配成员时发生的情况。
但真正的优势在于它采用了两阶段算法:通常的分配 - 重新计算迭代,然后是在线更新阶段。请务必阅读documentation page的算法部分以获取更多信息。
答案 1 :(得分:4)
k-means算法对集群中心的初始猜测非常敏感。您是否尝试使用相同初始质量中心的两个代码?
算法很简单,我怀疑你的实现和Matlab之间有很多差异。
答案 2 :(得分:3)
我不认为这是一个简单的问题。:)事实上,维基百科关于“k-means聚类”的文章给出了计算复杂性的相当悲观的画面。
如果你想摆脱随机重启(依赖于初始猜测),折衷就是“全局k均值”算法;论文和matlab代码可以在这里找到:http://lear.inrialpes.fr/~verbeek/software.php
答案 3 :(得分:2)
你可能经常会对任何特定的“k-means算法”(即Lloyd算法)出现的解决方案感到失望。那是因为Lloyd的算法经常陷入糟糕的局部最小值。
幸运的是,劳埃德只是解决k-means的一种方式。并且有一种方法几乎总能找到更好的局部最小值。诀窍是一次更新一个数据点的群集分配。您可以通过保持分配给每个均值的点数n
来有效地执行此操作。因此,您可以在删除点m
后重新计算群集均值x
,如下所示:
m_new = (n * m - x) / (n - 1)
使用以下内容将x
添加到群集均值m
:
m_new = (n * m + x) / (n + 1)
当然因为它无法进行矢量化,所以在MATLAB中运行会有点痛苦,但在其他语言中也不会太糟糕。
如果您真的热衷于获得最佳的本地最小值,并且不介意使用基于示例的群集,则应该查看affinity propagation。 MATLAB实现可在Frey lab affinity propagation page上找到。
答案 4 :(得分:2)
虽然K-Means++在单次运行中无法解决问题,但在运行N次时往往会提供更好的结果(与运行原始K-Means算法N次相比)。