.view()对x张量有什么作用?负值是什么意思?

x = x.view(-1, 16 * 5 * 5)

当前回答

我真的很喜欢@Jadiel de Armas的例子。

我想添加一个关于.view(…)元素如何排序的小见解。

对于形状为(a,b,c)的张量,其元素的顺序为 由编号系统确定:其中第一个数字有 数字,第二个数字是b,第三个数字是c。 由.view(…)返回的新张量中元素的映射 保持原始张量的阶数。

其他回答

View()通过“拉伸”或“挤压”张量的元素来重新塑造你指定的形状:


view()如何工作?

首先让我们看看什么是张量:

Tensor and its underlying storage e.g. the right-hand tensor (shape (3,2)) can be computed from the left-hand one with t2 = t1.view(3,2)

在这里你可以看到PyTorch通过添加shape和stride属性将底层的连续内存块转换为类似矩阵的对象来创建一个张量:

形状表示每个维度的长度 Stride表示在到达每个维度的下一个元素之前需要在内存中执行多少步

View (dim1,dim2,…)返回相同底层信息的视图,但被重新塑造为形状为dim1 x dim2 x…(通过修改形状和stride属性)。

注意,这隐含地假设新维和旧维有相同的乘积(即旧张量和新张量有相同的体积)。


PyTorch -1

-1是PyTorch的别名,表示“在其他维度都已指定的情况下推断该维度”(即原产品与新产品的商)。这是一个来自numpy.重塑()的约定。

因此,本例中的t1.view(3,2)将等效于t1.view(3,-1)或t1.view(-1,2)。

参数-1是什么意思?

您可以将-1读取为动态参数数或“任何东西”。因此,在view()中只能有一个参数-1。

如果你问x.view(-1,1),这将输出张量形状[任何东西,1]取决于x中的元素数量。例如:

import torch
x = torch.tensor([1, 2, 3, 4])
print(x,x.shape)
print("...")
print(x.view(-1,1), x.view(-1,1).shape)
print(x.view(1,-1), x.view(1,-1).shape)

将输出:

tensor([1, 2, 3, 4]) torch.Size([4])
...
tensor([[1],
        [2],
        [3],
        [4]]) torch.Size([4, 1])
tensor([[1, 2, 3, 4]]) torch.Size([1, 4])

权重。重塑(a, b)将返回一个新的张量,其数据与大小为(a, b)的权重相同,因为它将数据复制到内存的另一部分。

权重。Resize_ (a, b)返回不同形状的相同张量。然而,如果新的形状产生的元素比原来的张量少,一些元素将从张量中删除(但不从内存中删除)。如果新的形状产生的元素比原来的张量更多,那么新的元素将在内存中未初始化。

权重。视图(a, b)将返回一个新的张量,其数据与权重(a, b)相同

我发现x.view(- 1,16 * 5 * 5)等价于x.flatten(1),其中参数1表示扁平化过程从第一个维度开始(不是扁平化'样本'维度) 如您所见,后一种用法在语义上更清楚,也更容易使用,因此我更喜欢flatten()。

我们来做一些例题,从简单到难。

The view method returns a tensor with the same data as the self tensor (which means that the returned tensor has the same number of elements), but with a different shape. For example: a = torch.arange(1, 17) # a's shape is (16,) a.view(4, 4) # output below 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 [torch.FloatTensor of size 4x4] a.view(2, 2, 4) # output below (0 ,.,.) = 1 2 3 4 5 6 7 8 (1 ,.,.) = 9 10 11 12 13 14 15 16 [torch.FloatTensor of size 2x2x4] Assuming that -1 is not one of the parameters, when you multiply them together, the result must be equal to the number of elements in the tensor. If you do: a.view(3, 3), it will raise a RuntimeError because shape (3 x 3) is invalid for input with 16 elements. In other words: 3 x 3 does not equal 16 but 9. You can use -1 as one of the parameters that you pass to the function, but only once. All that happens is that the method will do the math for you on how to fill that dimension. For example a.view(2, -1, 4) is equivalent to a.view(2, 2, 4). [16 / (2 x 4) = 2] Notice that the returned tensor shares the same data. If you make a change in the "view" you are changing the original tensor's data: b = a.view(4, 4) b[0, 2] = 2 a[2] == 3.0 False Now, for a more complex use case. The documentation says that each new view dimension must either be a subspace of an original dimension, or only span d, d + 1, ..., d + k that satisfy the following contiguity-like condition that for all i = 0, ..., k - 1, stride[i] = stride[i + 1] x size[i + 1]. Otherwise, contiguous() needs to be called before the tensor can be viewed. For example: a = torch.rand(5, 4, 3, 2) # size (5, 4, 3, 2) a_t = a.permute(0, 2, 3, 1) # size (5, 3, 2, 4) # The commented line below will raise a RuntimeError, because one dimension # spans across two contiguous subspaces # a_t.view(-1, 4) # instead do: a_t.contiguous().view(-1, 4) # To see why the first one does not work and the second does, # compare a.stride() and a_t.stride() a.stride() # (24, 6, 2, 1) a_t.stride() # (24, 2, 1, 6) Notice that for a_t, stride[0] != stride[1] x size[1] since 24 != 2 x 3