В чем разница между изменением формы и просмотром в pytorch?

93

В numpy мы используем ndarray.reshape()для изменения формы массива.

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

Поэтому мне интересно, в чем разница между ними и когда я должен использовать любой из них?

Лифу Хуанг
источник

Ответы:

99

torch.viewсуществует очень давно. Он вернет тензор с новой формой. Возвращенный тензор будет разделять подчиненные данные с исходным тензором. См. Документацию здесь .

С другой стороны, похоже, что torch.reshape недавно появилась версия 0.4 . Согласно документу , этот метод будет

Возвращает тензор с теми же данными и количеством элементов, что и входные, но с указанной формой. По возможности, возвращаемый тензор будет видом ввода. В противном случае это будет копия. Смежные входы и входы с совместимыми шагами можно изменять без копирования, но вы не должны зависеть от поведения копирования или просмотра.

Это означает, что torch.reshapeможет возвращать копию или представление исходного тензора. Вы не можете рассчитывать на то, что вернете представление или копию. По словам разработчика:

если вам нужна копия, используйте clone (), если вам нужно такое же хранилище, используйте view (). Семантика reshape () такова, что он может или не может совместно использовать хранилище, и вы не знаете заранее.

Другое отличие состоит в том, что reshape()может работать как с непрерывным, так и с несмежным тензором, тогда как view()может работать только с смежным тензором. Также см. Здесь о значении contiguous.

Jdhao
источник
30
Возможно, было бы полезно подчеркнуть, что torch.view может работать только с смежными тензорами, а torch.reshape может работать с обоими.
p13rr0m 05
6
@pierrom contiguous здесь относится к тензорам, которые хранятся в непрерывной памяти или что-то еще?
gokul_uf 04
3
@gokul_uf Да, вы можете взглянуть на ответ, написанный здесь: stackoverflow.com/questions/48915810/pytorch-contiguous
MBT
означает ли в pytorch фраза "вид тензора"?
Чарли Паркер
Было бы полезно получить объяснение, что такое «совместимые шаги». Благодаря!
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налагает некоторые ограничения смежности на формы двух тензоров [ docs ]. Чаще всего это не вызывает беспокойства, но иногда 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.

nikhilweee
источник
1
Может быть, это только я, но я был сбит с толку, думая, что смежность является решающим фактором между тем, когда reshape делает и не передает данные. Из моих собственных экспериментов кажется, что это не так. (Ваш xи yвыше оба смежны). Может быть, это можно прояснить? Возможно, будет полезным комментарий о том, когда reshape копируется, а когда нет?
RMurphy
7

Tensor.reshape()более надежен. Он будет работать с любым тензором, а Tensor.view()работает только с тензором, tгдеt.is_contiguous()==True .

Объяснение несмежных и смежных функций - это другая история, но вы всегда можете сделать тензор tсмежным, если вы вызываете, t.contiguous()а затем вы можете позвонить view()без ошибки.

Прости
источник