- view()和reshape()
- transpose()和permute()
- contiguous
以后操作基于下述tensor。
import torch a=torch.rand(2,2,2) print(a)view()和reshape()
这两个功能很简单,就是把原来的tensor拍扁,变成8个数,然后按照你给定的形状恢复出来。
问题, 怎么拍扁,就是把第二维里面数依次取出来,比如上面的就是9,5,4,8,4,3,5,7。
问题,怎么恢复出我们要的形状?假设我们要的形状是(1,1,8),先填充你给定的最后一个维度即第二维,然后看你要在这个维度上填充多少个数,我们给的是8,刚好填完就没了。
print(a.view(1,1,8)) print(a.reshape(1,1,8))
发现两者一毛一样。两者拍扁和填充的原理一样,所以当然一样喽。没毛病,都可以升维降维。
print(a.view(1,1,2,4)) print(a.reshape(1,1,2,4)) print(a.view(2,4)) print(a.reshape(2,4))
但是,这两个有不同的地方,reshape更加强大,到底有什么不同,我们会在最后公开。
transpose()和permute()我们继续对a进行这两个操作:
这两个也非常像,但是这两个的原理和前面两个完全不一样,并不是拍扁然后恢复,而是交换维度,这个似乎非常抽象。
举个例子给你吧,现在维度是(2,2,2),假如我们要交换维度dim=1,dim=2,其流程如下:固定维度dim=0,然后对dim=1,dim=2进行矩阵转置,这个很简单对吧。
print(a.transpose(1,2))#维度1和维度2需要交换 print(a.permute(0,2,1))#效果一样,但用法不一样。表示现在的维度1是原来的维度2
我们观察一下,是不是就是一个转置而已!!!
从上面的用法可以看到,permute更加强大,transpose只能交换两个维度,但是:
print(a.permute(1,2,0))
突然变了3个维度,是不是有点烧脑了,不慌,我们一步一步来,其可以转化为:
print(a.transpose(1,2).transpose(2,0))
以上也是这两者仅有的区别了。
contiguous在上述transpose()和permute()之后会带来一个后果,即数据地址不连续,这个时候不可以用view操作,只能用reshape。
print(a) print(a.is_contiguous())#创建tensor或者view或者reshape,tensor的数据地址都是连续的。就是按照那个拍扁的顺序来存储在内存的。 print(a.view(1,1,8)) a=a.transpose(1,2)#交换维度,造成地址不连续 print(a.is_contiguous()) print(a.reshape(1,1,8))#仍然可以用 print(a.view(1,1,8))
tensor中的数据不连续存储,我们可以让其变得连续:
a=a.contiguous() print(a.view(1,1,8))
contiguous:相接的; 相邻的;
continuous:;持续的;



