【问题标题】:Dimension of tensordot between 2 3D tensors2 个 3D 张量之间的张量点维度
【发布时间】:2021-12-19 20:45:15
【问题描述】:

我有一个关于 tensordot 操作的快速问题。我试图弄清楚是否有一种方法可以在两个张量之间执行张量积以获得我想要的正确形状输出。其中一个张量是 B X L X D 维度,另一个是 B X 1 X D 维度,我试图弄清楚是否有可能最终得到 B X D 矩阵。

目前,我正在循环 B 维并在 1 X D 和 D X L(转置 L X D)矩阵之间执行矩阵乘法,并将它们堆叠以最终得到 B X L 矩阵。这显然不是最快的方法,因为循环可能很昂贵。是否可以通过执行快速张量点获得所需的 B X D 形状输出?我似乎无法找到摆脱其中一个 B 的方法。

非常感谢任何见解或方向。

【问题讨论】:

  • 我假设您提到了 BXL 的结果,因为 1 XD 和 DXL 的矩阵乘法的形状为 1 XL 而不是 1 X D。如果是这种情况,请使用正确的详细信息更新问题.
  • @A.Maman 感谢您的关注。更新了我的 OP

标签: python pytorch matrix-multiplication dimension tensordot


【解决方案1】:

一个选项

是使用torch.bmm(),它正是这样做的(docs)。

它采用形状为 (b, n, m) 和 (b, m, p) 的张量,并返回形状为 (b, n, p) 的批量矩阵乘法。

(我假设您给出了 B X L 的结果,因为 1 X D 和 D X L 的矩阵乘法的形状是 1 X L 而不是 1 X D)。

在你的情况下:

import torch
B, L, D = 32, 10, 512

a = torch.randn(B, 1, D)    #shape (B X 1 X D)
b = torch.randn(B, L, D)    #shape (B X L X D)

b = b.transpose(1,2)        #shape (B X D X L)

result = torch.bmm(a, b)

result = result.squeeze()
print(result.shape)
>>> torch.Size([32, 10])

或者

您可以使用torch.einsum(),我认为它更紧凑但可读性较差:

import torch
B, L, D = 32, 10, 512

a = torch.randn(B, 1, D)
b = torch.randn(B, L, D)

result = torch.einsum('abc, adc->ad', a, b)

print(result.shape)
>>> torch.Size([32, 10])

最后的挤压是为了使您的结果为形状 (32, 10) 而不是形状 (32, 1, 10)。

【讨论】:

  • 这正是我所希望的。谢谢好心的陌生人!这解决了我的问题。
【解决方案2】:

我相信torch.einsum 是执行张量求和最直观的方式:

>>> torch.einsum('bld,bed->bd', x, y)

形状为(B, D)

明确表述,这里执行的操作等价于:

res = torch.zeros(B, D)
for b in range(B):
    for l in range(L):
        for d in range(D):
            res += x[b,l,d]*y[b,0,d]

其实y上的第二个轴也是循环的,但是范围只是[0],因为y的第二个维度是单例。

【讨论】:

    猜你喜欢
    • 2019-11-08
    • 1970-01-01
    • 2016-07-02
    • 1970-01-01
    • 1970-01-01
    • 2019-02-19
    • 2023-01-29
    • 1970-01-01
    • 2020-11-01
    相关资源
    最近更新 更多