我有很多3 * 2矩阵(A1,A2,A3 ..),每个3 * 2都是平局。在两个绘制的情况下,我们有一个3 * 4(我们水平地堆叠A1,A2的每个绘制)。显然,我更容易将3 * 4矩阵(A)绘制为较大的矩阵,而不是一遍又一次地绘制3 * 2。
但是我需要为每个绘图(每个A1,A2 ......)执行矩阵乘法到矩阵B.说A1 * B和A2 * B ... AN * B
#each draw of the 3*2 matrix
A1 = np.array([[ 0, 1],
[ 4, 5],
[ 8, 9]])
A2 = np.array([[ 2, 3],
[ 6, 7],
[ 10, 11]])
# A is [A1,A2]
# Easier to draw A once for all (the larger matrix)
A = np.array([[ 0, 1, 2, 3],
[ 4, 5, 6, 7],
[ 8, 9, 10, 11]])
b = np.array([[ 0, 1],
[ 4, 5]
])
desired output
array([[ 4, 5, 12, 17],
[20, 29, 28, 41],
[36, 53, 44, 65]])
答案 0 :(得分:4)
您可以将矩阵A重新整形为2列,使其符合b
,进行矩阵乘法,然后重新整形:
np.dot(A.reshape(-1, 2), b).reshape(3, -1)
#array([[ 4, 5, 12, 17],
# [20, 29, 28, 41],
# [36, 53, 44, 65]])
答案 1 :(得分:3)
如果您不确定如何存储/堆叠传入的数组,一种方法是将它们堆叠为3D
数组,这样每个传入的数组都是 index-able 按第一轴 -
a = np.array((A1,A2))
示例运行 -
In [143]: a = np.array((A1,A2))
In [144]: a.shape
Out[144]: (2, 3, 2)
|-----------------> axis of stacking
然后,为了获得每个传入数组的矩阵乘法的等效输出b
,我们可以使用3D
堆叠数组a
上的np.tensordot
np.matmul
b
1}},因此在总和减少中从a
和第一个b
丢失最后一个轴,如此 -
out = np.tensordot(a,b,axes=((2),(0)))
让我们看一下输出值,并与每个矩阵乘法进行比较A1
,A2
等。
In [138]: out[0]
Out[138]:
array([[ 4, 5],
[20, 29],
[36, 53]])
In [139]: out[1]
Out[139]:
array([[12, 17],
[28, 41],
[44, 65]])
In [140]: A1.dot(b)
Out[140]:
array([[ 4, 5],
[20, 29],
[36, 53]])
In [141]: A2.dot(b)
Out[141]:
array([[12, 17],
[28, 41],
[44, 65]])
因此,基本上使用此堆叠操作,稍后在tensordot
上我们有:
out[0], out[1], .... = A1.dot(b), A2.dot(b), ....
替代np.tensordot
-
我们可以使用更简单的@ operator
版本来获得与tensordot
相同的输出 -
out = np.matmul(a,b)
在Python 3.5上,有一个更简单的版本取代np.matmul
,{{3}} -
out = a @ b
答案 2 :(得分:3)
即使计算不需要einsum
,也可以帮助我们思考问题:
In [584]: np.einsum('ij,jk->ik', A1,b)
Out[584]:
array([[ 4, 5],
[20, 29],
[36, 53]])
In [585]: np.einsum('ij,jk->ik', A2,b)
Out[585]:
array([[12, 17],
[28, 41],
[44, 65]])
A
是(3,4),它不会使用(2,2)b
。将其视为尝试使用加倍j
维度的工作:'i(2j),jk->i?k'
。但是如果我们插入轴怎么办? ' IMK,JK-> IMK&#39 ;?或者将额外维度添加到i
?
In [587]: np.einsum('imj,jk->imk', A.reshape(3,2,2),b)
Out[587]:
array([[[ 4, 5],
[12, 17]],
[[20, 29],
[28, 41]],
[[36, 53],
[44, 65]]])
数字在那里,只是形状是(3,2,2)。
In [590]: np.einsum('imj,jk->imk', A.reshape(3,2,2),b).reshape(3,4)
Out[590]:
array([[ 4, 5, 12, 17],
[20, 29, 28, 41],
[36, 53, 44, 65]])
或者您可以从一开始就构建A
,以便mij,jk->mik
有效(@Divaker
)
@Psidom
:
np.einsum('ij,jk->ik', A.reshape(3,2,2).reshape(-1,2) ,b).reshape(3,-1)
`@ piRSquared':
'kj,jI->kI`
答案 3 :(得分:2)
改变你的观点。您不必要地将自己锁定在3 x 2
。
您可以将A1
和A2
视为2x3
,然后将A
视为
array([[ 0, 4, 8, 2, 6, 10],
[ 1, 5, 9, 3, 7, 11]])
然后进行b = b.T
array([[0, 4],
[1, 5]])
这样你就可以进行操作了
b @ A
array([[ 4, 20, 36, 12, 28, 44],
[ 5, 29, 53, 17, 41, 65]])
让你的"吸引"看起来像这样
A = np.random.randint(10, size=(2, 9))
A
array([[7, 2, 1, 0, 9, 9, 1, 0, 2],
[8, 6, 1, 6, 6, 2, 4, 2, 9]])
b @ A
array([[32, 24, 4, 24, 24, 8, 16, 8, 36],
[47, 32, 6, 30, 39, 19, 21, 10, 47]])