如何沿第一维在两个三维张量之间进行矩阵乘法?



我想计算沿第一维的两个三维张量之间的点积。我尝试了以下einsum符号:

import numpy as np
a = np.random.randn(30).reshape(3, 5, 2)
b = np.random.randn(30).reshape(3, 2, 5)
# Expecting shape: (3, 5, 5)
np.einsum("ijk,ikj->ijj", a, b)

遗憾的是它返回了这个错误:

ValueError: einstein sum subscripts string includes output subscript 'j' multiple times

在我用np.tensordot失败后,我用了爱因斯坦和。欢迎提出意见和后续问题!

尺寸为55的两个维度不对应于同一轴。因此,您需要使用两个不同的下标来指定它们。例如,可以这样做:

>>> res = np.einsum('ijk,ilm->ijm', a, b)
>>> res.shape
(3, 5, 5)

注意,您还需要更改大小为22的轴的下标。这是因为您正在计算批处理外积(),即。我们同时在两个轴上迭代),而不是点积(即。我们在两个轴上同时迭代)。

  • 外产品:

    >>> np.einsum('ijk,ilm->ijm', a, b)
    
  • 下标k的点积,即aaxis=2baxis=1:

    >>> np.einsum('ijk,ikm->ijm', a, b)
    

    相当于a@b

dot product ... along the first dimension有点不清楚。第一个维度是"批"维度,其余的是3个点吗?还是别的什么?

In [103]: a = np.random.randn(30).reshape(3, 5, 2)
...: b = np.random.randn(30).reshape(3, 2, 5)
In [104]: (a@b).shape
Out[104]: (3, 5, 5)
In [105]: np.einsum('ijk,ikl->ijl',a,b).shape
Out[105]: (3, 5, 5)

@Ivan's答案不同:

In [106]: np.einsum('ijk,ilm->ijm', a, b).shape
Out[106]: (3, 5, 5)
In [107]: np.allclose(np.einsum('ijk,ilm->ijm', a, b), a@b)
Out[107]: False
In [108]: np.allclose(np.einsum('ijk,ikl->ijl', a, b), a@b)
Out[108]: True

Ivan's将其中一个的k维度和另一个的l维度相加,然后按元素进行广播。这不是矩阵乘法:

In [109]: (a.sum(axis=-1,keepdims=True)* b.sum(axis=1,keepdims=True)).shape
Out[109]: (3, 5, 5)
In [110]: np.allclose((a.sum(axis=-1,keepdims=True)* b.sum(axis=1,keepdims=True)),np.einsum('ijk,ilm->ijm', a,
...:  b))
Out[110]: True

批处理的另一个测试:

In [112]: res=np.zeros((3,5,5))
...: for i in range(3):
...:    res[i] = a[i]@b[i]
...: np.allclose(res, a@b)
Out[112]: True

最新更新