【发布时间】: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)
【问题讨论】:
标签: python scikit-learn while-loop k-means convergence