python - 为什么 KMeans 集群标签并不总是与 set random_state 相同?
问题描述
我有一个笔记本,我想从中分析集群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 开发人员报告的错误,或者这是一个特定于我的案例的问题,需要解决。
解决方案
这似乎是由于舍入误差造成的。最好的标签会在当前惯性优于之前的最佳标签时更新。但是,由于舍入误差,惯性值可能等于当前值,但看起来稍好一些,并且不必要地更新了标签。目前有一个PR正在解决这个问题。
推荐阅读
- c# - C#中的SQL Server多命令异常捕获
- c++ - Qtimer 不工作。我认为它没有更新
- android - 使用 Xdebug 在 nextcloud 中调试文件下载功能时超时
- ios - 将 applicationIconBadgeNumber 设置为零时,iOS 徽章未清除
- python - 一些python包本质上是全球性的吗?
- typescript - 如何编写 PickByValue 类型?
- css - 粘性页脚在短页面上强制置于底部
- javascript - 如何在画布中将图像绘制为画笔描边
- mongodb - 在不关闭数据库的情况下在 Mongo 中删除 5TB 集合
- javascript - 如何从 ajax 调用异步 MVC 控制器方法