我正在使用numpy执行矩阵乘法,但我不知道如何利用numpy进行3d矩阵乘法。
假设我有一个3x3的矩阵a,我把它乘以一个3x1的向量b,这将得到一个3x1的向量c。
这是在numpy中使用以下命令完成的:
# (3, 3) * (3, 1) -> (3, 1)
c = np.matmul(a, b)好的,现在我想对一个3d矩阵执行类似的操作,这个矩阵本质上是2500个3x3矩阵。现在,我正在做一些事情,其效果是:
# (2500, 3, 3) * (2500, 3, 1) -> list of (3, 1) vectors with length 2500
C = [np.matmul(a, b) for a, b in zip(A, B)]它返回一个(3,1)向量的列表。
我不想循环,而是充分利用numpy的矢量化和矩阵/张量积。有什么手术可以让我做..。
# (2500, 3, 3) * (2500, 3, 1) -> (2500, 3, 1)
np.<function>(A, B, <args>)我看过关于使用np.tensordot的东西,但我不知道如何设置轴。
np.tensordot(A, B, axes=???)发布于 2021-01-06 01:49:30
对于您拥有的3维数组(或3阶张量),您可以使用np.einsum doc进行更复杂的矩阵乘法。在您的特定情况下,您可以使用以下代码
>>> import numpy as np
>>> x = np.random.randint(0, 3, (3, 3, 3)) # shape (3, 3, 3)
>>> y = np.random.randint(0, 3, (3, 3, 3)) # shape (3, 3, 3)
>>> np.einsum('ijk,ikl->ijl', x, y) # still shape (3, 3, 3)特别地,einsum表达式'ijk,ikl->ijl'意味着对于每个ndarray矩阵,执行规则矩阵乘法jk,kl->jl,并将结果放入结果张量(i)中的ndarray条目中。此过程的更一般形式可能是
np.einsum('...jk,...kl->...jl', x, y)在每个张量(ndarray)的前面,你可以有任意数量的维度。
有关完整的示例,请参阅以下内容:
>>> import numpy as np
>>> x = np.random.randint(0, 3, (3, 3, 3)) # shape (3, 3, 3)
>>> x
array([[[0, 0, 1],
[2, 2, 1],
[2, 1, 1]],
[[2, 0, 2],
[2, 2, 1],
[2, 2, 2]],
[[2, 2, 2],
[1, 1, 2],
[0, 2, 2]]])
>>> y = np.random.randint(0, 3, (3, 3, 3)) # shape (3, 3, 3)
>>> y
array([[[0, 0, 1],
[2, 1, 0],
[0, 0, 2]],
[[1, 2, 0],
[2, 0, 1],
[2, 2, 1]],
[[0, 2, 1],
[0, 1, 0],
[0, 2, 1]]])
>>> np.einsum('ijk,ikl->ijl', x, y)
array([[[ 0, 0, 2],
[ 4, 2, 4],
[ 2, 1, 4]],
[[ 6, 8, 2],
[ 8, 6, 3],
[10, 8, 4]],
[[ 0, 10, 4],
[ 0, 7, 3],
[ 0, 6, 2]]])
>>> np.einsum('...ij,...jk->...ik', x, y)
array([[[ 0, 0, 2],
[ 4, 2, 4],
[ 2, 1, 4]],
[[ 6, 8, 2],
[ 8, 6, 3],
[10, 8, 4]],
[[ 0, 10, 4],
[ 0, 7, 3],
[ 0, 6, 2]]])发布于 2021-01-06 03:00:06
np.matmul(A,B)运行得很好。您收到了什么错误?
In [263]: A,B = np.arange(24).reshape(2,3,4), np.arange(8).reshape(2,4,1)einsum解决方案:
In [264]: np.einsum('ijk,ikl->ijl',A,B)
Out[264]:
array([[[ 14],
[ 38],
[ 62]],
[[302],
[390],
[478]]])
In [265]: _.shape
Out[265]: (2, 3, 1)matmul解决方案:
In [266]: A@B
Out[266]:
array([[[ 14],
[ 38],
[ 62]],
[[302],
[390],
[478]]])你的循环:
In [267]: [np.matmul(a, b) for a, b in zip(A, B)]
Out[267]:
[array([[14],
[38],
[62]]),
array([[302],
[390],
[478]])]matmul文档:
If either argument is N-D, N > 2, it is treated as a stack of
matrices residing in the last two indexes and broadcast accordingly.https://stackoverflow.com/questions/65583672
复制相似问题