PyTorch 中 `view()` 的 `-1` 是什么意思?

问题描述 投票:0回答:7

正如问题所说,

-1
view()
在PyTorch中做什么?

>>> 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.]])

PyTorch 中

-1
view()
是否会生成额外维度? PyTorch 中
-1
view()
与 NumPy 中
-1
reshape()
的行为是否相同?

python pytorch reshape tensor dimensions
7个回答
69
投票

是的,它的行为确实类似于

-1
中的
numpy.reshape()
,即,将推断该维度的实际值,以便视图中的元素数量与原始元素数量相匹配。

例如:

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

7
投票

我喜欢本杰明给出的答案https://stackoverflow.com/a/50793899/1601580

是的,它的行为确实类似于 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中常见的情况扁平化层是官方添加的就是这个常见的代码):

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://stackoverflow.com/a/66500823/1601580
"""
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])

看到原始张量被返回了!


2
投票

我想这与

np.reshape
类似:

新形状应与原始形状兼容。如果是整数,则结果将是该长度的一维数组。一种形状尺寸可以是-1。在这种情况下,该值是根据数组的长度和剩余维度推断出来的

如果您有

a = torch.arange(1, 18)
,您可以通过多种方式查看它,例如
a.view(-1,6)
a.view(-1,9)
a.view(3,-1)


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])

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])

0
投票

-1
是 PyTorch 的别名,表示“在其他维度均已指定的情况下推断此维度”(即原始乘积除以新乘积的商)。这是取自
numpy.reshape()
的约定。

因此,示例中的

t.view(1,17)
相当于
t.view(1,-1)
t.view(-1,17)


0
投票

-1
设置为view()的第一个数字可以自动调整形状,因此您无需将
12
2
3
6
设置为第一个数字,如下所示。 *-1 仅可用作第一个数字:

import torch

my_tensor = torch.tensor([[0, 1, 2], [3, 4, 5], [6, 7, 8], [9, 10, 11]])
                         # The size is [4, 3].
my_tensor.view((12,))
my_tensor.view((-1,))
my_tensor.view(12)
my_tensor.view(-1)
# tensor([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11])
# The size is [12].

my_tensor.view((2, 6))
my_tensor.view((-1, 6))
my_tensor.view(2, 6)
my_tensor.view(-1, 6)
# tensor([[0, 1, 2, 3, 4, 5], [6, 7, 8, 9, 10, 11]])
# The size is [2, 6].

my_tensor.view((3, 4))
my_tensor.view((-1, 4))
my_tensor.view(3, 4)
my_tensor.view(-1, 4)
# tensor([[0, 1, 2, 3], [4, 5, 6, 7], [8, 9, 10, 11]])
# The size is [3, 4].

my_tensor.view((6, 2))
my_tensor.view((-1, 2))
my_tensor.view(6, 2)
my_tensor.view(-1, 2)
# tensor([[0, 1], [2, 3], [4, 5], [6, 7], [8, 9], [10, 11]])
# The size is [6, 2].
最新问题
© www.soinside.com 2019 - 2025. All rights reserved.