【发布时间】:2018-03-06 16:43:42
【问题描述】:
我正在尝试在 python 中实现Kmeans 算法,它将使用cosine distance 而不是欧几里得距离作为距离度量。
我知道使用不同的距离函数可能是致命的,应该谨慎行事。使用余弦距离作为度量迫使我改变平均函数(根据余弦距离的平均值必须是归一化向量的逐元素平均值)。
我见过this手动覆盖sklearn的距离函数的优雅解决方案,我想使用相同的技术来覆盖代码的平均部分但我找不到它。
有谁知道怎么办?
距离度量不满足三角不等式有多重要?
如果有人知道我使用余弦度量或满足距离和平均函数的 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。但是这个功能非常复杂,我不明白该怎么做。
有人知道替代解决方案吗?
或者,有谁知道如何使用始终强制质心标准化的函数来编辑此函数?
【问题讨论】:
-
看看 scikit-learn 源代码中的k_means_.py。您链接到的余弦距离示例只不过是用自定义函数替换
k_means_模块中名为euclidean_distance的函数变量。如果您发布您的 k-means 代码以及您想要覆盖的功能,我可以给您一个更具体的答案。但是如果你想自己做,只需在k_means_源中查找平均函数的名称并替换它即可。 -
此外,一般而言,SO 问题应包含minimal, complete, viable example - 如果您包含要修改的代码或不起作用的代码,您可以获得更多帮助。
-
@charlesreid1 谢谢,我添加了代码。我的问题是我还没有完全理解
k_means_.py中的平均函数是如何工作的,因此我无法理解如何更改它。 -
有一个名为 spherecluster 的 python 包在球体上实现了 K-means 算法(因此它与您尝试做的事情基本相同)。
标签: python scikit-learn k-means cosine-similarity sklearn-pandas