在pytorch中重塑和视图之间有什么区别?

时间:2018-04-04 05:09:50

标签: pytorch

在numpy中,我们使用ndarray.reshape()来重塑数组。

我注意到在pytorch中,人们使用torch.view(...)用于同一目的,但同时也存在torch.reshape(...)

所以我想知道他们和我应该使用其中任何一个之间的区别是什么?

3 个答案:

答案 0 :(得分:33)

torch.view已存在很长时间了。它将返回具有新形状的张量。返回的张量将与原始张量共享下属数据。 请参阅documentation here

另一方面,似乎是torch.reshape has been introduced recently in version 0.4。根据{{​​3}},此方法将

  

返回一个张量,该张量具有与输入相同的数据和元素数,但具有指定的形状。如果可能,返回的张量将是输入的视图。否则,它将是一个副本。具有兼容步幅的连续输入和输入可以在不复制的情况下进行重新整形,但您不应该依赖于复制与查看行为。

这意味着torch.reshape可能会返回原始张量的副本或视图。您不能指望它返回视图或副本。根据开发人员的说法:

  

如果您需要副本,请使用clone(),如果您需要相同的存储使用视图()。 reshape()的语义是它可能会或可能不会共享存储,而您事先并不知道。

答案 1 :(得分:4)

尽管torch.viewtorch.reshape都用于重整张量,但这是它们之间的区别。

  1. 顾名思义,torch.view仅创建原始张量的 view 。新的张量将始终与原始张量共享。这意味着,如果您更改原始张量,则重塑后的张量将会更改,反之亦然。
>>> z = torch.zeros(3, 2)
>>> x = z.view(2, 3)
>>> z.fill_(1)
>>> x
tensor([[1., 1., 1.],
        [1., 1., 1.]])
  1. 为确保新张量始终与原始张量共享数据,torch.view对两个张量[docs]的形状施加了一些连续性约束。通常这不是一个问题,但是即使两个张量的形状兼容,torch.view有时也会引发错误。这是一个著名的反例。
>>> z = torch.zeros(3, 2)
>>> y = z.t()
>>> y.size()
torch.Size([2, 3])
>>> y.view(6)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
RuntimeError: invalid argument 2: view size is not compatible with input tensor's
size and stride (at least one dimension spans across two contiguous subspaces).
Call .contiguous() before .view().
  1. torch.reshape不施加任何连续性约束,但也不保证数据共享。新的张量可以是原始张量的视图,也可以是新的张量。
>>> z = torch.zeros(3, 2)
>>> y = z.reshape(6)
>>> x = z.t().reshape(6)
>>> z.fill_(1)
tensor([[1., 1.],
        [1., 1.],
        [1., 1.]])
>>> y
tensor([1., 1., 1., 1., 1., 1.])
>>> x
tensor([0., 0., 0., 0., 0., 0.])

TL; DR:
如果只想重塑张量,请使用torch.reshape。如果您还担心内存使用情况,并且要确保两个张量共享相同的数据,请使用torch.view

答案 2 :(得分:0)

Tensor.reshape()更强大。它适用于任何张量,而Tensor.view()仅适用于张量t,其中t.is_contiguous()==True

要解释不连续和连续是另一回事,但始终可以使张量t连续,只要调用t.contiguous(),然后就可以调用view()而不会出错