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