我正在尝试在python中实现Kmeans
算法,该算法将使用cosine distance
而不是欧式距离作为距离度量。我了解使用不同的距离功能可能会致命,应谨慎操作。使用余弦距离作为度量标准会迫使我更改平均值函数(根据余弦距离的平均值必须是归一化矢量的逐个元素平均值)。我已经看到了手动覆盖sklearn的距离函数的this优雅解决方案,并且我想使用相同的技术来覆盖代码的平均部分,但是我找不到它。有谁知道该怎么做?距离度量不满足三角不等式有多关键?如果有人知道我使用余弦度量或满足距离和平均函数的kmeans的另一种有效实现,那么它也确实会有所帮助。非常感谢你!编辑:在使用角距离而不是余弦距离之后,代码看起来像这样:
def KMeans_cosine_fit(sparse_data, nclust = 10, njobs=-1, randomstate=None):
# Manually override euclidean
def euc_dist(X, Y = None, Y_norm_squared = None, squared = False):
#return pairwise_distances(X, Y, metric = 'cosine', n_jobs = 10)
return np.arccos(cosine_similarity(X, Y))/np.pi
k_means_.euclidean_distances = euc_dist
kmeans = k_means_.KMeans(n_clusters = nclust, n_jobs = njobs, random_state = randomstate)
_ = kmeans.fit(sparse_data)
return kmeans
我注意到(通过数学计算),如果将向量归一化,则标准平均值可以很好地用于角度度量。据我了解,我必须在_mini_batch_step()
中更改k_means_.py。但是功能非常复杂,我不知道该怎么做。有人知道替代解决方案吗?或者,也许有人知道我该如何使用总是强制将质心标准化的函数来编辑此函数?
不幸的是Sklearn当前实现的k均值仅使用欧几里得距离。
原因是K均值包括查找聚类中心并将样本分配给最接近中心的计算,而欧几里得仅在样本中具有中心的含义。
如果要使用余弦距离的K均值,则需要创建自己的函数或类。或者,尝试使用其他群集算法,例如DBSCAN。