【问题标题】:How to specify a distance function for clustering?如何指定聚类的距离函数?
【发布时间】:2016-02-16 18:16:27
【问题描述】:

我想对给定距离的点进行聚类,但奇怪的是,似乎 scipy 和 sklearn 聚类方法都不允许指定距离函数。

例如,在sklearn.cluster.AgglomerativeClustering 中,我唯一可以做的就是输入一个亲和矩阵(这将非常占用内存)。为了构建这个非常矩阵,建议使用sklearn.neighbors.kneighbors_graph,但我不明白如何在两点之间指定距离函数。有人可以启发我吗?

【问题讨论】:

    标签: python scipy scikit-learn hierarchical-clustering


    【解决方案1】:

    所有 scipy 层次聚类例程都将接受一个自定义距离函数,该函数接受两个指定一对点的 1D 向量并返回一个标量。例如,使用fclusterdata:

    import numpy as np
    from scipy.cluster.hierarchy import fclusterdata
    
    # a custom function that just computes Euclidean distance
    def mydist(p1, p2):
        diff = p1 - p2
        return np.vdot(diff, diff) ** 0.5
    
    X = np.random.randn(100, 2)
    
    fclust1 = fclusterdata(X, 1.0, metric=mydist)
    fclust2 = fclusterdata(X, 1.0, metric='euclidean')
    
    print(np.allclose(fclust1, fclust2))
    # True
    

    metric= kwarg 的有效输入与 scipy.spatial.distance.pdist 相同。

    【讨论】:

    • 感谢您的提示。我试过 fclusterdata 但它失败了,因为它首先将输入数组转换为双精度数组,而我的数组是结构化的(它包含字符串)。我该如何处理?
    • 你能发布一些示例数据吗?
    • 当然:[(b'FOO', b'67482', 13167), ..., (b'BAR', b'32798', 1369)]。但我在想,解决这个问题的一种方法是在索引(即 1,...,n)上运行聚类方法,并在距离函数中使用这些索引来获取初始数组中的正确数据。顺便说一句,我不需要聚类是分层的,所以我可以使用 k-means 方法而不是 fclusterdata。
    • 我遵循了我的想法,现在它正在工作!函数 fclusterdata 就足够了,因为它返回了一个平面集群,这正是我所需要的。感谢您的帮助。
    • 这个例子似乎有问题。我试图运行它,但 fclust1fclust2 都是。需要设置适当的阈值。
    【解决方案2】:

    sklearn 具有允许预先计算距离矩阵的 DBSCAN(使用三角矩阵,其中 M_ij 是 i 和 j 之间的距离)。但这可能不是您正在寻找的集群类型。

    此外,正如其他人所提到的,scipy.cluster.hierarchy.fclusterdata 还允许预先计算距离指标。 this reply 中给出了一段 sn-p 代码,它提供了一些代码来将 NxN 距离矩阵转换为 fclusterdata 可以轻松读取的格式:

    import scipy.spatial.distance as ssd
    # convert the redundant n*n square matrix form into a condensed nC2 array
        distArray = ssd.squareform(distMatrix) # distArray[{n choose 2}-{n-i choose 2} + (j-i-1)] is the distance between points i and j
    

    【讨论】:

      【解决方案3】:

      对于层次聚类,scipy.cluster.hierarchy.fclusterdata 允许您通过 metric= 关键字参数使用列表 here 中包含的任何距离度量,前提是它与您想要的链接方法一起使用。

      【讨论】:

      • 不行,我必须定义我自己的距离函数(实际上是通过调用 geopy)。
      • 哦,误会了。您可以通过像上面告诉您的那样构建 kneighbors_graph 来做到这一点,但使用 metric=DistanceMetric.get_metric('pyfunc', name_of_my_distance_function) 指定用户定义的度量,通过导入 DistanceMetric 类并编写您自己的计算距离的函数,前提是它是一个有效的度量。
      • 感谢您提供有关如何使用距离函数的提示,但我承认我真的不明白 kneighbors_graph 的作用。我什至不理解文档中给出的示例的输出。我不熟悉在这种情况下使用图表。对我来说,它是应该提供给聚类算法的所有点之间的距离矩阵(或者,更好的是,一种为算法本身提供距离函数的方法)。
      猜你喜欢
      • 2021-01-24
      • 1970-01-01
      • 2017-06-09
      • 1970-01-01
      • 2013-09-25
      • 2016-01-10
      • 1970-01-01
      • 2017-04-18
      • 1970-01-01
      相关资源
      最近更新 更多