K-means:选择一组有效的初始质心有哪些好方法?

数据挖掘 数据挖掘 聚类 k-均值
2021-10-01 00:28:30

当使用质心的随机初始化时,不同的 K-means 运行会产生不同的总 SSE。它对算法的性能至关重要。有哪些有效的方法可以解决这个问题?最近的方法受到赞赏。

4个回答

产生更一致结果的方法是K-means++这种方法承认与简单的随机分配相比,初始质心位置可能有更好的选择。具体来说,当质心以不会在空间中聚集在一起的方式播种时,K-means 往往表现更好。

简而言之,方法如下:

  1. 随机选择一个数据点作为初始质心。
  2. 计算D(x),您的初始质心与所有其他数据点之间的距离,x.
  3. 从其余数据点中选择下一个质心,概率与D(x)2
  4. 重复直到所有质心都已分配。

笔记:D(x)应该随着更多质心的添加而更新。它应该设置为数据点和最近质心之间的距离。

您可能也有兴趣阅读这篇论文,该论文提出了该方法并描述了其整体预期性能。

我可能误解了您的问题,但通常 k-means 会根据您设置的聚类数量(即 k)为您随机选择质心。选择 k 的数字往往是一种主观练习。一个很好的起点是肘部/碎石图,可以在这里找到。

解决这个问题的常用方法是多次重新运行 K-means 算法,使用不同的质心随机初始化,并保持最佳解决方案。您可以通过评估训练数据的结果或通过交叉验证来做到这一点。

还有许多其他方法可以初始化质心,但没有一种方法能对每一个问题都表现得最好。您可以针对您的特定问题与随机初始化一起评估这些方法。

我同意肘部/碎石图。我发现它比随机种子更直观。这是一个示例代码来尝试它。

Ks=30
mean_acc=np.zeros((Ks-1))
std_acc=np.zeros((Ks-1))
ConfustionMx=[];
for n in range(1,Ks):    
    #Train Model and Predict  
    kNN_model = KNeighborsClassifier(n_neighbors=n).fit(X_train,y_train)
    yhat = kNN_model.predict(X_test)
    mean_acc[n-1]=np.mean(yhat==y_test);
    std_acc[n-1]=np.std(yhat==y_test)/np.sqrt(yhat.shape[0])

plt.plot(range(1,Ks),mean_acc,'g')
plt.fill_between(range(1,Ks),mean_acc - 1 * std_acc,mean_acc + 1 * std_acc, alpha=0.10)
plt.legend(('Accuracy ', '+/- 3xstd'))
plt.ylabel('Accuracy ')
plt.xlabel('Number of Nabors (K)')
plt.tight_layout()
plt.show()

print( "The best accuracy was with", mean_acc.max(), "with k=", mean_acc.argmax()+1)