问题描述
我将在python中实现kmeans。在一次迭代中,我计算了每150个点的中心标签:
label =
array([0,1,2,3,4,5,6,7,5],dtype=int64)
和最初的8个中心:
centers =
array([[5.1,3.5,1.4,0.2],[4.9,3.,[4.7,3.2,1.3,[4.6,3.1,1.5,[5.,3.6,[5.4,3.9,1.7,0.4],3.4,0.3],0.2]])
X是虹膜数据X.shape =(150,4):
X =
array( [5.1,3.8,[5.1,3.7,1.,3.3,0.5],[4.8,1.9,1.6,[5.2,...
现在,我想基于当前的中心标签来更新中心。这意味着迭代标签中的唯一值。然后提取X中的所有对应点,并基于所有提取的点计算中心。最后更新中心。例如,在第一次迭代中,提取带有标签0的X中的所有元素。然后计算center(每个维度的均值)。然后将center [0]更新为新中心。以此类推,标签1、2 ...
这是原始kmeans算法的一次迭代。我的问题是我该如何以numpy向量化的方式编写此步骤,而不是循环遍历。
解决方法
更新中心
您可以使用boolean array indexing和computation along an axis仅显式地遍历群集,而不是遍历每个数据点。
K = 8
for k in range(K):
centers[k] = X[label==k].mean(axis=0)
更新标签
这也可以通过遍历所有集群来完成:
distances = np.empty(shape=(X.shape[0],K))
for k in range(K):
distances[:,k] = np.sqrt(np.sum((X - centers[k])**2,axis=1))
labels = distances.argmin(axis=1)
但是通过利用矩阵乘法是成对的点积,也可以在没有显式循环的情况下完成。
squared_distances = np.sum(centers**2,axis=1) + (np.sum(X**2,axis=1) - 2*centers @ X.T).T
squared_distances[np.isclose(squared_distances,0)] = 0 # self-distance can become slightly negative with this method (floating point precision problem)
distances = np.sqrt(squared_distances)
labels = distances.argmin(axis=1)