【问题标题】:Multiply a 3d tensor with a 2d matrix using torch.matmul使用 torch.matmul 将 3d 张量与 2d 矩阵相乘
【发布时间】:2021-06-07 13:37:42
【问题描述】:

我在 PyTorch 中有两个张量,z 是形状为 (n_samples, n_features, n_views) 的 3d 张量,其中 n_samples 是数据集中的样本数,n_features 是每个样本的特征数,@ 987654325@ 是描述相同(n_samples, n_features) 特征矩阵但具有其他值的不同视图的数量。

我有另一个二维张量b,形状为(n_samples, n_views),其目的是在不同视图中重新缩放样本的所有特征。换句话说,它封装了同一样本的每个视图的特征的重要性。 例如:

import torch
z = torch.Tensor(([[2,3], [1,1], [4,5]], 
                  [[2,2], [1,2], [7,7]], 
                  [[2,3], [1,1], [4,5]], 
                  [[2,3], [1,1], [4,5]]))

b = torch.Tensor(([1, 0], 
                  [0, 1], 
                  [0.2, 0.8], 
                  [0.5, 0.5]))
print(z.shape, b.shape)

>>>torch.Size([4, 3, 2]) torch.Size([4, 2])

由于zb 之间的运算,我想获得形状为(n_samples, n_features) 的第三张量r。 一种可能的解决方案是:

b = b.unsqueeze(1)
r = z * b
r = torch.sum(r, dim=-1)
print(r, r.shape)
>>>tensor([[2.0000, 1.0000, 4.0000],
        [2.0000, 2.0000, 7.0000],
        [2.8000, 1.0000, 4.8000],
        [2.5000, 1.0000, 4.5000]]) torch.Size([4, 3])

使用torch.matmul() 是否可以达到相同的结果?我已经尝试了很多次来置换两个向量的维度,但都没有成功。

【问题讨论】:

    标签: python pytorch linear-algebra tensor


    【解决方案1】:

    是的,这是可能的。如果您在两个操作中都有多个批量维度,则可以使用广播。在这种情况下,每个操作数的最后两个维度被解释为 matrix 大小。 (我建议在documentation 中查找它。)

    因此,您需要为向量 b 增加一个维度,以使它们成为 n x 1“矩阵”(列向量):

    # original implementation
    b1 = b.unsqueeze(1)
    r1 = z * b1
    r1 = torch.sum(r1, dim=-1)
    print(r1.shape)
    
    # using torch.matmul
    r2 = torch.matmul(z, b.unsqueeze(2))[...,0]
    print(r2.shape)
    print((r1-r2).abs().sum())  # should be zero if we do the same operation
    

    另外,torch.einsum 也使这变得非常简单。

    # using torch.einsum
    r3 = torch.einsum('ijk,ik->ij', z, b)
    print((r1-r3).abs().sum())  # should be zero if we do the same operation
    

    einsum 是一个非常强大的操作,它可以做很多事情:你可以置换张量维度,对它们求和,或者执行标量积,所有这些都可以有或没有广播。它源自物理学中最常用的Einstein summation convention。粗略的想法是给操作符的每个维度命名,然后使用这些名称定义输出应该是什么样子。我认为最好阅读documentation。在我们的例子中,我们有一个 4 x 3 x 2 张量和一个 4 x 2 张量。所以我们称第一个张量的维度为ijk。这里ik应该被认为和第二张量的维度一样,所以这个可以描述为ik。最后输出应该很明显是ij(它必须是4 x 3张量)。从这个“签名”ijk, ik -> ij 可以清楚地看出,维度 i 被保留,维度 k 必须是“相加/相乘”(标量积)。

    【讨论】:

    • 非常感谢您的帮助。为了将来参考,您是否可以展示一个如何使用torch.einsum 的示例?
    • 我又添加了一段。这不是一个很好的解释,但我希望它能传达它的要点。
    猜你喜欢
    • 2016-12-11
    • 1970-01-01
    • 1970-01-01
    • 2011-05-28
    • 2020-10-14
    • 1970-01-01
    • 2021-05-25
    • 2018-07-09
    相关资源
    最近更新 更多