Python 三维阵列的Numpy元素级产品
我有两个形状为(N,2,2)的3d阵列A和B,我想根据N轴乘以元素,每个2x2矩阵上的矩阵积。通过循环实现,它看起来像Python 三维阵列的Numpy元素级产品,python,arrays,numpy,matrix,vectorization,Python,Arrays,Numpy,Matrix,Vectorization,我有两个形状为(N,2,2)的3d阵列A和B,我想根据N轴乘以元素,每个2x2矩阵上的矩阵积。通过循环实现,它看起来像 C[i] = dot(A[i], B[i]) 有没有一种不使用循环的方法可以做到这一点?我已经调查了tensordot,但还没能让它发挥作用。我想我可能需要类似于张量的东西(a,b,轴=([1,2],[2,1]),但这给了我一个NxN矩阵。看起来你在沿着第一个轴对每个切片进行矩阵乘法。同样,你也可以这样使用- np.einsum('ijk,ikl->ijl',A,B)
C[i] = dot(A[i], B[i])
有没有一种不使用循环的方法可以做到这一点?我已经调查了tensordot,但还没能让它发挥作用。我想我可能需要类似于张量的东西(a,b,轴=([1,2],[2,1]),但这给了我一个NxN矩阵。看起来你在沿着第一个轴对每个切片进行矩阵乘法。同样,你也可以这样使用-
np.einsum('ijk,ikl->ijl',A,B)
我们也可以使用-
在Python3.x上,这个matmul
操作简化为-
标杆管理
接近-
def einsum_based(A,B):
return np.einsum('ijk,ikl->ijl',A,B)
def matmul_based(A,B):
return np.matmul(A,B)
def forloop(A,B):
N = A.shape[0]
C = np.zeros((N,2,2))
for i in range(N):
C[i] = np.dot(A[i], B[i])
return C
时间安排-
In [44]: N = 10000
...: A = np.random.rand(N,2,2)
...: B = np.random.rand(N,2,2)
In [45]: %timeit einsum_based(A,B)
...: %timeit matmul_based(A,B)
...: %timeit forloop(A,B)
100 loops, best of 3: 3.08 ms per loop
100 loops, best of 3: 3.04 ms per loop
100 loops, best of 3: 10.9 ms per loop
您只需要对张量的第一个维度执行操作,该维度标记为
0
:
c = tensordot(a, b, axes=(0,0))
这将如你所愿。此外,您不需要轴的列表,因为您正在执行操作的只是一个维度。使用轴([1,2],[2,1])
可以交叉乘以第二维度和第三维度。如果你用索引表示法(爱因斯坦求和约定)写它,它对应于c[i,j]=a[i,k,l]*b[j,k,l]
,因此你收缩了你想要保留的索引
编辑:好的,问题是两个3d对象的张量积是一个6d对象。由于收缩涉及成对的索引,因此不可能通过tensordot
操作获得3d对象。诀窍是将计算一分为二:首先对索引执行tensordot
以执行矩阵运算,然后采用张量对角线将4d对象缩减为3d。在一个命令中:
d = np.diagonal(np.tensordot(a,b,axes=()), axis1=0, axis2=2)
用张量表示法
d[i,j,k]=c[i,j,i,k]=a[i,j,l]*b[i,l,k]
我得到了一个(2,2,2,2)
形状,而不是(10,2,2)
,所以可能有问题。对不起,我给了你一个错误的答案,请看我的编辑。谢谢Divakar。我希望我能使用这个,但我有点被一个没有einsum的旧版本的numpy卡住了。是否有tensordot等效调用?我永远无法理解einsum
是如何工作的。你有没有读过一些东西教你语法是如何工作的?@rayryeng只是一些官方文档和几个小时的游戏。还有很多其他的事情我看到人们用它做,所以我需要弄清楚!就像您使用permute
一样,只需使用它即可。最近,我又通过玩弄它来弄明白了。@Remy你终于可以访问np.einsum
支持的NumPy了吗?我真的不知道如何让tensordot在这种情况下工作。@Divakar是的,我在自己的电脑上工作过,而且速度真的快得多,我要咬紧牙关,升级其他人的numpy。再次感谢。
c = tensordot(a, b, axes=(0,0))
d = np.diagonal(np.tensordot(a,b,axes=()), axis1=0, axis2=2)