torch.view
istnieje 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.reshape
moż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
.
Chociaż oba
torch.view
itorch.reshape
są używane do zmiany kształtu tensorów, oto różnice między nimi.torch.view
tworzy 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.]])
torch.view
nakłada pewne ograniczenia ciągłości na kształty dwóch tensorów [ docs ]. Najczęściej nie jest to problemem, ale czasamitorch.view
generuje 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().
torch.reshape
nie 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żyjtorch.view
.źródło
x
iy
powyż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?Tensor.reshape()
jest bardziej wytrzymały. Będzie działać na każdym tensorze, podczas gdyTensor.view()
działa tylko na tensorze,t
gdziet.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
t
ciągły, gdy wywołasz,t.contiguous()
a następnie możesz wywołaćview()
bez błędu.źródło