使用 np.matmul 的替代方法是 np.einsum,它可以在 1 行更短且可以说更可口的代码中完成,无需方法链接。
示例数组:
np.random.seed(123)
w = np.random.rand(8,8,25000)
r = np.random.rand(8,25000)
wres = np.einsum('ijk,jk->ik',w,r)
# a quick check on result equivalency to your loop
print(np.allclose(np.matmul(w[:, :, 1], r[:, 1]), wres[:, 1]))
True
Timing 等同于@Imanol 的解决方案,因此请选择两者。两者都比循环快 30 倍。在这里,einsum 将因为数组的大小而具有竞争力。对于比这些更大的阵列,它可能会胜出,而在较小的阵列上会输。有关更多信息,请参阅this 讨论。
def solution1():
return np.einsum('ijk,jk->ik',w,r)
def solution2():
return np.squeeze(np.matmul(w.transpose(2, 0, 1), r.T[..., None])).T
def solution3():
Wres = np.empty((8, 25000))
for i in range(0,25000):
Wres[:,i] = np.matmul(w[:,:,i],r[:,i])
return Wres
%timeit solution1()
100 loops, best of 3: 2.51 ms per loop
%timeit solution2()
100 loops, best of 3: 2.52 ms per loop
%timeit solution3()
10 loops, best of 3: 64.2 ms per loop
Credit 至:@Divakar