首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >numpy中的3d矩阵乘法

numpy中的3d矩阵乘法
EN

Stack Overflow用户
提问于 2021-01-06 01:25:54
回答 2查看 185关注 0票数 2

我正在使用numpy执行矩阵乘法,但我不知道如何利用numpy进行3d矩阵乘法。

假设我有一个3x3的矩阵a,我把它乘以一个3x1的向量b,这将得到一个3x1的向量c。

这是在numpy中使用以下命令完成的:

代码语言:javascript
复制
# (3, 3) * (3, 1) -> (3, 1)
c = np.matmul(a, b)

好的,现在我想对一个3d矩阵执行类似的操作,这个矩阵本质上是2500个3x3矩阵。现在,我正在做一些事情,其效果是:

代码语言:javascript
复制
# (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的矢量化和矩阵/张量积。有什么手术可以让我做..。

代码语言:javascript
复制
# (2500, 3, 3) * (2500, 3, 1) -> (2500, 3, 1)
np.<function>(A, B, <args>)

我看过关于使用np.tensordot的东西,但我不知道如何设置轴。

代码语言:javascript
复制
np.tensordot(A, B, axes=???)
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2021-01-06 01:49:30

对于您拥有的3维数组(或3阶张量),您可以使用np.einsum doc进行更复杂的矩阵乘法。在您的特定情况下,您可以使用以下代码

代码语言:javascript
复制
>>> 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条目中。此过程的更一般形式可能是

代码语言:javascript
复制
np.einsum('...jk,...kl->...jl', x, y)

在每个张量(ndarray)的前面,你可以有任意数量的维度。

有关完整的示例,请参阅以下内容:

代码语言:javascript
复制
>>> 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]]])
票数 4
EN

Stack Overflow用户

发布于 2021-01-06 03:00:06

np.matmul(A,B)运行得很好。您收到了什么错误?

代码语言:javascript
复制
In [263]: A,B = np.arange(24).reshape(2,3,4), np.arange(8).reshape(2,4,1)

einsum解决方案:

代码语言:javascript
复制
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解决方案:

代码语言:javascript
复制
In [266]: A@B
Out[266]: 
array([[[ 14],
        [ 38],
        [ 62]],

       [[302],
        [390],
        [478]]])

你的循环:

代码语言:javascript
复制
In [267]: [np.matmul(a, b) for a, b in zip(A, B)]
Out[267]: 
[array([[14],
        [38],
        [62]]),
 array([[302],
        [390],
        [478]])]

matmul文档:

代码语言:javascript
复制
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.
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/65583672

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档