pytorch结构函数tensor.view()和terson.reshape(),以及contiguous()为何存在

前要

这两个函数都是用来改变tensor的形状的,区别看第[2.区别]

三个前提知识点:

  1. x= x+1pytorchpython中会新开辟空间存储计算结果, 重开x的内存地址,让x指向新的结果;自加(减)运算符x += 1和使用不会,是修改原始数据。
  2. 面向对象语言:对象和数据的地址分开,比如x = [1,2,3],对象是x,数据是[1,2,3]
  3. id()函数只能看对象内存地址。

1. 文档解释

view()
# 使用方法
x_tensor.view(*args) → Tensor
  1. 返回一个有相同数据结构不同的tensor。
  2. 返回的tensor必须有与原tensor相同的数据和相同数目的元素,但可以有不同的大小。
  3. 一个tensor必须是连续的contiguous()才能被view()。

参数:

  • x_tensor: 想改变结构的tensor
  • args: 目标结构

例:

x = torch.randn(4, 4) 
x.view(2,8) 
reshape()

reshape和上面的是一样的使用方法,但是是对于不连续的数据可以改变形状。

2. 区别

view()reshape()有两点以下区别。

  1. view()是内存共享的,reshape()不是共享的,可以理解为reshape获取的是tensor克隆真实副本,而不是view()改变了tensor的观察视角而已,然而实际上并不会这样使用它,因为reshape通常获取不到原数据的拷贝(因为会改变data的内存地址),所以一般用clone()克隆tensor后再view,确保对象和数据两个内存地址都被完整复制走。
x = torch.randint(0,20,(2,3))
'''
tensor([[ 7.,  2., 16.],
        [17., 19., 15.]])
'''
y = x.view(6)
'''
tensor([ 7.,  2., 16., 17., 19., 15.])
'''
z = x.view(-1,2)
'''
tensor([[ 7.,  2.],
        [16., 17.],
        [19., 15.]])
'''
##########区别##############
# 地址是否一样:
print(id(x)==id(y), id(x)==id(z), id(y)==id(z))
print(id(x.data)==id(y.data), 
	  id(x.data)==id(z.data),
	  id(y.data)==id(z.data))
''''outputs: 
False False False
True True True
'''

# 改变x
x[0] = 1
'''outputs: 统一变化
tensor([[ 1.,  1.,  1.],
        [17., 19., 15.]]) 
 tensor([ 1.,  1.,  1., 17., 19., 15.]) 
 tensor([[ 1.,  1.],
        [ 1., 17.],
        [19., 15.]])
'''

# 改变z
z[0] = 0
''''outputs: 统一变化
tensor([[ 0.,  0.,  1.],
        [17., 19., 15.]]) 
 tensor([ 0.,  0.,  1., 17., 19., 15.]) 
 tensor([[ 0.,  0.],
        [ 1., 17.],
        [19., 15.]])
'''

既然已经讲到这里,不妨提一下数据操作:x= x+1pytorchpython中会新开辟空间存储计算结果, 重开x的内存地址,让x指向新的结果;自加(减)运算符x += 1和使用不会,是修改原始数据。
例子如下

x  = x + 1
'''ouputs
tensor([[ 1.,  1.,  2.],
        [18., 20., 16.]]) 
 tensor([ 0.,  0.,  1., 17., 19., 15.]) 
 tensor([[ 0.,  0.],
        [ 1., 17.],
        [19., 15.]])
'''
  1. 对于不连续的tensor,也就是tensor . is_contiguous()==False

使用view()会报错如下:
RuntimeError: invalid argument 2: view size is not compatible with input tensor's....
因为tensor经过转置后数据的内存地址不连续导致的,转置函数可以看pytorch两个转置函数

但是reshape()可以改变这种内存不连续tensor的结构,而view()不可以,因为reshape等价于先contiguous()view(),也就是数据内存给你撸顺了,再改变观察视角。
例子如下:

x = torch.rand(3,4)
x = x.transpose(0,1)
print(x.is_contiguous())
'False'
# 会发现
x.view(3,4)
'''
RuntimeError: invalid argument 2: view size is not compatible with input tensor's....
内存地址不连续导致该错误
'''
# 但是这样是可以的。
x = x.contiguous()
x.view(3,4)

我们再看看reshape()

x = torch.rand(3,4)
x = x.permute(1,0) # 等价x = x.transpose(0,1)
x.reshape(3,4)
'''这就不报错了
说明x.reshape(3,4) 这个操作
等于x = x.contiguous().view()
尽管如此,但是torch文档中还是不推荐使用reshape
理由是除非为了获取完全不同但是数据相同的克隆体。
'''

3.关于连续contiguous()

目前pytorch只要是transpose()permute()这两个函数用过后,tensor都会变得不再连续,就不可以使用view().

调用contiguous()时,会强制拷贝一份tensor,让它的布局和从头创建的一毛一样。
(这一段看文字你肯定不理解,你也可以不用理解,有空我会画图补上)

你只需要记住了,使用view()之前,只要使用了transpose()permute()这两个函数一定要contiguous()

  • 23
    点赞
  • 29
    收藏
    觉得还不错? 一键收藏
  • 10
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 10
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值