pytorch中view,reshape,transpose,permute的作用与异同
view与reshape的功能与异同
-
view与reshape都可以改变目标的形状
-
示例:
>>> # view的例子 >>> x = torch.randn(4, 4) # 生成一个结构为(4,4)的随机Tensor >>> x.size() # 打印x的结构 torch.Size([4, 4]) >>> y = x.view(16) # 改变x的结构为(16) >>> y.size() torch.Size([16]) >>> z = x.view(-1, 8) # 改变x的结构为(自适应,8),-1即pytorch框架会自己推断出是多少 >>> z.size() torch.Size([2, 8])
>>> # reshape的例子 >>> a = torch.arange(4.) # 生成一个结构为(4)的连续整型Tensor >>> a [ 0. , 1. , 2. , 3. ] >>> torch.reshape(a, (2, 2)) # 改变a的结构为(2,2) tensor([[ 0., 1.], [ 2., 3.]]) >>> b = torch.tensor([[0, 1], [2, 3]]) >>> c = b.reshape((-1,)) # 改变b的结构为自适应推算结构 >>> c tensor([ 0, 1, 2, 3])
-
那么view与reshape功能都一样,区别在哪里喃?
区别在于:view生成的对象y与原来的对象x是共用一个存储空间,x的某个值改变了,y也会跟着改变。而reshape生成的对象不一定与原来的对象共用一个存储空间。
-
除此之外,pytorch官方文档建议,如果要生成一个对象的复制对象(即不使用同一存储空间),建议使用clone()方法。如果要生成一个对象的引用对象(即使用同一存储空间),建议使用view()方法
view与transpose的异同,以及transpose的功能
-
transpose的功能是交换目标的两个维度
-
示例:
>>> x = torch.randn(2, 3) >>> x.shape torch.Size([2, 3]) >>> x tensor([[-0.7859, -0.6206, -1.0093], [-0.3472, 0.2701, 2.5651]]) >>> y = torch.transpose(x, 0, 1) # 交换x的0维与1维即交换x.shape的2与3 >>> y.shape torch.Size([3, 2]) >>> y tensor([[-0.7859, -0.3472], [-0.6206, 0.2701], [-1.0093, 2.5651]])
-
view虽然与transpose都能改变目标的形状,且都是返回一个共用存储空间的对象
但是区别有:
-
transpose是交换目标的维度,而view是将目标的数据重排成新的形状
-
pytorch中有个概念contiguous,即相邻的数据在存储结构中是相邻的
而transpose会将一个本来contiguous的Tensor变为一个不contiguous的Tensor,view不会有这种效果。
也即x的x[0,0]与x[0,1]是在存储空间是连续的,有y=x.transpose(…)后虽然y[0,0]==x[0,0] and y[0,1]==x[0,1]但是y[0,0]可能与y[0,1]的存储空间不是连续的了
示例:
>>> x = torch.tensor([[1, 2, 3], [4, 5, 6]]) >>> y = x.transpose(0, 1) >>> print(x.data_ptr()) ... print(y.data_ptr()) # 可以看到他们的存储空间是同一个 2413295081664 2413295081664 >>> print(x.is_contiguous()) ... print(y.is_contiguous()) # 可以看到他们的contiguous特性是不一样的 True False
-
view方法只能处理contiguous的Tensor
示例:
>>> # 接上面的代码 >>> y.view(2,3) Traceback (most recent call last): File "**********************************************************", line 3553, in run_code exec(code_obj, self.user_global_ns, self.user_ns) File "<ipython-input-37-0e018fb48dc9>", line 1, in <module> y.view(2,3) RuntimeError: view size is not compatible with input tensor's size and stride (at least one dimension spans across two contiguous subspaces). Use .reshape(...) instead. >>> y.reshape(2,3) # reshape是可以的 tensor([[10, 4, 2], [ 5, 3, 6]])
-
transpose与permute的异同,以及permute的功能
-
permute 与tranpose() 是相似的,但是 transpose() 只能交换两个维度,而 permute() 可以一次性交换所有的维度。
示例:
>>> x = torch.randn(2, 3, 5) >>> x.size() torch.Size([2, 3, 5]) >>> torch.permute(x, (2, 0, 1)).size() torch.Size([5, 2, 3])
值得注意的是,再permute()中,你必须提供所有维度的一个排列,而在transpose()中只需要提供两个维度的顺序。transpose()可以视为一个特殊的permute()方法。