我试图通过使用tensordot,dot和reshaping等来实现与np.matmul并行矩阵乘法相同的行为。
我正在将其翻译为使用的库没有支持并行乘法的matmul,只有dot和tensordot。
此外,我想避免迭代第一维,并希望使用一组矩阵乘法和重新整形(希望尽可能多地使用BLAS / GPU运行,因为我有大量的小矩阵来计算平行)。
以下是一个例子:
import numpy as np
angles = np.array([np.pi/4, 2*np.pi/4, 2*np.pi/4])
vectors = np.array([ [1,0],[1,-1],[-1,0]])
s = np.sin(angles)
c = np.cos(angles)
rotations = np.array([[c,s],[-s,c]]).T
print rotations
print vectors
print("Correct: %s" % np.matmul(rotations, vectors.reshape(3,2,1)))
# I want to do this using tensordot/reshaping, i.e just gemm BLAS operations underneath
print("Wrong: %s" % np.tensordot(rotations, vectors, axes=(1,1)))
这个输出是:
Correct: [[[ 7.07106781e-01]
[ 7.07106781e-01]]
[[ 1.00000000e+00]
[ 1.00000000e+00]]
[[ -6.12323400e-17]
[ -1.00000000e+00]]]
Wrong: [[[ 7.07106781e-01 1.11022302e-16 -7.07106781e-01]
[ -7.07106781e-01 -1.41421356e+00 7.07106781e-01]]
[[ 6.12323400e-17 -1.00000000e+00 -6.12323400e-17]
[ -1.00000000e+00 -1.00000000e+00 1.00000000e+00]]
[[ 6.12323400e-17 -1.00000000e+00 -6.12323400e-17]
[ -1.00000000e+00 -1.00000000e+00 1.00000000e+00]]]
有没有办法可以修改第二个表达式,以获得与第一个表达式相同的结果,只需使用dot / tensordot。
我相信这是可能的,并且已经看过some comments online,但从未见过任何例子
答案 0 :(得分:3)
我们需要保持一个对齐并保持输出。所以,tensordot/dot
在这里不起作用。 More info on tensordot
可能会以某种方式解释为什么它不会。但是,我们可以使用np.einsum
,这在大多数情况下(根据我的经验)被认为比np.matmul
略快。
实现看起来像这样 -
np.einsum('ijk,ik->ij',rotations, vectors)
此外,似乎所需的输出有一个尾随单例暗淡。所以,在None/np.newaxis
附加一个新轴,就像这样 -
np.einsum('ijk,ik->ij',rotations, vectors)[...,None]