2d numpy,有效地分配非零索引 [row,col] [row,row] 和 [col,col] 的最小值

2d numpy, efficiently assign nonzero indices [row,col] the minimum of [row,row] and [col,col]

我正在使用矩阵来计算图中节点之间关系的组合(细节无关紧要)。

我有一个N*N的邻接矩阵,行列对应节点。因此,位置 [5,7] 是节点 5 与节点 7 的次数。[7,5] 也是如此。位置[3,3]是节点3一共出现了多少次,所以一共出现了多少次。

在每个循环中,我都必须减少矩阵。我取一个大小为 n 的向量,然后用该向量减去矩阵对角线。所以,我正在减少每个节点的总数:比如矩阵中的 [1,1] 和 [2,2] 和 [3,3] 等

希望到目前为止我说得有道理。这是这个问题。

至此,我修改了矩阵的对角线。现在,我想修改每个位置 [i,j] where

i != j and matrix[i,j] != 0  

我想将其修改为:

matrix[i,j] = min(matrix[i,i],matrix[j][j])

现在我当然可以遍历每个索引对 (i,j) 并执行我在上面写的内容。但这很慢。我希望有一些聪明的数学或 numpy 技巧可以使这更快。

谢谢!

首先,在进行任何优化之前,您应该分析一下:在程序的整个生命周期中只需要几十毫秒的时间,或者只占总时间的一小部分,试图聪明是没有意义的运行时间。

就是说,您可以利用广播对取最小值进行矢量化处理:

def slow(arr):
    out = arr.copy()
    for (i, j), x in np.ndenumerate(arr):
        if i != j and arr[i,j] != 0:
            out[i,j] = min(arr[i, i], arr[j, j])
    return out

def fast(arr):
    diag = arr.diagonal()
    mins = np.minimum(diag, diag[:, None])
    out = np.where(arr != 0, mins, arr)
    out[np.diag_indices_from(arr)] = diag
    return out

这给了我

In [61]: a = np.random.randint(0, 10, (100, 100))

In [62]: (slow(a) == fast(a)).all()
Out[62]: True

In [63]: %timeit slow(a)
11.9 ms ± 188 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

In [64]: %timeit fast(a)
62.8 µs ± 916 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)