또는 에서 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은 각 모양 튜플의 장소 중 하나에서를 사용했다는 것 입니다. 를 사용함으로써 -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에서 왜 그렇게 부르지 않았 습니까?