为啥我的 k-means 收敛条件给出的结果与 sklearn 不同?
Posted
技术标签:
【中文标题】为啥我的 k-means 收敛条件给出的结果与 sklearn 不同?【英文标题】:Why does my k-means convergence condition give different results than sklearn?为什么我的 k-means 收敛条件给出的结果与 sklearn 不同? 【发布时间】:2022-01-15 00:54:56 【问题描述】:我编写了一个函数,它使用 data
、K
和 n
(迭代次数)作为输入来执行 k-means 聚类。我可以设置n=100
,以便该函数计算欧几里得距离、分配集群并在完成之前计算新的集群质心 100 次。当将此结果与 sklearn 的 KMeans(使用相同的 data
和 K
)进行比较时,我得到了相同的质心。
我希望我的函数只运行到收敛(以避免不必要的迭代),因此它不再需要迭代次数作为输入。为了实现这一点,我使用了一个 while 循环,而在我的原始函数中,我使用了一个迭代 n
次的 for 循环。我的代码的一般步骤如下:
-
随机创建质心并存储在变量
centroids
中。
计算每个数据点与上面生成的质心的欧几里得距离,并存储在变量EucDist
中。
根据来自centroids
的EucDist
为每个数据点分配cluster
。
根据集群索引cluster
重新组合数据点。然后计算分离集群的平均值并将其分配为新的centroids
。
然后循环步骤 2-4 直到收敛。下面是我的 while 循环的代码(我知道这里可能有一些不必要的代码,但是我不确定问题出在哪里,如果它甚至是一个问题)。
while True:
previouscentroids = centroids
EucDist = np.array([]).reshape(a, 0)
for k in range(K):
Dist = np.sqrt(np.sum((data - centroids[:, k]) ** 2, axis = 1))
EucDist = np.c_[EucDist, Dist]
cluster = np.argmin(EucDist, axis = 1) + 1
points =
for k in range(K):
points[k + 1] = np.array([]).reshape(2, 0)
for i in range(a):
points[cluster[i]] = np.c_[points[cluster[i]], data[i]]
for k in range(K):
points[k + 1] = points[k + 1].T
for k in range(K):
centroids[:, k] = np.mean(points[k + 1], axis = 0)
if np.all(previouscentroids - centroids == 0):
break
我对此的理解是,一旦 centroids
与迭代开始时 (previouscentroids
) 相同,循环就会中断,我将拥有最后的集群。我假设这与我的原始函数产生的质心相同(与 sklearn 相同),因为我认为一旦达到收敛,无论你迭代循环多少次,集群都将保持不变(因此将质心)。下面是我原始函数中的 for 循环进行比较(几乎没有改变)。
for i in range(n):
EucDist = np.array([]).reshape(a, 0)
for k in range(K):
Dist = np.sqrt(np.sum((data - centroids[:, k]) ** 2, axis = 1))
EucDist = np.c_[EucDist, Dist]
cluster = np.argmin(EucDist, axis = 1) + 1
points =
for k in range(K):
points[k + 1] = np.array([]).reshape(2, 0)
for i in range(a):
points[cluster[i]] = np.c_[points[cluster[i]], data[i]]
for k in range(K):
points[k + 1] = points[k + 1].T
for k in range(K):
centroids[:, k] = np.mean(points[k + 1], axis = 0)
【问题讨论】:
【参考方案1】:K-means 是一种非确定性算法。如果您没有与 scikit-learn 中相同的初始化,则不确定是否找到相同的集群。在 scikit-learn 文档中是这样写的:
如果有足够的时间,K-means 将始终收敛,但这可能会达到局部最小值。这高度依赖于质心的初始化。因此,计算通常会进行多次,并且对质心进行不同的初始化。
【讨论】:
【参考方案2】:Kmeans 每次运行时都会发生变化,因为初始的集群中心是随机选择的。因此,除非您具有完全相同的初始集群中心,否则结果将不会相同。
【讨论】:
以上是关于为啥我的 k-means 收敛条件给出的结果与 sklearn 不同?的主要内容,如果未能解决你的问题,请参考以下文章