我试图在python中实现一个非常简单的贪婪聚类算法,但我很难对其进行优化以提高速度。该算法将采用距离矩阵,找到具有小于预定距离截止值的大多数分量的列,并将行索引(具有小于截止的分量)存储为群集的成员。集群的质心是列索引。然后从距离矩阵中移除每个成员索引的列和行(导致更小但仍然是正方形矩阵),并且算法迭代连续更小的距离矩阵,直到找到所有聚类。因为每次迭代都依赖于最后一次(形成一个新的距离矩阵,所以在簇之间没有重叠的成员),我想我无法避免python中的for循环缓慢。我已经尝试过numba(jit)加速它,但我认为它正在恢复到python模式,所以不会导致任何速度提升。以下是该算法的两种实现方式。第一个比后者慢。任何关于加速的建议都是最受欢迎的。我知道在scipy或sklearn中实现的其他聚类算法(例如DBSCAN,kmeans / medoids等),但我非常希望将当前的聚类算法用于我的应用程序。提前感谢任何建议。
方法1(较慢):
def cluster(distance_matrix, cutoff=1):
indices = np.arange(0, len(distance_matrix))
boolean_distance_matrix = distance_matrix <= cutoff
centroids = []
members = []
while boolean_distance_matrix.any():
centroid = np.argmax(np.sum(boolean_distance_matrix, axis=0))
mem_indices = boolean_distance_matrix[:, centroid]
mems = indices[mem_indices]
boolean_distance_matrix[mems, :] = False
boolean_distance_matrix[:, mems] = False
centroids.append(centroid)
members.append(mems)
return members, centroids
方法2(更快,但对于大型矩阵仍然很慢):
它接受由sklearn的最近邻居实现形成的邻接(稀疏)矩阵作为输入。这是我能想到的最简单,最快速的方法来获得聚类的相关距离矩阵。我相信使用稀疏矩阵也可以加速聚类算法。
nbrs = NearestNeighbors(metric='euclidean', radius=1.5,
algorithm='kd_tree')
nbrs.fit(data)
adjacency_matrix = nbrs.radius_neighbors_graph(data)
def cluster(adjacency_matrix, gt=1):
rows = adjacency_matrix.nonzero()[0]
cols = adjacency_matrix.nonzero()[1]
members = []
member = np.ones(len(range(gt+1)))
centroids = []
appendc = centroids.append
appendm = members.append
while len(member) > gt:
un, coun = np.unique(cols, return_counts=True)
centroid = un[np.argmax(coun)]
appendc(centroid)
member = rows[cols == centroid]
appendm(member)
cols = cols[np.in1d(rows, member, invert=True)]
rows = rows[np.in1d(rows, member, invert=True)]
return members, centroids