【踩坑】pytorch中的索引与copy_结合不会复制数据及其解决方案
转载请注明出处:小锋学长生活大爆炸[xfxuezhagn.cn]
如果本文帮助到了你,欢迎[点赞、收藏、关注]哦~
目录
背景知识
实验验证
结论分析
错误案例
处理方法
注意事项
附加说明
基本索引返回视图
高级索引返回副本
赋值操作都是原地操作
以下内容若有错误,欢迎指出!
背景知识
我们现在知道以下几个知识点:
- copy_函数:pytorch中变量的copy_函数,可以将变量inplace地复制到另一个变量中。比如buffer.copy_(a),将a中的数据直接复制到了buffer中。
- 视图(View): 视图是指不复制数据的情况下,返回一个与原始张量共享内存的张量。例如,切片操作通常会返回一个视图。
- 副本(Copy): 副本是指返回一个新的张量,包含了原始张量的数据,但不共享内存。布尔掩码索引返回的就是这样的副本。
- PyTorch和Numpy中的情况:在通过索引访问张量的内容时,PyTorch 遵循 Numpy 的行为,即基本索引返回视图,而高级索引返回副本。通过基本索引或高级索引进行的赋值都是原地操作。
- 切片():切片由中括号和冒号组成,如[:10]、[2:10]、[2:]。
- 基本索引:使用整数或切片来访问数组的元素。
- 高级索引:指的是使用整数数组、布尔数组或者其他序列来访问数组的元素。相比于基本索引,高级索引可以访问到数组中的任意元素,并且可以用来对数组进行复杂的操作和修改。
好了,现在有一个问题,如果结合索引与copy_操作,那是否会复制成功?
实验验证
答案是,不会成功。我们可以用代码测试一下:
import torchprint('>> 使用=号直接复制 <<')
buff = torch.arange(5)
mask = [True, False, False, True, False]
print('输出原始变量:', buff)
print('输出索引掩码:', mask)
print('输出索引变量:', buff[mask])
buff[mask][0] = 10
print('索引变量修改:', buff)
buff[mask] = torch.tensor([8, 9])
print('索引变量赋值:', buff)print('*' * 50)buff = torch.arange(5)
print('输出原始变量:', buff)
print('输出切片索引:', '1:3')
buff_indices = buff[1:3]
print('输出切片变量:', buff[buff_indices])
buff[1:3][0] = 10
print('切片变量修改:', buff)
buff[1:3] = torch.tensor([8, 9])
print('切片变量赋值:', buff)print('=' * 50)print('>> 使用copy_原地复制 <<')buff = torch.arange(5)
mask = [True, False, False, True, False]
print('输出原始变量:', buff)
print('输出索引掩码:', mask)
print('输出索引变量:', buff[mask])
buff[mask].copy_(torch.tensor([8, 9]))
print('索引变量copy:', buff)print('*' * 50)buff = torch.arange(5)
print('输出原始变量:', buff)
print('输出切片索引:', '1:3')
print('输出切片变量:', buff[1:3])
buff[1:3].copy_(torch.tensor([8, 9]))
print('切片变量copy:', buff)
输出结果(改变的地方加粗了):
>> 使用=号直接复制 <<
输出原始变量: tensor([0, 1, 2, 3, 4])
输出索引掩码: [True, False, False, True, False]
输出索引变量: tensor([0, 3])
索引变量修改: tensor([0, 1, 2, 3, 4])
索引变量赋值: tensor([8, 1, 2, 9, 4])
**************************************************
输出原始变量: tensor([0, 1, 2, 3, 4])
输出切片索引: 1:3
输出切片变量: tensor([1, 2])
切片变量修改: tensor([ 0, 10, 2, 3, 4])
切片变量赋值: tensor([0, 8, 9, 3, 4])
==================================================
>> 使用copy_原地复制 <<
输出原始变量: tensor([0, 1, 2, 3, 4])
输出索引掩码: [True, False, False, True, False]
输出索引变量: tensor([0, 3])
索引变量赋值: tensor([0, 1, 2, 3, 4])
**************************************************
输出原始变量: tensor([0, 1, 2, 3, 4])
输出切片索引: 1:3
输出切片变量: tensor([1, 2])
切片变量赋值: tensor([0, 8, 9, 3, 4])
结论分析
在PyTorch中,当你使用布尔掩码或索引来访问张量时,通常会创建一个新的张量,而不是对原始张量进行原地修改。在PyTorch中,切片操作通常会返回一个视图,而不是数据的副本。这意味着切片操作返回的张量和原始张量共享相同的内存。因此,对切片后的张量进行的任何修改都会影响到原始张量。与此相对,布尔掩码索引返回的是数据的副本,因此修改索引得到的张量不会影响原始张量。
因此可见,由于索引返回的是新张量,而copy_是原地复制,因此对于原来的变量来说并没有影响,所以不会复制成功。
而=号这个赋值操作,不管是基本索引还是高级索引,由于底层都是对张量的原地操作,因此确实可以赋值成功。
错误案例
根据以上内容就知道,有时候我们如果这样用,那就是错的:
buff = torch.arange(5)
mask = [True, False, False, True, False]
buff[mask].copy_(torch.tensor([8, 9]))
处理方法
如果确实想结合索引和copy_一起用怎么办?那么可以试试masked_scatter_。
torch.Tensor.masked_scatter_ — PyTorch 2.4 documentation
注意事项
- 对于 [1,2,3] 这种,仍然是位置索引,并不是切片,所以效果等同于上面的布尔索引。通常,PyTorch中的张量索引使用逗号分隔的整数索引来指定每个维度上的具体位置。如果你想对一个一维张量进行切片,应该使用冒号
:来指定范围。
附加说明
对于背景知识里的第4点,我们也来通过代码验证一下。
基本索引返回视图
基本索引包括标量索引、切片操作和整数索引。PyTorch通常会返回原始张量的视图,这意味着它们共享相同的底层数据。因此,对视图的修改会影响原始张量。例如:
import torcha = torch.tensor([1, 2, 3, 4])
b = a[:2] # 基本索引,b 是 a 的视图
b[0] = 10 # 修改视图会影响原始张量
print(a) # 输出: tensor([10, 2, 3, 4])
高级索引返回副本
高级索引包括使用布尔数组、整数数组或多维索引。PyTorch和NumPy一样,高级索引会返回一个新的张量,即副本,不与原始数据共享内存。因此,对副本的修改不会影响原始张量。例如:
import torcha = torch.tensor([1, 2, 3, 4])
indices = torch.tensor([0, 2])
b = a[indices] # 高级索引,b 是 a 的副本
b[0] = 10 # 修改副本不会影响原始张量
print(a) # 输出: tensor([1, 2, 3, 4])
print(b) # 输出: tensor([10, 3])
赋值操作都是原地操作
无论是通过基本索引还是高级索引,赋值操作都是原地操作,这意味着它们会直接修改原始张量的内容。例如:
-
基本索引赋值:
a = torch.tensor([1, 2, 3, 4]) a[:2] = torch.tensor([10, 20]) # 原地修改 a print(a) # 输出: tensor([10, 20, 3, 4]) -
高级索引赋值:
a = torch.tensor([1, 2, 3, 4]) indices = torch.tensor([0, 2]) a[indices] = torch.tensor([10, 20]) # 原地修改 a print(a) # 输出: tensor([10, 2, 20, 4])
相关文章:
【踩坑】pytorch中的索引与copy_结合不会复制数据及其解决方案
转载请注明出处:小锋学长生活大爆炸[xfxuezhagn.cn] 如果本文帮助到了你,欢迎[点赞、收藏、关注]哦~ 目录 背景知识 实验验证 结论分析 错误案例 处理方法 注意事项 附加说明 基本索引返回视图 高级索引返回副本 赋值操作都是原地操作 以下内容…...
十六、【Python】基础教程 - 【Flask】网络编程开发
目录 前言 Flask 基础概念 安装 Flask 示例:创建一个 Flask Web 应用 运行 Flask 应用 更复杂的例子 测试新功能 前言 Flask 是一个用 Python 编写的微型 Web 框架,它以简单性和灵活性著称,非常适合快速开发小型到中型的 Web 应用。F…...
C#初级——List 容器
容器 在C#中,容器通常指的是用于存储和组织数据的集合类。 本文介绍的容器是动态数组:List<T> 内部使用数组来存储元素,当添加元素超出当前数组容量时,会自动调整大小(扩容)。 list容器 List<&g…...
serial靶机教程
靶机下载地址 https://download.vulnhub.com/serial/serial.zip 主机发现 arp-scan -l 端口扫描 nmap 192.168.229.131 -A 根据对⽐可知serial的⼀个ip地址为192.168.47.143 该靶机开启了22端⼝和80端⼝ 对⽹站进⾏⼀个访问,⼤概意思为这是对新的cookie处理程序…...
【Linux-MISC设备】
目录 1. MISC设备2. MISC蜂鸣器实验 1. MISC设备 MISC设备的主设备号为10.MISC设备会自动创建cdev,不需要再手动创建。MISC设备是基于platform的. MISC驱动的编写的核心就是初始化miscdevice结构体变量,然后用misc_register函数向内核注册,…...
【随笔】VRRP+MSTP
虚拟路由冗余协议(Virtual Router Redundancy Protocol,VRRP) 设计采用主备模式,将VRRP组内多个路由设备都映射为一个虚拟路由设备。 一个VRRP组中只能由一台处于主控角色的路由器,可以有一个或多个备份角色的路由器。…...
vue 动态增删行,并form表单校验(附v2\v3)
Vue3 组件用的 ant 可以换成你们用,主要是form校验 前端代码 <a-formref"formRef":model"formData":label-col-props"{ span: 5 }":wrapper-col-props"{ span: 17 }"><a-row><a-form-itemlabel"角色…...
计算机网络的基本概念
IP地址(Internet Protocol Address)是指在计算机网络中每个设备的唯一标识符。它用于区分不同设备并在网络中进行数据包的路由。我们平常所使用的IP地址主要版本: IPv4 格式: 由四个整数(0到255)组成,以点…...
Python 爬虫项目实战三:GitHub 用户信息抓取与分析
一、项目背景 爬虫技术不仅限于获取网页内容,还可以用于获取和分析特定网站的用户信息。本文将演示如何使用Python编写爬虫程序,从GitHub网站抓取用户信息,并进行简单的数据分析。 二、环境准备 在开始之前,请确保你已经安装了…...
xtrabackup搭建MySQL 8.0 主从复制
xtrabackup搭建MySQL 8.0 主从复制 安装MySQL 8.0.37安装xtrabackupGTIDs初始化从库参考:GTID概述GTID相较与传统复制的优势GTID自身存在哪些限制GTID工作原理简单介绍如何开启GTID复制GTID与传统模式建立复制时候语句的不同点传统复制GTID复制 GTID同步状态简单解析…...
Java程序员接单分享
作为一名Java程序员,这阵子通过承接些小型项目,我顺利跨过了月薪破万的门槛。这些项目虽小,却如同磨刀石般,让我在实战中发现了自身技术栈的棱角与不足,尤其是意识到了在Java这一浩瀚技术海洋中的诸多未知领域。我深知…...
【HarmonyOS NEXT星河版开发学习】小型测试案例01-今日头条置顶练习
个人主页→VON 收录专栏→鸿蒙开发小型案例总结 基础语法部分会发布于github 和 gitee上面 前言 本系列可能是博客首发,鸿蒙开发星河版是一个全新的版本,由于参考视频较少鸿蒙开发不被重视导致csdn上面并没有全套的学习路线,…...
C语言----计算开机时间
计算开机时间 实例说明 编程实现计算开机时间,要求在每次开始计算开机时间时都能接着上次记录的结果向下记录。 实现过程: 1. 在TC中创建一个C文件。 2. 引用头文件,代码如下: #include <stdio.h> 3. 定义结构体time,用来…...
批发行业进销存-登录适配 android 横竖屏幕 源码CyberWinApp-SAAS 本地化及未来之窗行业应用跨平台架构
一、横竖屏切换的意义 以下是移动端横屏竖屏可切换在进销存中的一些重要应用: a、数据录入与查看 在录入商品信息、库存数量等大量数据时,横屏模式可以提供更宽阔的输入区域,减少输入错误。例如,在输入长串的商品编码或详细的商…...
js功能(1)
1、readonly 应用于元素:readonly 可以应用于 <input> 和 <textarea> 元素。 用户界面表现:当元素设置为 readonly 时,用户不能更改输入框中的值,但可以选中和复制文本,且表单包含该输入字段的值可以被提交…...
微信小程序乡村医疗系统,源码、部署+讲解
目录 摘 要 Abstract 1 绪论 1.1 研究背景及意义 1.2 研究现状 1.3 研究内容 2 相关技术介绍 2.1 Java 语言 2.2 MySQL 数据库 2.3 Spring Boot 框架 2.4 B/S 结构 2.5 微信小程序 3 系统分析 3.1 可行性分析 3.1.1 经济可行性 3.1.2 技术可行性…...
完美解决pip命令版本冲突导致对应版本模块包无法安装的问题
解决步骤 使用pip更新/降低指定模块包命令格式降低pip自身至指定版本的命令再次换源安装指定模块包 在对 FasterNet 这篇论文源码复现过程中,我们首先需要安装相关依赖文件( path/to/your/requirements.txt) -extra-index-url https://down…...
5.1-软件工程基础知识-软件工程概述
软件工程诞生原因 了解 早期的软件:主要是指采用个体工作方式实现的程序。第一次软件危机:20世纪60年代中期 典型表现有软件质量低下、项目无法如期完成、项目严重超支等因为软件而导致的重大事故时有发生。 软件工程的诞生:1968年在NATO会…...
极简聊天室-websocket版
再写一个极简聊天室的websocket版,在本例中,websocket仅用于服务器向客户端传输信息,客户端向服务器发送信息是传统的http post方式,用axios来实现的,当然websocket本身是支持双向通信,主要是为了方便跟前面…...
QT学生管理系统 开发文档
目录 第一章 UI界面设计与开发 登录界面 主界面 UI美化 第二章 数据库设计与开发 数据库设计 连接数据库 数据库功能设计 sql语句设计 查询所有学生数量 查询第几页学生数据 删除学生 修改学生信息 清空学生表 添加单个用户 删除单个用户 修改用户权限 查询所有用户…...
零门槛NAS搭建:WinNAS如何让普通电脑秒变私有云?
一、核心优势:专为Windows用户设计的极简NAS WinNAS由深圳耘想存储科技开发,是一款收费低廉但功能全面的Windows NAS工具,主打“无学习成本部署” 。与其他NAS软件相比,其优势在于: 无需硬件改造:将任意W…...
【人工智能】神经网络的优化器optimizer(二):Adagrad自适应学习率优化器
一.自适应梯度算法Adagrad概述 Adagrad(Adaptive Gradient Algorithm)是一种自适应学习率的优化算法,由Duchi等人在2011年提出。其核心思想是针对不同参数自动调整学习率,适合处理稀疏数据和不同参数梯度差异较大的场景。Adagrad通…...
Python爬虫实战:研究feedparser库相关技术
1. 引言 1.1 研究背景与意义 在当今信息爆炸的时代,互联网上存在着海量的信息资源。RSS(Really Simple Syndication)作为一种标准化的信息聚合技术,被广泛用于网站内容的发布和订阅。通过 RSS,用户可以方便地获取网站更新的内容,而无需频繁访问各个网站。 然而,互联网…...
el-switch文字内置
el-switch文字内置 效果 vue <div style"color:#ffffff;font-size:14px;float:left;margin-bottom:5px;margin-right:5px;">自动加载</div> <el-switch v-model"value" active-color"#3E99FB" inactive-color"#DCDFE6"…...
AI编程--插件对比分析:CodeRider、GitHub Copilot及其他
AI编程插件对比分析:CodeRider、GitHub Copilot及其他 随着人工智能技术的快速发展,AI编程插件已成为提升开发者生产力的重要工具。CodeRider和GitHub Copilot作为市场上的领先者,分别以其独特的特性和生态系统吸引了大量开发者。本文将从功…...
PAN/FPN
import torch import torch.nn as nn import torch.nn.functional as F import mathclass LowResQueryHighResKVAttention(nn.Module):"""方案 1: 低分辨率特征 (Query) 查询高分辨率特征 (Key, Value).输出分辨率与低分辨率输入相同。"""def __…...
毫米波雷达基础理论(3D+4D)
3D、4D毫米波雷达基础知识及厂商选型 PreView : https://mp.weixin.qq.com/s/bQkju4r6med7I3TBGJI_bQ 1. FMCW毫米波雷达基础知识 主要参考博文: 一文入门汽车毫米波雷达基本原理 :https://mp.weixin.qq.com/s/_EN7A5lKcz2Eh8dLnjE19w 毫米波雷达基础…...
tomcat指定使用的jdk版本
说明 有时候需要对tomcat配置指定的jdk版本号,此时,我们可以通过以下方式进行配置 设置方式 找到tomcat的bin目录中的setclasspath.bat。如果是linux系统则是setclasspath.sh set JAVA_HOMEC:\Program Files\Java\jdk8 set JRE_HOMEC:\Program Files…...
永磁同步电机无速度算法--基于卡尔曼滤波器的滑模观测器
一、原理介绍 传统滑模观测器采用如下结构: 传统SMO中LPF会带来相位延迟和幅值衰减,并且需要额外的相位补偿。 采用扩展卡尔曼滤波器代替常用低通滤波器(LPF),可以去除高次谐波,并且不用相位补偿就可以获得一个误差较小的转子位…...
【SpringBoot自动化部署】
SpringBoot自动化部署方法 使用Jenkins进行持续集成与部署 Jenkins是最常用的自动化部署工具之一,能够实现代码拉取、构建、测试和部署的全流程自动化。 配置Jenkins任务时,需要添加Git仓库地址和凭证,设置构建触发器(如GitHub…...
