我有一个具有三个维度的张量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
所引用的位置。然后,我可以将a
和c
相乘以获得一个可微的张量。
就像这样:
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.]]])
答案 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())
请注意,我们如何索引temp
,range(len(temp ))
以选择每一行,以及如何对1D b
即b.view(-1)
进行索引以获取相应的列。最后,.view(b.size())
使此数组的大小与b
相同。
如果我们现在打印c
:
tensor([[ 1., 6.],
[ 8., 10.]], grad_fn=<ViewBackward>)
grad_fn=..
的存在表明c
需要渐变,即其可微。