[英]numpy Vectorized multiplication of matrices
So what Im trying to do is this...所以我想做的是这个......
Suppose we have a set of matrices:假设我们有一组矩阵:
a1 = [1, 2]
b1 = [[3, 4], [5, 6]]
c1 = [7, 8]
a2 = [2, 4]
b2 = [[6, 8], [10, 12]]
c2 = [14, 16]
a3 = [3, 5]
b3 = [[7, 9], [11, 13]]
c3 = [15, 17]
A1 = np.array(a1)
B1 = np.array(b1)
C1 = np.array(c1)
A2 = np.array(a2)
B2 = np.array(b2)
C2 = np.array(c2)
A3 = np.array(a3)
B3 = np.array(b3)
C3 = np.array(c3)
I vectorized the collection of those arrays to produce我对这些数组的集合进行矢量化以生成
A = np.array([A1, A2, A3])
B = np.array([B1, B2, B3])
C = np.array([C1, C2, C3])
Then I need to perform something like然后我需要执行类似的操作
A.T @ B @ C
And I'd like to get the restult in the form of我想得到结果的形式
np.array([A1.T @ B1 @ C1, A2.T @ B2 @ C2, A3.T @ B3 @ C3])
The actual number of these triplets of matrices is in hundreds of thousands , so I'd like to do it using numpy vectorization, eg some form of tensor multiplication这些矩阵三元组的实际数量是数十万,所以我想使用 numpy 向量化来做,例如某种形式的张量乘法
I've tried to apply np.tensordot, but it doesn't qutie work as expected:我试图应用 np.tensordot,但它没有按预期工作:
np.tensordot(A, B, axes=((1), (1)))
Produces:产生:
array([[**[13, 16]**,
[26, 32],
[29, 35]],
[[26, 32],
**[52, 64]**,
[58, 70]],
[[34, 42],
[68, 84],
**[76, 92]**]])
Whereas I'd like it to be just an array of those marked arrays (each corresponding to Ai.T @ Bi)而我希望它只是那些标记数组的数组(每个对应于 Ai.T @ Bi)
The simple A @ B produces the same result...简单的 A @ B 产生相同的结果......
So is there a way to produce the expected result without a loop over first dime那么有没有一种方法可以产生预期的结果,而无需在第一角钱上进行循环
Hi you can vectorize your problem adding some dimensions and doing the product:嗨,您可以矢量化您的问题,添加一些维度并制作产品:
import numpy as np
a1 = [1, 2]
b1 = [[3, 4], [5, 6]]
c1 = [7, 8]
a2 = [2, 4]
b2 = [[6, 8], [10, 12]]
c2 = [14, 16]
a3 = [3, 5]
b3 = [[7, 9], [11, 13]]
c3 = [15, 17]
A1 = np.array(a1)
B1 = np.array(b1)
C1 = np.array(c1)
A2 = np.array(a2)
B2 = np.array(b2)
C2 = np.array(c2)
A3 = np.array(a3)
B3 = np.array(b3)
C3 = np.array(c3)
A = np.array([A1, A2, A3])
B = np.array([B1, B2, B3])
C = np.array([C1, C2, C3])
Res = (A[:,:,None]*B*C[:,None,:]).sum((1,2))
EDIT编辑
You also can solve the same problem using Einsten sum notation (i've just realized that).您也可以使用 Einsten sum notation 解决同样的问题(我刚刚意识到这一点)。 This is more straight forward and also easier.这更直接,也更容易。
res = np.einsum('ni,nij,nj->n',A,B,C)
The shapes:形状:
In [272]: A.shape
Out[272]: (3, 2)
In [273]: B.shape
Out[273]: (3, 2, 2)
In [274]: C.shape
Out[274]: (3, 2)
the subarray product is a scalar:子阵列乘积是一个标量:
In [275]: (A1.T@B1@C1).shape
Out[275]: ()
In [276]: (A1.T@B1@C1)
Out[276]: 219
matmul/@
can treat the first dimension (3), as a batch one if we expand all arrays to 3d, keeping in mind that we want the "the last of A with the 2nd to the last B" rule the last 2 dimensions: matmul/@
可以将第一个维度 (3) 视为批处理,如果我们将所有数组扩展到 3d,请记住我们希望“A 的最后一个与第二个到最后一个 B”规则最后两个维度:
In [277]: A[:,None,:]@B@C[:,:,None]
Out[277]:
array([[[ 219]],
[[1752]],
[[2704]]])
In [278]: _.shape
Out[278]: (3, 1, 1)
In [279]: (A[:,None,:]@B@C[:,:,None])[:,0,0]
Out[279]: array([ 219, 1752, 2704])
the equivalent einsum
is:等效的einsum
是:
In [280]: np.einsum('ij,ijk,ik->i', A, B, C)
Out[280]: array([ 219, 1752, 2704])
Here batch
i
is repeated all the way, while j
and k
are the familiar matrix product variables.这里batch
i
一直重复,而j
和k
是熟悉的矩阵乘积变量。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.