Python与PyTorch的浅拷贝与深拷贝

1.Python赋值操作的原理

在python中,x= something, 这样的赋值操作,准确的理解是:给存储something建立一个索引x (即存储地址), x通过访问something的存储内容,获得something的值。

在下面代码中:

# 情况1: 原变量地址不变,但是内容发生修改
a = torch.rand(4)
print('before a', a, id(a))
b = a 
print('before b', b, id(a))
a[2] = 5
print('after a', a, id(a))
print('after b', b, id(b))

输出:

before a tensor([0.7519, 0.1700, 0.7580, 0.2318]) 4613605632
before b tensor([0.7519, 0.1700, 0.7580, 0.2318]) 4613605632
after a tensor([0.7519, 0.1700, 5.0000, 0.2318]) 4613605632
after b tensor([0.7519, 0.1700, 5.0000, 0.2318]) 4613605632

解析:从上面id信息可以看出,在我们设置b = a 后,a,b均指向同一个内容。当对a[2]进行修改时,该地址内容变化后,对应a,b均发生变化。这是经典的使用赋值方法的浅拷贝方法。

# 情况2:原始变量指向新地址
a = torch.rand(4)
print('before a', a, id(a))
b = a 
print('before b', b, id(a))
a = torch.rand(4)
print('after a', a, id(a))
print('after b', b, id(b))
before a tensor([0.7991, 0.6592, 0.4349, 0.6903]) 4615172560
before b tensor([0.7991, 0.6592, 0.4349, 0.6903]) 4615172560
after a tensor([0.4795, 0.3145, 0.6954, 0.3496]) 4615149584
after b tensor([0.7991, 0.6592, 0.4349, 0.6903]) 4615172560

解析:b=a时,b指向a最初所指向的地址内容,后面重新对a的指向地址和内容进行更新,实际仅影响a的指向,对b没有影响。

2. copy()

copy()是python中常见的一个函数,属于浅拷贝的一种,但是在复制过程中会出现两种情况:

  • 第一种情况:当复制的对象种无复杂子对象的时候,原来值的改变不影响浅复制的值,同时原来值的id和浅拷贝的id不一致;
  • 第二种情况:当复制的对象种存在复杂子对象的时候,如果改变其中复杂子对象的值,浅复制的值也会发生改变;但是改变其他非复杂对象值,则不会影响赋值的值。主要原因是在 copy()中,将复杂子类使用一个公共镜像存储起来,当镜像改变了之后,另一个使用该镜像的值也发生改变。

import copy
a = [[1, 2], 3, 4]
print('before a', a, id(a))
b = copy.copy(a) 
print('before b', b, id(b))
a[0][0] = 0
print('after a', a, id(a))
print('after b', b, id(b))
a[2] = 5
print('after a', a, id(a))
print('after b', b, id(b))
before a [[1, 2], 3, 4] 4615194240
before b [[1, 2], 3, 4] 4614455104
after a [[0, 2], 3, 4] 4615194240
after b [[0, 2], 3, 4] 4614455104
after a [[0, 2], 3, 5] 4615194240
after b [[0, 2], 3, 4] 4614455104

3. deepcopy()

采用deepcopy函数进行赋值时,将被复制对象完全再复制一遍,生成一个新的独立的个体。

from copy import deepcopy
a = [[1, 2], 3, 4]
print('before a', a, id(a))
b = deepcopy(a) 
print('before b', b, id(b))
a[0][0] = 0
print('after a', a, id(a))
print('after b', b, id(b))
a[2] = 5
print('after a', a, id(a))
print('after b', b, id(b))
before a [[1, 2], 3, 4] 4614452352
before b [[1, 2], 3, 4] 4614564032
after a [[0, 2], 3, 4] 4614452352
after b [[1, 2], 3, 4] 4614564032
after a [[0, 2], 3, 5] 4614452352
after b [[1, 2], 3, 4] 4614564032

4. PyTorch中的深拷贝与浅拷贝

4.1. inplace=True

inplace=True的意思是原地操作,例如 x = x + 5, 就是对x进行原地操作,这样操作能够节省内存。

4.2. .Tensor, .tensor, .from_numpy, .as_tensor的区别

.Tensor和.tensor是深拷贝,在内存中创建一个额外的数据副本,不共享内存,所以不受数组改变的影响。

.from_numpy和as_tensor是浅拷贝,在内存中共享数据。

import numpy as np
import torch

a = np.array([1, 2, 3, 4])
a1 = torch.from_numpy(a)
a2 = torch.Tensor(a)
a3 = torch.tensor(a)
a4 = torch.as_tensor(a)
print('before a', a, id(a))
print('before a1', a1, id(a1))
print('before a2', a2, id(a2))
print('before a3', a3, id(a3))
print('before a4', a4, id(a4))

a[1] = 0
print('after a', a, id(a))
print('after a1', a1, id(a1))
print('after a2', a2, id(a2))
print('after a3', a3, id(a3))
print('after a4', a4, id(a4))
before a [1 2 3 4] 4615260944
before a1 tensor([1, 2, 3, 4]) 4615062928
before a2 tensor([1., 2., 3., 4.]) 4614685696
before a3 tensor([1, 2, 3, 4]) 4615208048
before a4 tensor([1, 2, 3, 4]) 4615436944
after a [1 0 3 4] 4615260944
after a1 tensor([1, 0, 3, 4]) 4615062928
after a2 tensor([1., 2., 3., 4.]) 4614685696
after a3 tensor([1, 2, 3, 4]) 4615208048
after a4 tensor([1, 0, 3, 4]) 4615436944

从这里来看,a和a1, a4两个变量相互影响。

4.3. .detach()和.clone()

.clone() 是深拷贝,创建新的存储地址,而不是引用保存旧的tensor,在梯度回传的时候,clone()充当中间变量,会将梯度传给源张量进行叠加,但是本身不保存其grad,值为None.

.detach()是浅拷贝,新的tesnor会脱离计算图,不回牵涉梯度计算。

import torch

x = torch.tensor([2.0, 3.0, 4.0], requires_grad=True)
clone_x = x.clone()
detach_x = x.detach()
clone_detach_x = x.clone().detach()

y = 2*x + 10
y.backward(torch.FloatTensor([1.0, 2.0, 1.0]))

print(x.grad)
print(clone_x.requires_grad)
print(clone_x.grad)
print(detach_x.requires_grad)
print(clone_detach_x.requires_grad)
tensor([2., 4., 2.])
True
None
False
False
/var/folders/ll/nwlhsbw14ds8cs419pf18fn80000gn/T/ipykernel_20906/929467759.py:13: UserWarning: The .grad attribute of a Tensor that is not a leaf Tensor is being accessed. Its .grad attribute won't be populated during autograd.backward(). If you indeed want the .grad field to be populated for a non-leaf Tensor, use .retain_grad() on the non-leaf Tensor. If you access the non-leaf Tensor by mistake, make sure you access the leaf Tensor instead. See github.com/pytorch/pytorch/pull/30531 for more informations. (Triggered internally at /Users/runner/work/_temp/anaconda/conda-bld/pytorch_1670525473998/work/build/aten/src/ATen/core/TensorBody.h:485.)
  print(clone_x.grad)

4.4. contiguous函数

在pytorch中,很多操作都用到浅拷贝的思路,只是重新定义下标与元素的对应关系。

import torch

x = torch.randn(3,2)
y = torch.transpose(x, 0, 1)
print('before')
print('x:', x)
print('y:', y)

print('after')
y[0, 0] = 12
print('x:', x)
print('y:', y)

使用contiguous()之后,

import torch

x = torch.randn(3,2)
y = torch.transpose(x, 0, 1).contiguous()
print('before')
print('x:', x)
print('y:', y)

print('after')
y[0, 0] = 12
print('x:', x)
print('y:', y)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/956004.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【MySQL索引:B+树与页的深度解析】

文章目录 MySQL索引:B树与页的深度解析1. 索引使用的数据结构——B树1.1 B树介绍1.2 B树的特点1.3 B树和B树的对比 2. MySQL中的页2.1 页的介绍2.2 页主体2.3 页目录2.4 B树在MySQL索引中的应用 MySQL索引:B树与页的深度解析 在MySQL数据库中&#xff0…

改进上一篇博文中的按键驱动读取程序,增加环形缓冲区

引言和具体的问题描述 上一篇博文:https://blog.csdn.net/wenhao_ir/article/details/145225508 中写的读取按键值的程序,如果按键按得很快,会出现前面的按键值被后面的按键值被覆盖的情况,即前面的按键值还没被来得及被读取&…

linux环境下软件安装

Linux环境下安装软件 linux安装tomcatLinux配置多台Tomcat linux 手动安装jdklinux yum安装jdk(openjdk)Nacos 安装下载nacos解压三、启动四、常用命令 git安装yum命令安装通过编译安装git linux安装tomcat 1.安装tomcat 下载tomcat安装包,解压到任意目录&#xff…

自定义提示确认弹窗-vue

最初可运行代码 弹窗组件代码&#xff1a; &#xff08;后来发现以下代码可运行&#xff0c;但打包 typescript 类型检查出错&#xff0c;可打包的代码在文末&#xff09; <template><div v-if"isVisible" class"dialog"><div class&quo…

leetcode707-设计链表

leetcode 707 思路 本题也是用了虚拟头节点来进行解答&#xff0c;这样的好处是&#xff0c;不管是头节点还是中间的节点都可以当成是中间节点来处理&#xff0c;用同一套方法就可以进行处理&#xff0c;而不用考虑太多的边界条件。 下面题目中最主要的实现就是添加操作addA…

LabVIEW桥接传感器配置与数据采集

该LabVIEW程序主要用于配置桥接传感器并进行数据采集&#xff0c;涉及电压激励、桥接电阻、采样设置及错误处理。第一个VI&#xff08;"Auto Cleanup"&#xff09;用于自动清理资源&#xff0c;建议保留以确保系统稳定运行。 以下是对图像中各个组件的详细解释&#…

OpenCV基础:获取子矩阵的几种方式

目录 相关阅读 方法一&#xff1a;使用切片操作 方法二&#xff1a;使用高级索引 方法三&#xff1a;使用条件筛选 方法四&#xff1a;使用 numpy 的 take 函数 相关阅读 OpenCV基础&#xff1a;矩阵的创建、检索与赋值-CSDN博客 OpenCV基础&#xff1a;图像运算-CSDN博客…

深入剖析Java线程安全的集合类:原理、特点与应用

引言&#xff1a;线程安全集合类的重要性 在当今的软件开发领域&#xff0c;多线程编程已经成为了构建高性能、响应式应用的关键技术。随着硬件技术的飞速发展&#xff0c;多核处理器的普及使得程序能够充分利用多个核心的计算能力&#xff0c;从而显著提升运行效率。在多线程环…

Ubuntu 22.04虚拟机安装配置调整(语言输入法字体共享剪切板等等

2025.01.07安装配置Ubuntu 22.04 记一下 快捷键 截屏 在设置-键盘-快捷键查看 跟搜到的不一样…不过shiftprint感觉也够用 安装 用的是VMware 参考&#xff1a;VMware中安装配置Ubuntu&#xff08;2024最新版 超详细&#xff09; 调教&#xff08;&#xff1f; 语言 改了…

vim练级攻略(精简版)

vim推荐配置: curl -sLf https://gitee.com/HGtz2222/VimForCpp/raw/master/install.sh -o ./install.sh && bash ./install.sh 0. 规定 Ctrl-λ 等价于 <C-λ> :command 等价于 :command <回车> n 等价于 数字 blank字符 等价于 空格&#xff0c;tab&am…

VSCode 的部署

一、VSCode部署 (1)、简介 vsCode 全称 Visual Studio Code&#xff0c;是微软出的一款轻量级代码编辑器&#xff0c;免费、开源而且功能强大。它支持几乎所有主流的程序语言的语法高亮、智能代码补全、自定义热键、括号匹配、代码片段、代码对比Diff、版本管理GIT等特性&…

Nginx在Linux中的最小化安装方式

1. 安装依赖 需要安装的东西&#xff1a; wget​&#xff0c;方便我们下载Nginx的包。如果是在Windows下载&#xff0c;然后使用SFTP上传到服务器中&#xff0c;那么可以不安装这个软件包。gcc g​&#xff0c;Nginx是使用C/C开发的服务器&#xff0c;等一下安装会用到其中的…

如何在vue中渲染markdown内容?

文章目录 引言什么是 markdown-it&#xff1f;安装 markdown-it基本用法样式失效&#xff1f;解决方法 高级配置语法高亮 效果展示 引言 在现代 Web 开发中&#xff0c;Markdown 作为一种轻量级的标记语言&#xff0c;广泛用于文档编写、内容管理以及富文本编辑器中。markdown…

Android 高版本如何获取App安装列表?

有个需求需要获取App内的安装列表,但是现在在高版本Android中,只能获取到一部分App效果,我获取的代码如下: val calendar Calendar.getInstance()val packageManager context.packageManagerval usageStatsManager context.getSystemService(Context.USAGE_STATS_SERVICE) …

第 5 场 算法季度赛

题目&#xff1a; 5.精准难度【算法赛】 - 蓝桥云课 问题描述 小蓝&#xff0c;蓝桥杯命题组的核心人物。今年的他出题灵感爆发&#xff0c;一口气出了 N 道题目&#xff0c;难度系数分别为 A1​,A2​,…,AN​。 只是&#xff0c;这些题目的难度参差不齐&#xff0c;让组委…

对话 TDengine 解决方案中心总经理陈肃:构建技术与市场的桥梁

TD 小T导读 他是大数据领域的杰出专家&#xff0c;拥有超过十项一作发明专利&#xff0c;是中国通信行业标准《大数据 消息中间件技术要求与测试方法》的重要编写者&#xff0c;并凭借数据中间件领域的突出成就荣获 2019 年“CJK OSS Award”。他是腾讯云 TVP 专家和 TGO 鲲鹏会…

rabbitmq安装延迟队列

在RabbitMQ中&#xff0c;延迟队列是一种特殊的队列类型。当消息被发送到此类队列后&#xff0c;不会立即投递给消费者&#xff0c;而是会等待预设的一段时间&#xff0c;待延迟期满后才进行投递。这种队列在多种场景下都极具价值&#xff0c;比如可用于处理需要在特定时间触发…

GitLab集成Jira

GitLab与Jira集成的两种方式 GitLab 提供了两种 Jira 集成&#xff0c;即Jira议题集成和Jira开发面板集成&#xff0c;可以配置一个或者两个都配置。 具体集成步骤可以参考官方文档Jira 议题集成&#xff08;极狐GitLab文档&#xff09;和Jira 开发面板集成&#xff08;极狐G…

【正则表达式】从0开始学习正则表达式

正则表达式&#xff08;英语&#xff1a;Regular Expression&#xff0c;在代码中常简写为regex、regexp或RE&#xff09; 一、推荐学习网站 正则表达式 – 语法 | 菜鸟教程 正则表达式30分钟入门教程 | 菜鸟教程 编程胶囊-打造学习编程的最好系统 二、必知必记 2.1 元字符…

【docker踩坑记录】

docker踩坑记录 踩坑记录(持续更新中.......)docker images 权限问题 踩坑记录(持续更新中…) docker images 权限问题 permission denied while trying to connect to the Docker daemon socket at unix:///var/run/docker.sock: Head "http://%2Fvar%2Frun%2Fdocker.s…