在pytorch的view函数中,-1是什么意思?

45

正如问题所述,在pytorch的view中,-1是什么意思?

>>> a = torch.arange(1, 17)
>>> a
tensor([  1.,   2.,   3.,   4.,   5.,   6.,   7.,   8.,   9.,  10.,
         11.,  12.,  13.,  14.,  15.,  16.])

>>> a.view(1,-1)
tensor([[  1.,   2.,   3.,   4.,   5.,   6.,   7.,   8.,   9.,  10.,
          11.,  12.,  13.,  14.,  15.,  16.]])

>>> a.view(-1,1)
tensor([[  1.],
        [  2.],
        [  3.],
        [  4.],
        [  5.],
        [  6.],
        [  7.],
        [  8.],
        [  9.],
        [ 10.],
        [ 11.],
        [ 12.],
        [ 13.],
        [ 14.],
        [ 15.],
        [ 16.]])

它 (-1) 会生成额外的维度吗? 它的行为是否与numpy的reshape -1相同?


4
据我所知(我不是专家...),给定的维度-1将适应于其他维度。因此,a.view(-1,1)将生成一个具有维数17x1的向量,因为有17个值 - 所以v.view(1,-1)将生成一个1x17的向量...。 - bene
1
如果你想知道 x.view(-1) 是什么意思,它会将向量展平。为什么?因为它必须构建一个只有1个维度并推断维度的新视图--所以它将其展平。此外,似乎这个操作避免了 .resize() 带来的非常恶心的错误,因为元素的顺序似乎得到了尊重。顺便说一下,pytorch现在有这个用于展平的操作:https://pytorch.org/docs/stable/generated/torch.flatten.html 或者查看我的答案 https://dev59.com/9FUL5IYBdhLWcg3wI1Ep#66500823 - Charlie Parker
6个回答

68

是的,它在 numpy.reshape() 中的行为类似于 -1 ,也就是实际值将被推断,以便视图中的元素数量与原始元素数量相匹配。

例如:

import torch

x = torch.arange(6)

print(x.view(3, -1))      # inferred size will be 2 as 6 / 3 = 2
# tensor([[ 0.,  1.],
#         [ 2.,  3.],
#         [ 4.,  5.]])

print(x.view(-1, 6))      # inferred size will be 1 as 6 / 6 = 1
# tensor([[ 0.,  1.,  2.,  3.,  4.,  5.]])

print(x.view(1, -1, 2))   # inferred size will be 3 as 6 / (1 * 2) = 3
# tensor([[[ 0.,  1.],
#          [ 2.,  3.],
#          [ 4.,  5.]]])

# print(x.view(-1, 5))    # throw error as there's no int N so that 5 * N = 6
# RuntimeError: invalid argument 2: size '[-1 x 5]' is invalid for input with 6 elements

print(x.view(-1, -1, 3))  # throw error as only one dimension can be inferred
# RuntimeError: invalid argument 1: only one dimension can be inferred

如果它本身是-1呢?例如,我面前有这个:correct[:k].view(-1)。在这种特殊情况下,那会做什么? - Charlie Parker
4
@CharlieParker:这将使张量变平(类似于torch.flatten(correct)),即返回一个包含所有元素的单个维度的张量。例如,在我的答案中运行命令后运行x.view(-1)将返回tensor([0., 1., 2., 3., 4., 5.]),即一个大小为6的单一维度的张量。 - benjaminplanche

7

我喜欢Benjamin给出的答案 https://dev59.com/9FUL5IYBdhLWcg3wI1Ep#50793899

是的,在numpy.reshape()中它的行为类似于-1,即将该维度的实际值推断出来,以使视图中的元素数量与原始元素数量匹配。

但我认为可能对你来说不太直观的奇怪情况是只使用一个-1进行调用,即tensor.view(-1)我猜想它的工作方式与以往完全相同,只是因为您要给视图一个单独的数字,所以它假定您想要一个单独的维度。 如果您有tensor.view(-1, Dnew),它将生成一个具有两个维度/索引的张量,但会确保第一个维度根据张量的原始维度具有正确的大小。 假设您有(D1,D2),则Dnew = D1 * D2,然后新维度将为1。

有关可运行代码的真实示例:

import torch

x = torch.randn(1, 5)
x = x.view(-1)
print(x.size())

x = torch.randn(2, 4)
x = x.view(-1, 8)
print(x.size())

x = torch.randn(2, 4)
x = x.view(-1)
print(x.size())

x = torch.randn(2, 4, 3)
x = x.view(-1)
print(x.size())

输出:

torch.Size([5])
torch.Size([1, 8])
torch.Size([8])
torch.Size([24])

历史/背景

在 PyTorch 引入 flatten 层之前(常见情况),我认为一个很好的例子是这段常见的代码:

class Flatten(nn.Module):
    def forward(self, input):
        # input.size(0) usually denotes the batch size so we want to keep that
        return input.view(input.size(0), -1)

对于连续的情况,在这个视图中,x.view(-1) 是一个奇怪的扁平层,但缺少压缩(即添加一个尺寸为1的维度)。添加或删除此压缩通常对代码实际运行非常重要。


例子2

如果你想知道x.view(-1)是什么意思,它会把向量压平。为什么?因为它必须构造一个只有1维的新视图并推断维度 -- 因此它将其压平。此外,这个操作似乎避免了非常严重的错误.resize()带来的问题,因为元素的顺序似乎得到了尊重。顺便说一下,pytorch现在有这个操作可以用于压平:https://pytorch.org/docs/stable/generated/torch.flatten.html

#%%
"""
Summary: view(-1, ...) keeps the remaining dimensions as give and infers the -1 location such that it respects the
original view of the tensor. If it's only .view(-1) then it only has 1 dimension given all the previous ones so it ends
up flattening the tensor.

ref: my answer https://dev59.com/9FUL5IYBdhLWcg3wI1Ep#66500823
"""
import torch

x = torch.arange(6)
print(x)

x = x.reshape(3, 2)
print(x)

print(x.view(-1))

输出

tensor([0, 1, 2, 3, 4, 5])
tensor([[0, 1],
        [2, 3],
        [4, 5]])
tensor([0, 1, 2, 3, 4, 5])

看到原始张量被返回了!


请注意,.view() 似乎可以避免 resize 常常带来的麻烦 bug。 - Charlie Parker

2
我认为这与np.reshape类似:
新形状应与原始形状兼容。 如果是整数,则结果将是该长度的1-D数组。一个形状维度可以是-1, 在这种情况下,该值将从数组的长度和剩余维度中推断出来
如果有a = torch.arange(1, 18),您可以像a.view(-1,6)a.view(-1,9)a.view(3,-1)等不同方式查看它。

如果我们有一个单独的-1怎么办?例如,我面前有这个:correct[:k].view(-1)。在这种特殊情况下,它会做什么? - Charlie Parker

1

来自 PyTorch 文档

>>> x = torch.randn(4, 4)
>>> x.size()
torch.Size([4, 4])
>>> y = x.view(16)
>>> y.size()
torch.Size([16])
>>> z = x.view(-1, 8)  # the size -1 is inferred from other dimensions
>>> z.size()
torch.Size([2, 8])

1
如果我们有一个单独的-1怎么办?例如,我面前有这个:correct[:k].view(-1)。在这种特殊情况下,它会做什么? - Charlie Parker

0

-1 是 PyTorch 中的一个别名,表示“在已经指定其他维度的情况下推断此维度”(即原始乘积除以新乘积)。这是从 numpy.reshape() 中采用的约定。

因此,在示例中 t.view(1,17) 等同于 t.view(1,-1)t.view(-1,17)


0

-1代表2,例如,如果你有

>>> a = torch.rand(4,4)
>>> a.size()
torch.size([4,4])
>>> y = x.view(16)
>>> y.size()
torch.size([16])
>>> z = x.view(-1,8) # -1 is generally inferred as 2  i.e (2,8)
>>> z.size()
torch.size([2,8])

如果我们有一个单独的-1怎么办?例如,我面前有这个:correct[:k].view(-1)。在这种特殊情况下,它会做什么? - Charlie Parker

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接