每一次写代码当需要变换维度的时候总会在纠结究竟用哪一种变换维度的函数能够保持自己获得想要的结果,这次于是就举几个简单的例子来对比一下:
假设我们有一个矩阵如下所示:
a=torch.IntTensor([[[1,2,3],[4,5,6]],
[[7,8,9],[10,11,12]]])
a是一个[2, 2, 3]的矩阵,如下所示:
tensor([[[ 1, 2, 3],
[ 4, 5, 6]],
[[ 7, 8, 9],
[10, 11, 12]]], dtype=torch.int32)
a=torch.reshape(a,[4,3])
可以看到结果为:
tensor([[ 1, 2, 3],
[ 4, 5, 6],
[ 7, 8, 9],
[10, 11, 12]], dtype=torch.int32)
可以发现,虽然维度进行了变换,但是仅仅只是将每一行进行融合了,而并未对二维行列产生任何影响,若将原矩阵进行其他变换
a=torch.reshape(a,[2,6])
可获得:
tensor([[ 1, 2, 3, 4, 5, 6],
[ 7, 8, 9, 10, 11, 12]], dtype=torch.int32)
同样顺序都是存在着的,如果用a=torch.reshape(a,[2,2,3])进行变换,可以直接回到原来的样子,并且位置也保持不变。
view和reshape的功能类似,区别在于:
1)view只适用于内存中连续存储的 tensor,若之前经过了 transpose, permute这种直接跨维度的操作,会使得内存不连续,而reshape没有这种问题,所以一般情况下可以用reshape
2)使用reshape的时候,可以用:
a=torch.reshape(a,[4,3])
a=a.reshape([4,3])
而view只能用:
a=a.view([4,3])
permute定义为permute(self,dims),因此适用于高维矩阵进行转置,可以对所有维度任意进行转置
a=a.permute(0,2,1)
这是仅仅将第1维和第2维进行调换,结果如下:
tensor([[[ 1, 4],
[ 2, 5],
[ 3, 6]],
[[ 7, 10],
[ 8, 11],
[ 9, 12]]], dtype=torch.int32)
可以看到在每一个2维矩阵中行列进行了转置,若:
a=a.permute(2,1,0)
tensor([[[ 1, 7],
[ 4, 10]],
[[ 2, 8],
[ 5, 11]],
[[ 3, 9],
[ 6, 12]]], dtype=torch.int32)
当将所有维度都进行转置了以后,可以发现,每一个2维矩阵的元素都更改到了不同的通道中,可以看出,permute可以对任意维度进行转置,可以一个也可以全部。
transpose定义为:a.transpose(self,dim0,dim1),因此只适用于将两个维度进行转置,可以将上述的permute变成用transpose进行2次转置,过程如下:
a=a.transpose(0,1)
或者a=torch.transpose(a,[0,1])
tensor([[[ 1, 2, 3],
[ 7, 8, 9]],
[[ 4, 5, 6],
[10, 11, 12]]], dtype=torch.int32)
可以看到,当将第0维和第1维进行置换,实际上是将一个2维矩阵的行和另一个2维矩阵的行进行了置换,接着:
a=a.transpose(1,2)
tensor([[[ 1, 7],
[ 4, 10]],
[[ 2, 8],
[ 5, 11]],
[[ 3, 9],
[ 6, 12]]], dtype=torch.int32)
此时再将行列进行转换,从而最终获得一个torch.Size([2, 3, 2])的3维矩阵,
当我们需要对矩阵进行维度变换的时候,就是直接改变矩阵的原有维度变成新的维度,我们采用reshape或者view,而当需要对通道的位置进行改变的时候,而不改变原来固有的所有通道的值,我们采用transform或者permute