使用Numpy(无循环)将轴乘以矩阵(点积)

时间:2017-12-13 11:47:06

标签: numpy matrix product multiplication

我正在与Numpy合作处理图像处理问题,我正在尝试避免循环并执行以下操作:

我有一个Dims矩阵M NxNxKxK(它是矩阵KxK的矩阵NxN),对于每一行,我希望乘以(点积)行中的所有N个矩阵(KxK)。因此,如果我在完整的M(所有行)上执行此操作,我得到矩阵的向量V(Nx1)(KxK),其中V [i]保持M [i,0] xM [i,1]的点积]×... XM [I,N-1]。

我使用循环实现了这个问题的解决方案,我无法找到一种方法来实现这一点而不需要循环。

实施(带循环):

    a = np.array([[1,1,1], [1,1,1], [1,1,1]])
    mat = np.array([[a,a,a,a], [a*2,a*2,a*2,a*2], [a*3,a*3,a*3,a*3],
                    [a*4,a*4,a*4,a*4]])  # the original matrix
    N, N, k, k = mat.shape
    result = np.ones((N, k, k))  # resulting matrix
    for i in range(N):
        k = functools.reduce(np.dot, mat[i,:])
        result[i,:] = k
    print(result)

1 个答案:

答案 0 :(得分:2)

以下使用reduce但不是N:

的循环
mat = mat.swapaxes(0, 1)
result = functools.reduce(lambda a, b: np.einsum('ijk,ikl->ijl', a, b), mat[:])

einsum表示法'jk,kl->jl'表示矩阵乘法,索引i表示应该对第一个索引的每个值进行处理。 mat[0]mat[1]的第一个索引实际上是mat(列索引)的第二个索引,因此,在写入时,乘法发生在mat的每一列中。您希望在每一行中完成它,因此使用swapaxes

这是否比for-loop版本更快或更慢取决于N和k的相对大小。 np.dot方法经过高度优化,但如果N上的循环非常长,einsum可能会获胜。一些%timeit结果:

  • 当N = 100,k = 2时,for循环版本需要7.5 ms,einsum版本需要4.31 ms。
  • 当N = 100,k = 20时,for循环版本需要27.3 ms,einsum版本需要153 ms。

因此,在特定情况下获得适度增长,在大多数其他情况下会出现重大损失。但你没有要求一个“有效”的解决方案,你要求一个“没有循环”,所以这里是(“没有循环”!=“更快”)。正如Divakar在评论中建议的那样,你可能最好保持代码不变。