pytorch - data process - 赋值

本文详细介绍了在PyTorch中如何处理因直接赋值导致的内存共享问题,包括索引操作和view()函数的使用。通过示例展示了x+=1与x=x+1的区别,并提出使用.clone()创建副本以避免意外修改原数据。同时,讨论了.clone()在计算图中的作用。
摘要由CSDN通过智能技术生成

reference

https://icepoint666.github.io/2019/05/27/pytorch-clone/

https://tangshusen.me/Dive-into-DL-PyTorch/#/chapter02_prerequisite/2.2_tensor?id=_222-%e6%93%8d%e4%bd%9c

 

直接赋值 tensor 易错点

  • torch中对于直接赋值的这种操作一定要小心,先看看是不是需要直接赋值,还是重新开辟一块内存来存放
  • 我们可以使用类似NumPy的索引操作来访问Tensor的一部分,需要注意的是:索引出来的结果与原数据共享内存,也即修改一个,另一个会跟着修改
  • view()返回的新Tensor与源Tensor虽然可能有不同的size,但是是共享data的,也即更改其中的一个,另外一个也会跟着改变。(顾名思义,view仅仅是改变了对这个张量的观察角度,内部数据并未改变)

不要用 x += 1(与原数据共享内存,也即修改一个,另一个会跟着修改),用x=x+1就没有问题 !!!!!!

本质原因还是 共享内存,所以 x += 1这种写法 直接更改原来memory address 内容;而 x = x+1, 是新创建一个variable 具有新的memory address。(just  a guess, 未经证实)

 

如果想用x += 1这种写法,如何避免共享内存,details can refer this blog.

 

1.索引出来的结果与原数据共享内存

import torch

x = torch.rand(5, 3)
print(x, '\n')

y = x[0, :]
y += 1
print(y)
print(x[0, :]) # 源tensor也被改了
tensor([[0.8773, 0.6006, 0.7565],
        [0.2363, 0.7644, 0.4871],
        [0.7156, 0.1406, 0.3292],
        [0.8075, 0.4868, 0.7283],
        [0.4470, 0.4558, 0.3665]]) 

tensor([1.8773, 1.6006, 1.7565])
tensor([1.8773, 1.6006, 1.7565])

 

不要用 x += 1,用x=x+1就没有问题

import torch
 
x = torch.rand(5, 3)
print(x, '\n')
 
y = x[0, :]
y = y + 1
print(y)
print(x[0, :]) # 源tensor没有被修改!!!!!!!


tensor([[0.6475, 0.9476, 0.6793],
        [0.9083, 0.6180, 0.7341],
        [0.5327, 0.9944, 0.7394],
        [0.4824, 0.6551, 0.7850],
        [0.5130, 0.4454, 0.2850]]) 

tensor([1.6475, 1.9476, 1.6793])
tensor([0.6475, 0.9476, 0.6793])

 

 

2.view()

view()返回的新Tensor与源Tensor虽然可能有不同的size。

y = x.view(15)

z = x.view(-1, 5)  # -1所指的维度可以根据其他维度的值推出来

print(x.size(), y.size(), z.size())


torch.Size([5, 3]) torch.Size([15]) torch.Size([3, 5])

 

但是,但是是共享data的,也即更改其中的一个,另外一个也会跟着改变

(顾名思义,view仅仅是改变了对这个张量的观察角度,内部数据并未改变)。

x += 1

print(x)
print(y) # 也加了1

tensor([[2.8773, 2.6006, 2.7565],
        [1.2363, 1.7644, 1.4871],
        [1.7156, 1.1406, 1.3292],
        [1.8075, 1.4868, 1.7283],
        [1.4470, 1.4558, 1.3665]])

tensor([2.8773, 2.6006, 2.7565, 1.2363, 1.7644, 1.4871, 1.7156, 1.1406, 1.3292,
        1.8075, 1.4868, 1.7283, 1.4470, 1.4558, 1.3665])

3.如何实现 赋值

用 .clone() 创建一个新的副本,开辟新的内存以存贮数据。

使用clone还有一个好处是会被记录在计算图中,即梯度回传到副本时也会传到源Tensor

x_cp = x.clone().view(15)
x -= 1

print(x)

print(x_cp)     # copy version, do not change


tensor([[1.8773, 1.6006, 1.7565],
        [0.2363, 0.7644, 0.4871],
        [0.7156, 0.1406, 0.3292],
        [0.8075, 0.4868, 0.7283],
        [0.4470, 0.4558, 0.3665]])

tensor([2.8773, 2.6006, 2.7565, 1.2363, 1.7644, 1.4871, 1.7156, 1.1406, 1.3292,
        1.8075, 1.4868, 1.7283, 1.4470, 1.4558, 1.3665])

 

 

 

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值