【发布时间】:2025-12-27 20:45:11
【问题描述】:
我有一个笔记本,我想在其中分析来自sklearn.cluster.KMeans 的集群。当我运行代码时,集群是相同的,但应用的标签可能会有所不同。这使我无法在笔记本的降价部分中按标签引用集群。我想知道为什么即使设置random_state 也会发生这种情况。看来random_state 只允许聚类相同,但为什么它每次也不应用相同的标签值?下面的代码将复制该问题,并且该图显示了标签如何变化。
from sklearn.cluster import KMeans
import numpy as np
import matplotlib.pyplot as plt
np.random.seed(2)
x = np.random.normal(size=(1800, 2))
x[:700, 0] += 3
x[:700, 1] += 3
x[700:1200, 0] -= 0.5
x[700:1200, 1] -= 0.5
x[1200:, 0] += 3
x[1200:, 1] -= 3
np.random.shuffle(x)
first = None
while True: # it typically only takes a few iterations for a difference to occur
km = KMeans(n_clusters=3, random_state=10)
km.fit(x)
pred = km.predict(x)
if first is None:
first = pred
elif not np.array_equal(first, pred):
print(first)
print(pred)
fig, ax = plt.subplots(1,2)
for label in range(3):
clusters = x[first == label]
cluster = x[pred == label]
ax[0].scatter(clusters[:, 0], clusters[:, 1], label=label)
ax[1].scatter(cluster[:, 0], cluster[:, 1], label=label)
break
ax[0].legend()
ax[1].legend()
plt.show()
[0 1 1 ... 2 0 0] # labels for first run
[0 2 2 ... 1 0 0] # different labels for later run
此外,我很困惑为什么使用相同的random_state 时详细输出不完全相同。
我注意到了几件事。首先是np.random.seed(1) 不会产生这个问题。因此,它似乎依赖于数据。其次,如果n_jobs=1 这似乎没有发生,但默认的n_jobs=None 会给出不同的结果(标签和详细输出)。并行化是否会导致这种情况发生?
很高兴知道这是我应该向 scikit-learn 开发人员报告的错误,还是我需要解决的特定问题。
【问题讨论】:
-
这个article 表示这种行为是故意的,但如果您需要修复它,有解决方法。
-
@MatthewBarlowe 是的,但是那篇文章没有设置 random_state 所以解释是因为集群中心是随机分布的。据我了解,在设置 random_state 时,应将集群中心初始化为相同的值。
-
这里是source code,它可能会帮助您回答为什么的问题。
-
@Kraigolas 我已经通读了源代码。随机性的唯一用途是集群中心初始化,所以我不明白变化的结果。后端是使用 Cython 编写的,C 代码是否可能引入了一些替代的随机状态?
标签: python scikit-learn k-means