Jaka jest różnica między zmianą kształtu a widokiem w pytorchu?


93

W numpy używamy ndarray.reshape()do przekształcania tablicy.

Zauważyłem, że w pytorchu ludzie używają torch.view(...)do tego samego celu, ale jednocześnie jest też taki torch.reshape(...)istniejący.

Zastanawiam się więc, jakie są między nimi różnice i kiedy powinienem użyć któregokolwiek z nich?

Odpowiedzi:


99

torch.viewistnieje od dawna. Zwróci tensor o nowym kształcie. Zwrócony tensor będzie współdzielił dane podstawowe z oryginalnym tensorem. Zobacz dokumentację tutaj .

Z drugiej strony wydaje się, że torch.reshape została wprowadzona niedawno w wersji 0.4 . Zgodnie z dokumentem ta metoda będzie

Zwraca tensor z tymi samymi danymi i liczbą elementów co dane wejściowe, ale o określonym kształcie. Jeśli to możliwe, zwrócony tensor będzie widokiem wejścia. W przeciwnym razie będzie to kopia. Ciągłe dane wejściowe i dane wejściowe ze zgodnymi przebiegami można zmieniać bez kopiowania, ale nie należy polegać na zachowaniu kopiowania i przeglądania.

Oznacza to, że torch.reshapemoże zwrócić kopię lub widok oryginalnego tensora. Nie możesz liczyć na to, że zwrócimy widok lub kopię. Według dewelopera:

jeśli potrzebujesz kopii, użyj clone (), jeśli potrzebujesz tego samego miejsca na przechowywanie view (). Semantyka reshape () polega na tym, że może, ale nie musi, współużytkować pamięć masową, o czym nie wiesz z góry.

Inną różnicą jest to, że reshape()może działać zarówno na ciągłym, jak i nieciągłym tensorze, podczas gdy view()może działać tylko na ciągłym tensorze. Zobacz także tutaj znaczenie contiguous.


30
Może podkreślenie, że torch.view może działać tylko na sąsiadujących tensorach, podczas gdy torch.reshape może również działać na obu.
p13rr0m

6
@pierrom ciągły tutaj odnoszący się do tensorów, które są przechowywane w ciągłej pamięci lub coś innego?
gokul_uf

3
@gokul_uf Tak, możesz spojrzeć na odpowiedź zapisaną tutaj: stackoverflow.com/questions/48915810/pytorch-contiguous
MBT

czy wyrażenie „widok tensora” oznacza w pytorchu?
Charlie Parker

Pomocne będzie wyjaśnienie, czym są „zgodne kroki”. Dzięki!
bruin

45

Chociaż oba torch.viewi torch.reshapesą używane do zmiany kształtu tensorów, oto różnice między nimi.

  1. Jak sama nazwa wskazuje, torch.viewtworzy jedynie widok oryginalnego tensora. Nowy tensor zawsze będzie udostępniać swoje dane oryginalnemu tensorowi. Oznacza to, że jeśli zmienisz oryginalny tensor, zmieniony tensor ulegnie zmianie i odwrotnie.
>>> z = torch.zeros(3, 2)
>>> x = z.view(2, 3)
>>> z.fill_(1)
>>> x
tensor([[1., 1., 1.],
        [1., 1., 1.]])
  1. Aby upewnić się, że nowy tensor zawsze dzieli swoje dane z oryginałem, torch.viewnakłada pewne ograniczenia ciągłości na kształty dwóch tensorów [ docs ]. Najczęściej nie jest to problemem, ale czasami torch.viewgeneruje błąd, nawet jeśli kształty dwóch tensorów są zgodne. Oto słynny kontrprzykład.
>>> 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.reshapenie nakłada żadnych ograniczeń związanych z ciągłością, ale także nie gwarantuje udostępniania danych. Nowy tensor może być widokiem oryginalnego tensora lub może to być całkowicie nowy tensor.
>>> 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:
Jeśli chcesz tylko zmienić kształt tensorów, użyj torch.reshape. Jeśli obawiasz się również użycia pamięci i chcesz mieć pewność, że te dwa tensory współużytkują te same dane, użyj torch.view.


1
Może to tylko ja, ale pomyliłem się, myśląc, że ciągłość jest decydującym czynnikiem między tym, kiedy zmiana kształtu udostępnia dane, a kiedy ich nie udostępnia. Z moich własnych eksperymentów wynika, że ​​tak nie jest. (Twoje xi ypowyżej są ciągłe). Może da się to wyjaśnić? Może przydałby się komentarz dotyczący tego, kiedy zmiana kształtu działa, a kiedy nie kopiuje?
RMurphy

7

Tensor.reshape()jest bardziej wytrzymały. Będzie działać na każdym tensorze, podczas gdy Tensor.view()działa tylko na tensorze, tgdzie t.is_contiguous()==True.

Wyjaśnienie kwestii nieciągłych i ciągłych jest inną historią czasu, ale zawsze możesz sprawić, że tensor będzie tciągły, gdy wywołasz, t.contiguous()a następnie możesz wywołać view()bez błędu.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.