pytorchでの形状変更とビューの違いは何ですか?


83

numpyではndarray.reshape()、配列の再形成に使用します。

pytorchでは、人々torch.view(...)が同じ目的で使用していることに気づきましたが、同時に、torch.reshape(...)既存のものもあります。

だから私はそれらの違いは何ですか、そして私はそれらのどちらかをいつ使うべきか疑問に思っていますか?

回答:


88

torch.view長い間存在してきました。新しい形状のテンソルを返します。返されたテンソルは、元のテンソルと基礎となるデータを共有します。こちらのドキュメントを参照してください

一方、torch.reshape 最近バージョン0.4で導入されたようです。文書によると、この方法は

入力と同じデータと要素数で、指定された形状のテンソルを返します。可能な場合、返されるテンソルは入力のビューになります。それ以外の場合は、コピーになります。連続する入力と互換性のあるストライドを持つ入力は、コピーせずに再形成できますが、コピーと表示の動作に依存しないでください。

これはtorch.reshape、元のテンソルのコピーまたはビューを返す可能性があることを意味します。ビューまたはコピーを返すことを期待することはできません。開発者によると:

コピーが必要な場合はclone()を使用し、同じストレージが必要な場合はview()を使用します。reshape()のセマンティクスは、ストレージを共有する場合と共有しない場合があり、事前にわからないことです。

もう1つの違いは、reshape()隣接テンソルと非隣接テンソルの両方view()で操作できるのに対し、隣接テンソルでのみ操作できることです。の意味についてもこちらをご覧くださいcontiguous


28
torch.viewは隣接するテンソルでのみ動作できるのに対し、torch.reshapeは両方で動作できることを強調することも役立つ場合があります。
p13rr0m 2018

6
@pierrom連続ここでは、連続メモリまたは他の何かに格納されているテンソルを指しますか?
gokul_uf 2018

3
@gokul_ufはい、ここに書かれている答えを見ることができます:stackoverflow.com/questions/48915810/pytorch-contiguous
MBT

「テンソルのビュー」というフレーズは、pytorchで意味しますか?
チャーリーパーカー

42

torch.viewtorch.reshapeは両方ともテンソルの形状を変更するために使用されますが、ここにそれらの違いがあります。

  1. 名前が示すように、元のテンソルのビューtorch.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に、2つのテンソルの形状にいくつかの隣接制約を課します[ドキュメント]。多くの場合、これは問題ではありませんtorch.viewが、2つのテンソルの形状に互換性がある場合でも、エラーがスローされることがあります。これが有名な反例です。
>>> 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。メモリ使用量も気になり、2つのテンソルが同じデータを共有するようにしたい場合は、を使用しますtorch.view


私だけかもしれませんが、データを共有する場合と共有しない場合の決定要因は、隣接性であると考えることに混乱しました。私自身の実験から、そうではないようです。(あなたxy上記は両方とも隣接しています)。おそらくこれは明らかにすることができますか?おそらく、リシェイプがコピーする場合としない場合についてのコメントが役立つでしょうか?
RMurphy

6

Tensor.reshape()より堅牢です。一方でそれは、任意のテンソル上で動作しますTensor.view()テンソルでのみ動作しますt場所t.is_contiguous()==True

非連続と連続について説明することは別のタイムストーリーですが、いつでもテンソルをt連続させるt.contiguous()ことができview()ます。そうすれば、エラーなしで呼び出すことができます。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.