PyTorch:reshape() 和 view() 方法之间的区别

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

reshape 和 view 方法有什么区别,为什么我们需要,我正在使用 pytorch 张量并致力于改变数据的形状,然后我开始了解这两个函数。如果我们使用较少的资源处理大数据,那么对内存的影响是什么?哪些消耗更多的内存,哪些成本更高。

x = torch.tensor([1, 2, 3, 4, 5], dtype = torch.float32)
x = x.reshape(-1, 1)

以及查看方法

x = x.view(x.shape[0], 1)

有什么区别以及我应该使用哪个

arrays pytorch dataset torch
1个回答
0
投票

简短的回答:当重塑连续张量时,两种方法都会执行相同的操作(即提供给定张量的新视图),因此可以互换使用。当重塑非连续张量时,

reshape()
将从给定张量复制必要的内存部分以生成结果张量,而
view()
将失败并出现
RuntimeError

长答案

主要区别在于

torch.Tensor.reshape()
torch.Tensor.view()
如何处理非连续张量。

要理解差异,我们需要了解什么是连续张量,以及什么是张量的视图

  • A 连续张量 是一个张量,其值存储在单个、不间断的(因此是“连续的”)内存中。非连续张量的内存布局可能有间隙。
  • 生成张量的视图意味着重新解释其内存中值的排列。想象一下存储 16 个值的内存:我们可以将其解释为 16 元素一维张量或 4×4 元素二维张量。两种解释都可以使用相同的底层内存。通过使用视图并重新解释内存布局,我们可以从同一块内存创建不同形状的张量,这样可以避免重复并节省内存。

现在回到这两种方法:

  • 如果应用于连续张量,
    reshape()
    view()
    都会生成给定张量内存的新视图,这样就避免了重复。
  • 如果应用于非连续张量,将无法创建视图。两种方法处理这种情况的方式不同:
    • reshape()
      方法将复制必要的内存并返回一个张量,其内存不会与给定的张量共享。
    • view()
      方法将产生一个
      RuntimeError

我们可以用下面的代码来演示这一点:

from torch import arange

contiguous = arange(16).view(4, 4)             # Create contiguous 4×4 tensor
noncontiguous = arange(20).view(4, 5)[:, :4]   # Create non-contiguous 4×4 tensor

contiguous_r = contiguous.reshape(16)          # OK: produces a 1-d view
assert contiguous_r.data_ptr() == contiguous.data_ptr()  # Same memory used

contiguous_v = contiguous.view(16)             # OK: produces a 1-d view
assert contiguous_v.data_ptr() == contiguous.data_ptr()  # Same memory used

noncontiguous_r = noncontiguous.reshape(16)    # OK: produces a new 1-d array
assert noncontiguous_r.data_ptr() != noncontiguous.data_ptr()  # New memory used

noncontiguous_v = noncontiguous.view(16)       # ERROR: cannot produce view

最后一行将产生 RuntimeError:视图大小与输入张量的大小和步幅不兼容(至少一个维度跨越两个连续的子空间)。使用 .reshape(...) 代替。

也许在这一点上,我还应该提到张量的 stride 是什么:本质上,它是告诉我们如何将张量的索引映射到其底层内存的信息。您将找到有关步幅的更多信息,以及有关连续张量与非连续张量的一般信息,例如,在 PyTorch 论坛的此讨论中。

至于你的问题,我应该使用哪个?:

  • 如果您只是想确保在重塑张量时收到结果,我建议使用
    reshape()
    :对于连续张量,
    reshape()
    将执行与
    view()
    完全相同的操作(即,生成关于给定的张量并且不复制其内存)。对于非连续张量,
    reshape()
    将是唯一能产生结果的方法,而
    view()
    将失败(见上文)。
  • 如果您确实确定要重塑的张量是连续的并且想要捕捉它们不连续的情况,我建议使用
    view()
    。例如,如果您在内存不足的情况下工作,因此宁愿失败也不愿复制内存,这可能是有意义的。
    view()
    的另一个用例不是重新解释形状,而是重新解释底层内存的数据类型。我想这不是您的用例,但您可以在我上面链接的
    view()
    文档中找到更多相关信息。
© www.soinside.com 2019 - 2024. All rights reserved.