Какая разница между изменением формы и представлением в pytorch?

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

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

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

Ответ 1

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

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

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

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

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

Ответ 2

Хотя и 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 накладывает некоторые ограничения на смежность форм двух тензоров [ 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.

Ответ 3

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

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