Python 三维张量内维的矩阵乘法?

Python 三维张量内维的矩阵乘法?,python,numpy,Python,Numpy,我有两个numpy维度矩阵(386,3,4)和(386,4,3)。我想生成一个输出维度(386,3,3)。换句话说,我希望以矢量化的方式执行以下循环- for i in range(len(input1)): output[i] = np.matmul(input1[i], input2[i]) 最好的方法是什么?我们需要保持第一个轴对齐,因此我建议使用- 验证形状的示例运行- In [106]: a = np.random.rand(386, 3, 4) In [107]: b =

我有两个
numpy
维度矩阵
(386,3,4)
(386,4,3)
。我想生成一个输出维度
(386,3,3)
。换句话说,我希望以矢量化的方式执行以下循环-

for i in range(len(input1)):
    output[i] = np.matmul(input1[i], input2[i])

最好的方法是什么?

我们需要保持第一个轴对齐,因此我建议使用-

验证形状的示例运行-

In [106]: a = np.random.rand(386, 3, 4)

In [107]: b = np.random.rand(386, 4, 3)

In [108]: np.einsum('ijk,ikl->ijl',a,b).shape
Out[108]: (386, 3, 3)
运行示例以验证较小输入上的值-

In [174]: a = np.random.rand(2, 3, 4)

In [175]: b = np.random.rand(2, 4, 3)

In [176]: output = np.zeros((2,3,3))

In [177]: for i in range(len(a)):
     ...:     output[i] = np.matmul(a[i], b[i])
     ...:     

In [178]: output
Out[178]: 
array([[[ 1.43473795,  0.860279  ,  1.17855877],
        [ 1.91036828,  1.23063125,  1.5319063 ],
        [ 1.06489098,  0.86868941,  0.84986621]],

       [[ 1.07178572,  1.020091  ,  0.63070531],
        [ 1.34033495,  1.26641131,  0.79911685],
        [ 1.68916831,  1.63009854,  1.14612462]]])

In [179]: np.einsum('ijk,ikl->ijl',a,b)
Out[179]: 
array([[[ 1.43473795,  0.860279  ,  1.17855877],
        [ 1.91036828,  1.23063125,  1.5319063 ],
        [ 1.06489098,  0.86868941,  0.84986621]],

       [[ 1.07178572,  1.020091  ,  0.63070531],
        [ 1.34033495,  1.26641131,  0.79911685],
        [ 1.68916831,  1.63009854,  1.14612462]]])
In [180]: a = np.random.rand(386, 3, 4)

In [181]: b = np.random.rand(386, 4, 3)

In [182]: output = np.zeros((386,3,3))

In [183]: for i in range(len(a)):
     ...:     output[i] = np.matmul(a[i], b[i])
     ...:     

In [184]: np.allclose(np.einsum('ijk,ikl->ijl',a,b), output)
Out[184]: True
运行示例以验证较大输入上的值-

In [174]: a = np.random.rand(2, 3, 4)

In [175]: b = np.random.rand(2, 4, 3)

In [176]: output = np.zeros((2,3,3))

In [177]: for i in range(len(a)):
     ...:     output[i] = np.matmul(a[i], b[i])
     ...:     

In [178]: output
Out[178]: 
array([[[ 1.43473795,  0.860279  ,  1.17855877],
        [ 1.91036828,  1.23063125,  1.5319063 ],
        [ 1.06489098,  0.86868941,  0.84986621]],

       [[ 1.07178572,  1.020091  ,  0.63070531],
        [ 1.34033495,  1.26641131,  0.79911685],
        [ 1.68916831,  1.63009854,  1.14612462]]])

In [179]: np.einsum('ijk,ikl->ijl',a,b)
Out[179]: 
array([[[ 1.43473795,  0.860279  ,  1.17855877],
        [ 1.91036828,  1.23063125,  1.5319063 ],
        [ 1.06489098,  0.86868941,  0.84986621]],

       [[ 1.07178572,  1.020091  ,  0.63070531],
        [ 1.34033495,  1.26641131,  0.79911685],
        [ 1.68916831,  1.63009854,  1.14612462]]])
In [180]: a = np.random.rand(386, 3, 4)

In [181]: b = np.random.rand(386, 4, 3)

In [182]: output = np.zeros((386,3,3))

In [183]: for i in range(len(a)):
     ...:     output[i] = np.matmul(a[i], b[i])
     ...:     

In [184]: np.allclose(np.einsum('ijk,ikl->ijl',a,b), output)
Out[184]: True

matmul
也适用于:

a = np.random.random((243,3,4))
b = np.random.random((243,4,3))
np.matmul(a,b).shape
# (243, 3, 3)

啊!!我该学习
einsum()
。我逃避它已经有一段时间了。你有关于它的快速教程吗?谢谢@martianwars看看这是否有帮助-我认为与
np.matmul
相比,我没有得到相同的结果。有轻微的differences@martianwars添加的示例也会运行以验证值。我得到
allclose
True
,但打印出来时,值略有不同这就是创建matmul的目的-没有循环。