Проще говоря, torch.Tensor.view()
что вдохновлено numpy.ndarray.reshape()
или numpy.reshape()
создает новый взгляд на тензор, если новая форма совместима с формой исходного тензора.
Давайте разберемся в этом подробно на конкретном примере.
In [43]: t = torch.arange(18)
In [44]: t
Out[44]:
tensor([ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17])
С этим тензором t
формы (18,)
новые виды могут быть созданы только для следующих фигур:
(1, 18)
или , что эквивалентно (1, -1)
или или , что эквивалентно или или , что эквивалентно или или , что эквивалентно или или , что эквивалентно или или , что эквивалентно или(-1, 18)
(2, 9)
(2, -1)
(-1, 9)
(3, 6)
(3, -1)
(-1, 6)
(6, 3)
(6, -1)
(-1, 3)
(9, 2)
(9, -1)
(-1, 2)
(18, 1)
(18, -1)
(-1, 1)
Как мы уже можем наблюдать из приведенных выше кортежей формы, умножение элементов кортежа формы (например 2*9
, 3*6
и т. Д.) Всегда должно быть равно общему количеству элементов в исходном тензоре ( 18
в нашем примере).
Еще одна вещь, которую стоит заметить, это то, что мы использовали -1
в одном из мест в каждом из кортежей формы. Используя a -1
, мы ленимся в выполнении вычислений сами, и скорее делегируем задачу PyTorch, чтобы выполнить вычисление этого значения для фигуры, когда она создает новое представление . Важно отметить, что мы можем использовать только один -1
кортеж формы. Остальные значения должны быть явно предоставлены нами. Остальное PyTorch будет жаловаться, бросая RuntimeError
:
RuntimeError: может быть выведено только одно измерение
Таким образом, со всеми вышеупомянутыми формами PyTorch всегда будет возвращать новый вид оригинального тензораt
. Это в основном означает, что он просто изменяет информацию шага тензора для каждого из новых запрашиваемых представлений.
Ниже приведены некоторые примеры, иллюстрирующие, как шаги тензоров изменяются с каждым новым представлением .
# stride of our original tensor `t`
In [53]: t.stride()
Out[53]: (1,)
Теперь мы увидим шаги для новых взглядов :
# shape (1, 18)
In [54]: t1 = t.view(1, -1)
# stride tensor `t1` with shape (1, 18)
In [55]: t1.stride()
Out[55]: (18, 1)
# shape (2, 9)
In [56]: t2 = t.view(2, -1)
# stride of tensor `t2` with shape (2, 9)
In [57]: t2.stride()
Out[57]: (9, 1)
# shape (3, 6)
In [59]: t3 = t.view(3, -1)
# stride of tensor `t3` with shape (3, 6)
In [60]: t3.stride()
Out[60]: (6, 1)
# shape (6, 3)
In [62]: t4 = t.view(6,-1)
# stride of tensor `t4` with shape (6, 3)
In [63]: t4.stride()
Out[63]: (3, 1)
# shape (9, 2)
In [65]: t5 = t.view(9, -1)
# stride of tensor `t5` with shape (9, 2)
In [66]: t5.stride()
Out[66]: (2, 1)
# shape (18, 1)
In [68]: t6 = t.view(18, -1)
# stride of tensor `t6` with shape (18, 1)
In [69]: t6.stride()
Out[69]: (1, 1)
Так что это магия view()
функции. Это просто изменяет шаги (оригинального) тензора для каждого из новых представлений , пока форма нового представления совместима с исходной формой.
Другая интересная вещь, которую можно наблюдать из кортежей шагов, состоит в том, что значение элемента в 0- й позиции равно значению элемента в 1- й позиции кортежа формы.
In [74]: t3.shape
Out[74]: torch.Size([3, 6])
|
In [75]: t3.stride() |
Out[75]: (6, 1) |
|_____________|
Это потому что:
In [76]: t3
Out[76]:
tensor([[ 0, 1, 2, 3, 4, 5],
[ 6, 7, 8, 9, 10, 11],
[12, 13, 14, 15, 16, 17]])
шаг (6, 1)
говорит, что для перехода от одного элемента к следующему элементу по 0- му измерению мы должны прыгнуть или сделать 6 шагов. (т.е. чтобы перейти от 0
к 6
, нужно сделать 6 шагов.) Но чтобы перейти от одного элемента к следующему элементу в 1- м измерении, нам нужен только один шаг (например, чтобы перейти от 2
к3
).
Таким образом, информация о шагах лежит в основе того, как элементы доступны из памяти для выполнения вычислений.
Эта функция будет возвращать представление и будет точно такой же, как при использовании, torch.Tensor.view()
если новая форма совместима с формой исходного тензора. В противном случае он вернет копию.
Однако заметки torch.reshape()
предупреждают, что:
непрерывные входы и входы с совместимыми шагами могут быть изменены без копирования, но это не должно зависеть от поведения копирования и просмотра.
reshape
в PyTorch ?!