Was ist der Unterschied zwischen Umformung und Ansicht in Pytorch?

83

In numpy verwenden wir ndarray.reshape()zum Umformen eines Arrays.

Mir ist aufgefallen, dass in Pytorch Menschen torch.view(...)für den gleichen Zweck verwenden, aber zur gleichen Zeit gibt es auch eine torch.reshape(...)existierende.

Ich frage mich also, was die Unterschiede zwischen ihnen sind und wann ich einen von beiden verwenden sollte.

Lifu Huang
quelle

Antworten:

89

torch.viewexistiert schon lange. Es wird ein Tensor mit der neuen Form zurückgegeben. Der zurückgegebene Tensor teilt die zugrunde liegenden Daten mit dem ursprünglichen Tensor. Siehe die Dokumentation hier .

Andererseits scheint es, dass torch.reshape es kürzlich in Version 0.4 eingeführt wurde . Laut dem Dokument wird diese Methode

Gibt einen Tensor mit denselben Daten und der gleichen Anzahl von Elementen wie die Eingabe zurück, jedoch mit der angegebenen Form. Wenn möglich, ist der zurückgegebene Tensor eine Ansicht der Eingabe. Andernfalls handelt es sich um eine Kopie. Aneinandergrenzende Eingaben und Eingaben mit kompatiblen Schritten können ohne Kopieren umgeformt werden, Sie sollten sich jedoch nicht auf das Kopier- oder Anzeigeverhalten verlassen.

Dies bedeutet, dass torch.reshapemöglicherweise eine Kopie oder eine Ansicht des ursprünglichen Tensors zurückgegeben wird. Darauf können Sie nicht zählen, um eine Ansicht oder eine Kopie zurückzugeben. Nach Angaben des Entwicklers:

Wenn Sie eine Kopie benötigen, verwenden Sie clone (), wenn Sie dieselbe Speicheranwendungsansicht () benötigen. Die Semantik von reshape () ist, dass es den Speicher gemeinsam nutzen kann oder nicht und Sie es vorher nicht wissen.

Ein weiterer Unterschied besteht darin, dass reshape()sowohl mit zusammenhängenden als auch mit nicht zusammenhängenden Tensoren gearbeitet werden view()kann, während nur mit zusammenhängenden Tensoren gearbeitet werden kann. Siehe auch hier über die Bedeutung von contiguous.

jdhao
quelle
28
Vielleicht ist es hilfreich zu betonen, dass torch.view nur mit zusammenhängenden Tensoren arbeiten kann, während torch.reshape auch mit beiden arbeiten kann.
p13rr0m
6
@pierrom zusammenhängend hier bezieht sich auf Tensoren, die im zusammenhängenden Speicher gespeichert sind oder etwas anderes?
gokul_uf
3
@gokul_uf Ja, Sie können einen Blick auf die hier geschriebene Antwort werfen
MBT
bedeutet der Ausdruck "eine Ansicht eines Tensors" in Pytorch?
Charlie Parker
42

Obwohl beide torch.viewund torch.reshapezur Umformung von Tensoren verwendet werden, sind hier die Unterschiede zwischen ihnen.

  1. Wie der Name schon sagt, wird torch.viewlediglich eine Ansicht des ursprünglichen Tensors erstellt. Der neue Tensor wird immer seine Daten mit der Original - Tensor teilen. Dies bedeutet, dass sich der umgeformte Tensor ändert, wenn Sie den ursprünglichen Tensor ändern, und umgekehrt.
>>> z = torch.zeros(3, 2)
>>> x = z.view(2, 3)
>>> z.fill_(1)
>>> x
tensor([[1., 1., 1.],
        [1., 1., 1.]])
  1. Um sicherzustellen, dass der neue Tensor seine Daten immer mit dem Original teilt, werden torch.viewden Formen der beiden Tensoren einige Kontiguitätsbeschränkungen auferlegt [ docs ]. Meistens ist dies kein Problem, torch.viewwirft aber manchmal einen Fehler aus, selbst wenn die Formen der beiden Tensoren kompatibel sind. Hier ist ein berühmtes Gegenbeispiel.
>>> 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.reshapelegt keine Kontiguitätsbeschränkungen fest, garantiert aber auch nicht den Datenaustausch. Der neue Tensor kann eine Ansicht des ursprünglichen Tensors sein, oder er kann insgesamt ein neuer Tensor sein.
>>> 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:
Wenn Sie nur Tensoren umformen möchten, verwenden Sie torch.reshape. Wenn Sie auch Bedenken hinsichtlich der Speichernutzung haben und sicherstellen möchten, dass die beiden Tensoren dieselben Daten verwenden, verwenden Sie torch.view.

nikhilweee
quelle
Vielleicht bin ich es nur, aber ich war verwirrt darüber, dass die Kontiguität der entscheidende Faktor zwischen dem Zeitpunkt der Umgestaltung und dem Nichtaustausch von Daten ist. Aus meinen eigenen Experimenten geht hervor, dass dies nicht der Fall ist. (Ihre xund yoben sind beide zusammenhängend). Vielleicht kann das geklärt werden? Vielleicht wäre ein Kommentar dazu hilfreich, wann eine Umformung kopiert und wann nicht?
RMurphy
6

Tensor.reshape()ist robuster. Es funktioniert auf jedem Tensor, während es Tensor.view()nur auf Tensor funktioniert, two t.is_contiguous()==True.

Nicht zusammenhängend und zusammenhängend zu erklären, ist eine andere Zeitgeschichte, aber Sie können den Tensor immer zusammenhängend machen, wenn tSie anrufen, t.contiguous()und dann können Sie view()ohne Fehler anrufen .

Prosti
quelle