【问题标题】:Permute rows in "slices" of 3d array to match each other置换 3d 数组的“切片”中的行以相互匹配
【发布时间】:2016-10-27 21:38:31
【问题描述】:

我有一系列二维数组,其中行是某个空间中的点。许多相似的点出现在所有数组中,但行顺序不同。 我想对行进行排序,使它们具有最相似的顺序。此外,对于使用 K-means 或 DBSCAN 进行聚类,这些点差异太大。问题也可以这样投。如果我将数组堆叠成 3d 数组,如何排列行以最小化沿第二轴的平均标准偏差 (SD)? 有什么好的排序算法可以解决这个问题?

我尝试了以下方法。

  1. 创建一组参考二维数组并对每个数组中的行进行排序,以最小化到参考二维数组的平均欧几里得距离。 恐怕这会产生有偏见的结果。

  2. 对数组中的行进行成对排序,然后是成对的中位数对,然后是成对的排序,等等...这实际上不起作用,我不知道为什么。

第三种方法可能只是蛮力优化,但我尽量避免这种情况,因为我有多组数组要执行该过程。

这是我的第二种方法(Python)的代码:

def reorder_to(A, B):
    """Reorder rows in A to best match rows in B.

    Input
    -----
    A : N x M numpy.array
    B : N x M numpy.array

    Output
    ------
    perm_order : permutation order
    """

    if A.shape != B.shape:
        print "A and B must have the same shape"
        return None

    N = A.shape[0]

    # Create a distance matrix of distance between rows in A and B
    distance_matrix = np.ones((N, N))*np.inf
    for i, a in enumerate(A):
        for ii, b in enumerate(B):
            ba = (b-a)
            distance_matrix[i, ii] = np.sqrt(np.dot(ba, ba))

    # Choose permutation order by smallest distances first
    perm_order = [[] for _ in range(N)]
    for _ in range(N):
        ind = np.argmin(distance_matrix)
        i, ii = ind/N, ind%N
        perm_order[ii] = i
        distance_matrix[i, :] = np.inf
        distance_matrix[:, ii] = np.inf

    return perm_order


def permute_tensor_rows(A):
    """Permute 1d rows in 3d array along the 0th axis to minimize average SD along 2nd axis.

    Input
    -----
    A : numpy.3darray
        Each "slice" in the 2nd direction is an independent array whose rows can be permuted
        to decrease the average SD in the 2nd direction.

    Output
    ------
    A : numpy.3darray
        A with sorted rows in each "slice".
    """
    step = 2
    while step <= A.shape[2]:
        for k in range(0, A.shape[2], step):

            # If last, reorder to previous
            if k + step > A.shape[2]:
                A_kk = A[:, :, k:(k+step)]
                kk_order = reorder_to(np.median(A_kk, axis=2), np.median(A_k, axis=2))
                A[:, :, k:(k+step)] = A[kk_order, :, k:(k+step)]
                continue

            k_0, k_1 = k, k+step/2
            kk_0, kk_1 = k+step/2, k+step

            A_k = A[:, :, k_0:k_1]
            A_kk = A[:, :, kk_0:kk_1]

            order = reorder_to(np.median(A_k, axis=2), np.median(A_kk, axis=2))
            A[:, :, k_0:k_1] = A[order, :, k_0:k_1]

        print "Step:", step, "\t ... Average SD:", np.mean(np.std(A, axis=2))
        step *= 2

    return A

【问题讨论】:

  • 听起来是个有趣的问题,但从你目前的解释中我不太明白。
  • 总方差而不是平均标准差可能是更好的指标
  • '真的不起作用' 这应该是什么意思?代码中的实际错误?运行但您不喜欢结果?我们如何知道代码是否正确?
  • 我想我可以解释我的方法是什么,但从代码中更容易阅读。无论如何,该函数可以置换每个切片中的行,但它不会降低第二方向的平均 SD。我不知道为什么。

标签: python arrays sorting numpy cluster-analysis


【解决方案1】:

对不起,我应该看看你的代码示例;内容非常丰富。

这里似乎为您的问题提供了一个开箱即用的解决方案:

http://docs.scipy.org/doc/scipy/reference/generated/scipy.optimize.linear_sum_assignment.html#scipy.optimize.linear_sum_assignment

根据我的经验,最多只有 100 分真正可行。

【讨论】:

  • 这看起来像是工作分配。您如何建议我用这种方法重铸问题来解决它?
猜你喜欢
  • 1970-01-01
  • 2017-04-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-10-28
相关资源
最近更新 更多