【问题标题】:Agglomerative clustering from custom pairwise distance function自定义成对距离函数的凝聚聚类
【发布时间】:2021-01-24 12:27:05
【问题描述】:

感谢此线程上富有洞察力的 cmets:Pairwise Wasserstein distance on 2 arrays,我能够想出一个自定义函数来查找一组二维数组(10 个点,具有 x、y 坐标)之间的距离度量。我的下一步是找到一种方法将这些信息输入到凝聚聚类算法中,例如 scipy.cluster.hierarchy 模块的 fcluster() 方法。

更具体地说,我想使用以下函数为 3 维数据数组找到一组理想的 n 个簇。我不确定如何调整 pairwise-wasserstein 函数来检索 fcluster 需要以凝聚方式找到集群分配的距离矩阵。

提前感谢您的任何想法!

import numpy as np
from scipy.optimize import linear_sum_assignment
from scipy.cluster.hierarchy import dendrogram, linkage, ward
from scipy.cluster.hierarchy import fcluster

data = np.array([[[1, 2], [3, 4], [1, 2], [3, 4], [1, 2], [3, 4], [1, 2], [3, 4], [1, 2], [3, 4]],
                 [[5, 6], [7, 8], [5, 6], [7, 8], [5, 6], [7, 8], [5, 6], [7, 8], [5, 6], [7, 8]],
                 [[1, 15], [3, 2], [1, 2], [5, 4], [1, 2], [3, 4], [1, 2], [3, 4], [1, 2], [3, 4]],
                 [[5, 1], [7, 8], [5, 6], [7, 1], [5, 6], [7, 8], [5, 1], [7, 8], [5, 6], [7, 8]]])


def wasserstein_distance_function(f1, f2):
    min_cost = np.inf
    f1 = f1.reshape((10, 2))
    f2 = f2.reshape((10, 2))
    for l in np.linspace(0.8, 1.2, 3):
        for k in np.linspace(0.8, 1.2, 3):
            cost = distance.cdist(l * f1, k * f2, 'sqeuclidean')
            row_ind, col_ind = linear_sum_assignment(cost)
            curr_cost = cost[row_ind, col_ind].sum()
            if curr_cost < min_cost:
                min_cost = curr_cost
    return min_cost

def pairwise_wasserstein(points):
    """
    Helper function to perform the pairwise distance function of all points within 'points' parameter
    """
    for first_index in range(0,points.shape[0]):
      for second_index in range(first_index+1,points.shape[0]):
        print("First index: ", first_index, ", Second index: ", second_index, ", Distance: ",wasserstein_distance_function(points[first_index],points[second_index]))

def find_clusters_formation(data):
    """
    Method to find the clusters for the points array
    """
    dist_mat = pairwise_wasserstein(data)
    Z = ward(dist_mat)
    cluster = fcluster(Z, 3, criterion='maxclust')        

【问题讨论】:

  • 两个问题:1、你提供的数据涉及4个不同的点,对吧?因此,为了这个问题,您想将 4 个点聚类为 3 个聚类? 2、你用sklearn的AgglomerativeClustering代替fcluster可以吗?预测一个可能的问题:无论使用何种聚类库,都可以使用树状图进行可视化。
  • 感谢回复: 1. 这四个数据点只是一个说明。通常我有大约 5000 个这样的“阵型”——即我试图将 10 名球员的足球位置聚集成总共 20 个集群。上面的简化只是为了说明我在哪里难以适应数据。 2. 我对替代聚类算法非常开放,但只是发现聚类功能是迄今为止最直观的。

标签: python scipy cluster-analysis distance


【解决方案1】:

更新:

我可能通过将所有 10 个玩家的 x 和 y 坐标组合成 [1, 20] 数组来使其工作,其形式为:[x1, y1, x2, y2, ..., x10, y10]然后在 wasserstein_distance_function 中重新塑造它们。

我还不能 100% 确定这是否有效,但最初的结果似乎很有希望(即,相当平衡的集群)。

【讨论】:

    【解决方案2】:

    如果你想使用一个预定义的度量,你必须创建一个距离矩阵,这是一个对角线上有 0 的二次矩阵。当然,它的对角线上有零的原因是:一个点到它自己的距离为零。 然后将该矩阵作为参数传递给聚类算法的 fit_predict 函数。

    1. 第一步 - 创建距离矩阵并计算数据点之间的距离:
    distance_matrix = np.asarray([
        [wasserstein_distance_function(data[first_index], data[second_index]) 
             for first_index in range(len(data))] 
                 for second_index in range(len(data))])
    

    这将打印以下内容:

    array([[  0.  , 100.8 ,  76.4 ,  96.32],
           [100.8 ,   0.  , 215.  ,  55.68],
           [ 76.4 , 215.  ,   0.  , 186.88],
           [ 96.32,  55.68, 186.88,   0.  ]])
    
    1. 第二步 - 根据需要使用参数填充聚类算法:
    clusterer = AgglomerativeClustering(n_clusters=3, affinity="precomputed", linkage="average", distance_threshold=None)
    
    1. 第三步 - 提取标签:
    clusterer.fit_predict(distance_matrix)
    

    打印出来:

    array([2, 0, 1, 0], dtype=int64)
    

    它达到你想要的了吗?

    【讨论】:

      猜你喜欢
      • 2012-07-09
      • 2019-02-05
      • 2017-06-09
      • 2019-05-19
      • 2016-11-18
      • 2013-09-25
      • 2020-01-23
      • 2015-08-05
      • 2017-04-18
      相关资源
      最近更新 更多