Update from Sync Service

This commit is contained in:
FNS Service
2026-07-31 15:28:08 +08:00
commit b8a78631a4
569 changed files with 193313 additions and 0 deletions
@@ -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)