Update from Sync Service
This commit is contained in:
@@ -0,0 +1,125 @@
|
||||
|
||||
最近被 [pytorch](https://so.csdn.net/so/search?q=pytorch&spm=1001.2101.3001.7020) 的几种 Tensor 维度转换方式搞得头大,故钻研了一下,将钻研历程和结果简述如下
|
||||
|
||||
_**注意:torch.__version__ == '1.2.0’**_
|
||||
|
||||
## [torch](https://so.csdn.net/so/search?q=torch&spm=1001.2101.3001.7020).transpose() 和 torch.permute()
|
||||
|
||||
两者作用相似,都是用于交换不同维度的内容。但其中`torch.transpose()`是交换指定的两个维度的内容,`permute()`则可以一次性交换多个维度。具体情况如 code 所示:
|
||||
**transpose()**: 两个维度的交换
|
||||
|
||||
```
|
||||
>>> a = torch.Tensor([[[1,2,3,4,5], [6,7,8,9,10], [11,12,13,14,15]],
|
||||
[[-1,-2,-3,-4,-5], [-6,-7,-8,-9,-10], [-11,-12,-13,-14,-15]]])
|
||||
>>> a.shape
|
||||
torch.Size([2, 3, 5])
|
||||
>>> print(a)
|
||||
tensor([[[ 1., 2., 3., 4., 5.],
|
||||
[ 6., 7., 8., 9., 10.],
|
||||
[ 11., 12., 13., 14., 15.]],
|
||||
|
||||
[[ -1., -2., -3., -4., -5.],
|
||||
[ -6., -7., -8., -9., -10.],
|
||||
[-11., -12., -13., -14., -15.]]])
|
||||
>>> b = a.transpose(1,2) # 使用transpose,将维度1和2进行交换。这个很好理解。转换后tensor与其shape如下
|
||||
>>> print(b, b.shape)
|
||||
(tensor([[[ 1., 6., 11.],
|
||||
[ 2., 7., 12.],
|
||||
[ 3., 8., 13.],
|
||||
[ 4., 9., 14.],
|
||||
[ 5., 10., 15.]],
|
||||
|
||||
[[ -1., -6., -11.],
|
||||
[ -2., -7., -12.],
|
||||
[ -3., -8., -13.],
|
||||
[ -4., -9., -14.],
|
||||
[ -5., -10., -15.]]]),
|
||||
torch.Size([2, 5, 3])))
|
||||
```
|
||||
|
||||
**permute()**:一次性做任意维度的交换
|
||||
|
||||
```
|
||||
>>> c = a.permute(2, 0, 1)
|
||||
>>> print(c, c.shape) # 此举将原维度0,1,2的次序变为2,1,0,所以shape也发生了相应的变化。
|
||||
(tensor([[[ 1., 6., 11.],
|
||||
[ -1., -6., -11.]],
|
||||
|
||||
[[ 2., 7., 12.],
|
||||
[ -2., -7., -12.]],
|
||||
|
||||
[[ 3., 8., 13.],
|
||||
[ -3., -8., -13.]],
|
||||
|
||||
[[ 4., 9., 14.],
|
||||
[ -4., -9., -14.]],
|
||||
|
||||
[[ 5., 10., 15.],
|
||||
[ -5., -10., -15.]]]),
|
||||
torch.Size([5, 2, 3]))
|
||||
```
|
||||
|
||||
transpose() 和 permute() 之间的转化:
|
||||
|
||||
```
|
||||
>>> b = a.permute(2,0,1)
|
||||
>>> c = a.transpose(1,2).transpose(0,1)
|
||||
>>> print(b == c, b.shape)
|
||||
(tensor([[[True, True, True],
|
||||
[True, True, True]],
|
||||
|
||||
[[True, True, True],
|
||||
[True, True, True]],
|
||||
|
||||
[[True, True, True],
|
||||
[True, True, True]],
|
||||
|
||||
[[True, True, True],
|
||||
[True, True, True]],
|
||||
|
||||
[[True, True, True],
|
||||
[True, True, True]]]),
|
||||
torch.Size([5, 2, 3]))
|
||||
```
|
||||
|
||||
如代码所示,先将 [Tensor](https://so.csdn.net/so/search?q=Tensor&spm=1001.2101.3001.7020) a 的 1,2 维度进行交换,再将得到的 Tensor 的 0,1 维度再交换,得到的结果和 permute 是一样的。
|
||||
|
||||
## transpose() 和 view()
|
||||
|
||||
`view()`是个在 pytorch 中很常见的函数。该函数也起到转换 Tensor 维度的作用,但它转换的方式和 transpose()/permute() 截然不同。如果说`tranpose()`是按照 Tensor 的原有维度忠实地进行交换,那么`view()`就直接而且简单的多——首先,view() 函数会将 Tensor 所有维度拉平成一维,然后再根据传入的的维度信息重构出一个 Tensor。code 如下:
|
||||
|
||||
```
|
||||
# 还是上面的Tensor a
|
||||
>>> print(a.shape)
|
||||
torch.Size([2, 3, 5])
|
||||
>>> print(a.view(2,5,3))
|
||||
tensor([[[ 1., 2., 3.],
|
||||
[ 4., 5., 6.],
|
||||
[ 7., 8., 9.],
|
||||
[ 10., 11., 12.],
|
||||
[ 13., 14., 15.]],
|
||||
|
||||
[[ -1., -2., -3.],
|
||||
[ -4., -5., -6.],
|
||||
[ -7., -8., -9.],
|
||||
[-10., -11., -12.],
|
||||
[-13., -14., -15.]]])
|
||||
>>> c = a.transpose(1,2)
|
||||
>>> print(c, c.shape)
|
||||
(tensor([[[ 1., 6., 11.],
|
||||
[ 2., 7., 12.],
|
||||
[ 3., 8., 13.],
|
||||
[ 4., 9., 14.],
|
||||
[ 5., 10., 15.]],
|
||||
|
||||
[[ -1., -6., -11.],
|
||||
[ -2., -7., -12.],
|
||||
[ -3., -8., -13.],
|
||||
[ -4., -9., -14.],
|
||||
[ -5., -10., -15.]]]),
|
||||
torch.Size([2, 5, 3]))
|
||||
```
|
||||
|
||||
如代码所示。即使`view()`和`transpose()`最终得到的 Tensor 的 shape 是一样的,但二者内容并不相同。view 函数只是按照给定的 (2,5,3) 的 Tensor 维度,将元素**按顺序**一个个填进去;而 transpose 函数,则的确是在进行第一个第二维度的**转置**。
|
||||
|
||||
此外,有些情况下转置 (transpose) 后的 Tensor 是无法被 **view** 的,原因在于,转置后的 Tensor 不是 “连续”(non-contiguous)的。关于 contiguous array 的问题 numpy 里也一样,在这里有个[很棒的解释](https://stackoverflow.com/questions/26998223/what-is-the-difference-between-contiguous-and-non-contiguous-arrays/26999092#26999092)
|
||||
Reference in New Issue
Block a user