У чому різниця між зміною форми та видом у pytorch?


93

У numpy ми використовуємо ndarray.reshape()для переформування масиву.

Я помітив, що в pytorch люди використовують torch.view(...)з тією ж метою, але в той же час існує і така torch.reshape(...).

Тому мені цікаво, в чому різниця між ними і коли я повинен використовувати будь-який з них?

Відповіді:


99

torch.viewіснує вже давно. Він поверне тензор з новою формою. Повернутий тензор поділиться базовими даними з оригінальним тензором. Дивіться документацію тут .

З іншого боку, схоже, torch.reshape нещодавно він був представлений у версії 0.4 . Згідно з документом , цей метод буде

Повертає тензор з тими ж даними та кількістю елементів, що і вхідні дані, але із заданою формою. Коли це можливо, повернутий тензор буде виглядом вводу. В іншому випадку це буде копія. Суміжні входи та входи із сумісними кроками можна змінити без копіювання, але ви не повинні залежати від поведінки копіювання та перегляду.

Це означає, що torch.reshapeможе повернутися копія або вигляд оригінального тензора. Ви не можете розраховувати на те, що повернете подання або копію. За словами розробника:

якщо вам потрібна копія, використовуйте clone (), якщо вам потрібен той самий вид використання сховища (). Семантика reshape () полягає в тому, що він може або не може спільно використовувати сховище, і ви не знаєте заздалегідь.

Інша відмінність полягає в тому, що він reshape()може діяти як на суміжний, так і на несуміжний тензор, тоді як view()може працювати лише на суміжний тензор. Також дивіться тут про значення contiguous.


30
Можливо, підкреслення того, що torch.view може працювати лише на суміжних тензорах, тоді як torch.reshape може працювати на обох, також може бути корисним.
p13rr0m

6
@pierrom суміжний тут, маючи на увазі тензори, які зберігаються у суміжній пам'яті чи щось інше?
gokul_uf

3
@gokul_uf Так, ви можете поглянути на відповідь, написану тут: stackoverflow.com/questions/48915810/pytorch-contiguous
MBT

чи означає фраза "погляд на тензор" у піторсі?
Чарлі Паркер,

Буде корисним пояснити, що таке "сумісні кроки". Дякую!
bruin

45

Хоча обидва torch.viewі torch.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накладає певні обмеження на суміжність форм двох тензорів [ документи ]. Найчастіше це не турбує, але іноді torch.viewвидає помилку, навіть якщо форми двох тензорів сумісні. Ось відомий зустрічний приклад.
>>> 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. Якщо ви також стурбовані використанням пам'яті і хочете переконатись, що два тензори мають спільні дані, використовуйте torch.view.


1
Можливо, це лише я, але я збентежився, думаючи, що суміжність є вирішальним фактором між тим, коли переформатування робить і не передає дані. З моїх власних експериментів здається, що це не так. (Ваш xі yвище обидва суміжні). Можливо, це можна пояснити? Можливо, коментар щодо того, коли переформатування робить і не копіює, був би корисним?
RMurphy

7

Tensor.reshape()є більш надійним. Він буде працювати на будь-якому тензорі, тоді як Tensor.view()працює лише на тензорі tде t.is_contiguous()==True.

Пояснення щодо несуміжних та суміжних - це інша історія часу, але ви завжди можете зробити тензор tсуміжним, коли ви телефонуєте, t.contiguous()і тоді ви можете телефонувати view()без помилки.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.