Pytorch从最后一个张量维中选择值,从另一个张量维中选择索引,维数较小

时间:2019-03-16 11:36:51

标签: pytorch

我有一个具有三个维度的张量a。第一维对应于小批量大小,第二维对应于序列长度,而第三维对应于特征维。例如,

>>> a = torch.arange(1, 13, dtype=torch.float).view(2,2,3)  # Consider the values of a to be random
>>> a
tensor([[[ 1.,  2.,  3.],
         [ 4.,  5.,  6.]],

        [[ 7.,  8.,  9.],
         [10., 11., 12.]]])

我有第二个二维张量。它的第一维对应于小批量的大小,其第二维对应于序列的长度。它包含a第三维的索引范围内的值。 a的第三维尺寸为3,因此b可以包含值0、1或2。例如,

>>> b = torch.LongTensor([[0, 2],[1,0]])
>>> b
tensor([[0, 2],
        [1, 0]])

我想获取张量c,其形状为b,并包含a引用的所有b值。 在较高的情况下,我希望拥有:

c = torch.empty(2,2)
c[0,0] = a[0, 0, b[0,0]]
c[1,0] = a[1, 0, b[1,0]]
c[0,1] = a[0, 1, b[0,1]]
c[1,1] = a[1, 1, b[1,1]]

>>> c
tensor([[ 1.,  5.],
        [ 8., 10.]])

如何快速创建张量c?此外,我还希望c是可区分的(能够使用.backprob())。我对pytorch不太熟悉,所以不确定是否存在此版本。

作为替代方案,除了c具有与b相同的形状外,我还可以使用具有c相同形状的a,只有零,但是在b所引用的位置。然后,我可以将ac相乘以获得一个可微的张量。

就像这样:

c = torch.zeros(2,2,3, dtype=torch.float)
c[0,0,b[0,0]] = 1
c[1,0,b[1,0]] = 1
c[0,1,b[0,1]] = 1
c[1,1,b[1,1]] = 1

>>> a*c
tensor([[[ 1.,  0.,  0.],
         [ 0.,  5.,  0.]],

        [[ 0.,  8.,  0.],
         [10.,  0.,  0.]]])

1 个答案:

答案 0 :(得分:1)

让我们先声明必要的变量:(请注意requires_grad的初始化过程中的a,我们将使用它来确保可区分性)

a = torch.arange(1,13,dtype=torch.float32,requires_grad=True).reshape(2,2,3)
b = torch.LongTensor([[0, 2],[1,0]])

让我们重塑a并压缩小批量和序列尺寸:

temp = a.reshape(-1,3)

所以temp现在看起来像:

tensor([[ 1.,  2.,  3.],
    [ 4.,  5.,  6.],
    [ 7.,  8.,  9.],
    [10., 11., 12.]], grad_fn=<AsStridedBackward>)

请注意,b的每个值都可以在temp的每一行中使用,以获取所需的输出。现在我们要做:

c = temp[range(len(temp )),b.view(-1)].view(b.size())

请注意,我们如何索引temprange(len(temp ))以选择每一行,以及如何对1D bb.view(-1)进行索引以获取相应的列。最后,.view(b.size())使此数组的大小与b相同。

如果我们现在打印c

tensor([[ 1.,  6.],
    [ 8., 10.]], grad_fn=<ViewBackward>)

grad_fn=..的存在表明c需要渐变,即其可微。