关于pytorch中(view,reshape),permute,transpose的一点理解与记录

文章介绍了Tensor的stride属性如何定义其维度信息,以及view和reshape函数如何改变tensor的形状。view基于内存中的连续数据,而reshape允许不连续的stride。当stride不符合特定条件时,可以使用reshape或contiguous()来调整。
摘要由CSDN通过智能技术生成

view和reshape

用不严谨的说法,view是reshape的子集。

说view之前,我先介绍以下tensor里面的stride属性。举一个例子:

import torch
x = torch.Tensor([[[[1, 2, 3],
                    [4, 5, 6]],

                   [[7, 8, 9],
                    [10, 11, 12]]],


                  [[[13, 14, 15],
                    [16, 17, 18]],

                   [[19, 20, 21],
                    [22, 23, 24]]]])  # 一个 (2, 2, 2, 3) 结构的 4 阶张量
print(x.stride())

这是一个(2,2,2,3)的tensor的stride——(12,6,3,1)

我们可以发现,12=2*2*3,6=2*3,3=3*1

其实就是——stride[i]=shape[i+1]*stride[i+1]

实际上tensor在我们想象中是方的,但是他在内存中就是一串数据,不同于一维的列表的是,每个元素的指针并非直接指向下一个,而是根据stride指向不同维度的元素。

如果stride符合这个公式,那么说明tensor在内存里面的存储顺序是和我们print出来tensor的打印顺序一样的,官方用了一个很形象的说法——符合连续条件。

参照地球被支点撬走啦大佬的图

 

 其实我们可以看到,一个tensor的维度信息其实是通过stride来定义的。

比如这张图中,第一维的跨度是3,而第二维的跨度是1。

view的作用

view函数的作用其实就是重新定义stride来达到改变tensor形状的效果。但是有一种情况会让view函数报错,那就是有函数改变了stride,而且使stride不符合stride[i]=shape[i+1]*stride[i+1]。

举个例子:我们通过维度操作函数transpose来改变tensor的stride

import torch
x = torch.Tensor([[[[1, 2, 3],
                    [4, 5, 6]],

                   [[7, 8, 9],
                    [10, 11, 12]]],

                  [[[13, 14, 15],
                    [16, 17, 18]],

                   [[19, 20, 21],
                    [22, 23, 24]]]])  # 一个 (2, 2, 2, 3) 结构的 4 阶张量
# print("stride=",x.reshape(3,4,2).stride())
print(x.stride())
print(x.transpose(1,0).stride())

(12, 6, 3, 1)
(6, 12, 3, 1)

可以看到其实就是调换了stride,也就是索引顺序。但是数据在内存中的状态其实和stride=(12, 6, 3, 1)的时候相同。这个时候运行view改变tensor,其实是在stride=(12, 6, 3, 1)的内存数据之上修改,而不是我们以为的(6, 12, 3, 1)。

这时程序发现,stride不符合连续条件,所以就报错了。

这时我们有两个方法,一个是用reshape代替view,reshape函数允许stride不符合连续条件时,依据原tensor创建一个现有stride规则的tensor,然后再view。你也可以在使用view前使用contiguous函数,这个函数的作用也是依据原tensor创建一个现有stride规则的tensor。

print(x.transpose(1,0).reshape(4,2,3))
print(x.transpose(1,0).contiguous().view(4,2,3))

总结

其实tensor到底在内存中还是一串连续数据,依靠stride属性规范了维度索引,依靠size属性规范了维度的大小。由此我们可以明白,只需要改变tensor的stride和size就可以达成改变tensor的目的。但是view算法是建立在改变一个“内存里面的存储顺序是和print出来tensor的打印顺序一样”的tensor基础之上的,所以要不我们用contiguous把tensor规范化,要不用reshape一键式操作。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值