Pytorch 反向传播 计算图被修改的报错
先看看报错的内容
RuntimeError: one of the variables needed for gradient computation has been modified by an inplace operation: [torch.FloatTensor [5, 1]], which is output 0 of AsStridedBackward0, is at version 2; expected version 1 instead. Hint: enable anomaly detection to find the operation that failed to compute its gradient, with torch.autograd.set_detect_anomaly(True).
报错中说,一个需要梯度计算的变量已经被原地修改了,这引发了报错。
torch.set_grad_enabled(True)
然后我使用上述语句开启了梯度跟踪,发现问题出在我的标签计算函数:
def get_label(net, X):return net(X).reshape((-1, 1))
为什么会出错呢?在这种情况下,由于 label 是从网络输出直接计算得到的,它与网络的计算图相连接。如果在 label 上进行了原地操作(上述的修改形状操作),就可能破坏计算图,使其不可导或其他,总之是导致反向传播时无法正确计算梯度,从而引发报错。
那怎么解决这个问题?将该结果与计算图进行分离就行了,此刻如果再进行反向传播,梯度就不会传播到此处。修改后,代码如下;
def get_label(net, X):return net(X).detach().reshape((-1, 1))
detach()函数的作用是将数据和计算图分离开来,得到数据部分,与计算图再无瓜葛。
举一个更形象的例子,看下面的代码:
label = net(X) # 计算标签
# 对 label 或 label 的某个部分进行了原地操作,比如:
# label[0, 0] = label[0, 0] * 2
# 或
# label += 1
loss = Loss(label, y) # 计算损失
在这个例子中,label由第一条语句前向传播得到,是直接与网络的输出连在一起,后面我却对label的值进行了手动修改。
这些操作可能导致计算图的结构不完整或不可导,从而影响反向传播的计算。为了避免这样的问题,一般建议避免在计算标签或损失时对张量进行原地操作。如果需要修改张量的值,最好创建一个新的张量,而不是直接在原有张量上进行修改。
下面是我的整个程序,大家也可以调试代码来理解其中的含义:
import torch.nn as nn
import matplotlib.pyplot as plt
import torch
from torch.utils import data
def get_label(net, X):#计算标签,计算完后必须要使用detach()分离计算图,否则代码将报计算图被修改的错误return net(X).detach().reshape((-1, 1))def train(net, trainer, Loss, train_data, train_label, epochs, batch_size):#将训练数据和标签捆在一起,便于后面一起便利data_iter = data.DataLoader(list(zip(train_data, train_label)), batch_size=batch_size)#用来存储数据的变化值,前者为训练轮次,后者为每一轮训练平均损失draw_x, draw_y = [], []for epoch in range(epochs):#每次处理一个批次的数据for X, y in data_iter:trainer.zero_grad() # 清除梯度pre_y = net(X) # 前向传播loss = Loss(pre_y, y) # 计算损失loss.backward() # 反向传播,计算梯度trainer.step() # 更新权重,进行优化#添加绘图需要的数据draw_x.append(epoch)draw_y.append(torch.mean(Loss(net(train_data),train_label)).data)#设置绘图参数plt.figure(figsize=(5, 4), dpi=150)#设置图像大小和分辨率plt.plot(draw_x, draw_y, label='train_loss')#设置要绘制的数据,被给出图例plt.xlabel('epoch')#设置X轴标题plt.ylabel('loss')#设置y轴标题plt.legend()#显示图例#显示最终图像plt.show()def test(net, Loss, test_data, test_label):loss_sum = torch.zeros_like(test_label)data_iter = data.DataLoader(list(zip(test_data, test_label)), batch_size=batch_size, shuffle=False)for X, y in data_iter:pre_y = net(X) # 前向传播loss = Loss(pre_y, y) # 计算损失loss_sum += loss # 累加损失return torch.sum(loss_sum) / len(loss_sum) # 返回平均损失def init_weight(m):if type(m) == nn.Linear:#权重使用何凯明正态初始化方法进行初始化nn.init.kaiming_normal_(m.weight)#偏置使用0偏置nn.init.zeros_(m.bias)lr = 0.01 # 学习率
epochs = 100 # 训练轮数
batch_size = 5 # 批大小
shared = nn.Linear(5, 5) # 共享层
net = nn.Sequential(nn.Linear(10, 5), nn.ReLU(), # 输入层到隐藏层1的线性层,ReLU激活函数shared, nn.ReLU(), # 共享层,ReLU激活函数shared, nn.ReLU(), # 共享层,ReLU激活函数nn.Linear(5, 1)) # 从隐藏层到输出层的线性层,无激活函数(线性回归)#显示真实参数(我们的标签就是用这个参数跑出来的),这也是我们最终需要拟合的参数
for name, param in net.named_parameters():print(name, param)#获取随机数作为样本
X = torch.randn((200, 10))
# 通过网络得到真实标签
True_label = get_label(net, X)
#一开始自动随机生成了参数已经被我当作真实参数了,此刻我需要另重新初始化参数
net.apply(init_weight)
#获取训练器
trainer = torch.optim.SGD(net.parameters(), lr=lr)
#获取损失函数
Loss = nn.MSELoss() # 定义损失函数,使用均方误差。#开始训练模型发
train(net, trainer, Loss, X[:50], True_label[:50], epochs, batch_size=batch_size)
#打印测试损失
print(f'测试损失{test(net, Loss, X[50:], True_label[50:])}')
相关文章:
Pytorch 反向传播 计算图被修改的报错
先看看报错的内容 RuntimeError: one of the variables needed for gradient computation has been modified by an inplace operation: [torch.FloatTensor [5, 1]], which is output 0 of AsStridedBackward0, is at version 2; expected version 1 instead. Hint: enable an…...
android studio设置gradle和gradle JDK版本
文章目录 1.gradle JDK版本2.gradle版本 1.gradle JDK版本 file -> project structure -> SDK Location -> Gradle Settings -> Gradle JDK -> Download JDK 2.gradle版本 file -> project structure -> Project...
Android 15即将到来,或将推出5大新功能特性
Android15 OneUI电池优化 三星最近完成了对其所有设备的稳定版 One UI 6.0 更新的推出,引起了用户的极大兴奋。据新出现的互联网统计数据显示,即将发布的基于 Android 15 的 One UI 7 将通过优化电池和功耗来重新定义用户体验,这是一项具有突…...
sqlalchemy 事务自动控制(类java aop)
最近使用它交互数据库,想实现类似java aop那种自动事务控制,不用手动commit或者rollback。我是用的是flaskdenpendency-injecter 这是我的db的配置类,里面会初始化一些session配置,里面比较重要的是把autocommit和autoflush关闭了…...
vue2-手写轮播图
轮播图5长展示,点击指示器向右移动一个图片,每隔2秒移动一张照片! <template><div class"top-app"><div class"carousel-container"><div class"carousel" ref"carousel">&…...
Google I/O大会:Android 13
3个体验升级的方向 以智能手机为场景核心、 扩大智能终端的应用边界以及实现多设备间更好地协同。具体到系统体验层,安卓13将支持图标颜色随主题更换、为不同应用设定使用的语言、新的媒体中心界面等等,同时谷歌也推出了自家的钱包应用(Goog…...
VUE指令(一)
vue会根据不同的指令,针对不同的标签实现不同的功能。指令是带有 v- 前缀的特殊标签属性。指令的职责是,当表达式的值改变时,将其产生的连带影响,响应式地作用于 DOM。 1、v-text:设置元素的文本内容,不会解…...
微信小程序开发学习笔记《7》全局配置以及小程序窗口
微信小程序开发学习笔记《7》全局配置以及小程序窗口 博主正在学习微信小程序开发,希望记录自己学习过程同时与广大网友共同学习讨论。全局配置官方文档 一、全局配置文件及常用的配置项 小程序根目录下的app.json 文件是小程序的全局配置文件。 常用的配置项如…...
Vue、uniApp、微信小程序、Html5等实现数缓存
此文章带你实现前端缓存,利用时间戳封装一个类似于Redis可以添加过期时间的缓存工具 不仅可以实现对缓存数据设置过期时间,还可以自定义是否需要对缓存数据进行加密处理 工具介绍说明 对缓存数据进行非对称加密处理 对必要数据进行缓存,并…...
如何将ArcGIS工程文件迁移到ArcGIS Pro内
当你刚接触ArcGIS Pro的时候,尝试新建一个工程文件会发现工程文件的后缀已经改变,那么以前在ArcGIS内辛苦制作的工程文件是否就不能在ArcGIS Pro内使用了,答案是否定的,对此Esri也给出了解决方案,这里为大家介绍一下迁…...
Jenkins基础篇--添加用户和用户权限设置
添加用户 点击系统管理,点击管理用户,然后点击创建用户(Create User) 用户权限管理 点击系统管理,点击全局安全配置,找到授权策略,选择安全矩阵,配置好用户权限后,点击…...
C语言基础内容(七)——第08章_C语言常用函数
文章目录 第08章_C语言常用函数本章专题脉络1、字符串相关函数1.1 字符串的表示方式1.2 两种方式的区别1.2 字符串常用函数strlen()strcpy()strncpy()strcat()strncat()strcmp()strlwr()/strupr()1.3 基本数据类型和字符串的转换基本数据类型 -> 字符串字符串 -> 基本数据…...
CRM系统针对销售管理有哪些功能?如何帮助销售效率增长?
从长远来看,有效的CRM管理系统可以帮助您的企业达到甚至超过收入目标。现代大多数企业都依靠CRM系统来管理其销售周期并增加收入。但是,当大多数人提到CRM时,他们指的是使能够改善业务关系并轻松管理不断团队的软件或工具。合格的CRM系统能够…...
基于Pixhawk和ROS搭建自主无人车(一):底盘控制篇
参考 ArduPilot Development超维空间科技乐迪MiniPix车船使用说明书 1. 硬件篇 1.1 底盘构成一览 1.2 底盘接线示意 2. 软件篇 2.1 APM 固件下载 pixhawk 是硬件平台,PX4 是 pixhawk 的原生固件,APM(Ardupilot Mega)是硬件平台…...
部署 Spring Boot 应用中文文档
本文为官方文档直译版本。原文链接 部署 Spring Boot 应用中文文档 引言部署到云Cloud Foundry与服务绑定 KubernetesKubernetes 容器生命周期 HerokuOpenShift亚马逊网络服务(AWS)AWS Elastic Beanstalk使用 Tomcat 平台使用 Java SE 平台 总结 CloudCa…...
【数据库原理】(23)实际应用中的查询优化方法
一.基于索引的优化 索引是数据库查询优化的关键工具之一。合理地使用索引可以显著提高查询速度,降低全表扫描的成本。以下是建立和使用索引的一些基本原则和最佳实践。 索引的建立与使用原则 数据量规模与查询频率: 值得建立索引的表通常具有较多的记录࿰…...
MySQL中datetime和timestamp的区别
datetime和timestamp的区别 相同点: 存储格式相同 datetime和timestamp两者的时间格式都是YYYY-MM-DD HH:MM:SS 不同点: 存储范围不同. datetime的范围是1000-01-01到9999-12-31. 而timestamp是从1970-01-01到2038-01-19, 即后者的时间范围很小. 与时区关系. datetime是存储…...
2024年如何使用WordPress构建克隆Udemy市场
您想创建像 Udemy 这样的学习管理 (LMS) 网站吗?最好的学习管理系统工具LifterLMS将帮助您制作像Udemy市场这样的 LMS 网站。 目录 Udemy市场是什么? 创建 Udemy 克隆所需的几项强制性技术: 步骤 1) 注册您的域名 步骤 2) 获取虚拟主…...
(leetcode)Z字形变换 -- 模拟算法
个人主页:Lei宝啊 愿所有美好如期而遇 题目链接 . - 力扣(LeetCode) 输入描述 string convert(string s, int numRows),输入一个字符串s,以及一个行数numRows,将字符串按照这个行数进行Z字形排列&…...
STM32--基于STM32F103的MAX30102心率血氧测量
本文介绍基于STM32F103ZET6MAX30102心率血氧测量0.96寸OLED(7针)显示(完整程序代码见文末链接) 一、简介 MAX30102是一个集成的脉搏血氧仪和心率监测仪生物传感器的模块。它集成了一个红光LED和一个红外光LED、光电检测器、光器…...
多场景 OkHttpClient 管理器 - Android 网络通信解决方案
下面是一个完整的 Android 实现,展示如何创建和管理多个 OkHttpClient 实例,分别用于长连接、普通 HTTP 请求和文件下载场景。 <?xml version"1.0" encoding"utf-8"?> <LinearLayout xmlns:android"http://schemas…...
在Ubuntu中设置开机自动运行(sudo)指令的指南
在Ubuntu系统中,有时需要在系统启动时自动执行某些命令,特别是需要 sudo权限的指令。为了实现这一功能,可以使用多种方法,包括编写Systemd服务、配置 rc.local文件或使用 cron任务计划。本文将详细介绍这些方法,并提供…...
C# 类和继承(抽象类)
抽象类 抽象类是指设计为被继承的类。抽象类只能被用作其他类的基类。 不能创建抽象类的实例。抽象类使用abstract修饰符声明。 抽象类可以包含抽象成员或普通的非抽象成员。抽象类的成员可以是抽象成员和普通带 实现的成员的任意组合。抽象类自己可以派生自另一个抽象类。例…...
uniapp微信小程序视频实时流+pc端预览方案
方案类型技术实现是否免费优点缺点适用场景延迟范围开发复杂度WebSocket图片帧定时拍照Base64传输✅ 完全免费无需服务器 纯前端实现高延迟高流量 帧率极低个人demo测试 超低频监控500ms-2s⭐⭐RTMP推流TRTC/即构SDK推流❌ 付费方案 (部分有免费额度&#x…...
代码随想录刷题day30
1、零钱兑换II 给你一个整数数组 coins 表示不同面额的硬币,另给一个整数 amount 表示总金额。 请你计算并返回可以凑成总金额的硬币组合数。如果任何硬币组合都无法凑出总金额,返回 0 。 假设每一种面额的硬币有无限个。 题目数据保证结果符合 32 位带…...
Python基于历史模拟方法实现投资组合风险管理的VaR与ES模型项目实战
说明:这是一个机器学习实战项目(附带数据代码文档),如需数据代码文档可以直接到文章最后关注获取。 1.项目背景 在金融市场日益复杂和波动加剧的背景下,风险管理成为金融机构和个人投资者关注的核心议题之一。VaR&…...
关于uniapp展示PDF的解决方案
在 UniApp 的 H5 环境中使用 pdf-vue3 组件可以实现完整的 PDF 预览功能。以下是详细实现步骤和注意事项: 一、安装依赖 安装 pdf-vue3 和 PDF.js 核心库: npm install pdf-vue3 pdfjs-dist二、基本使用示例 <template><view class"con…...
Java求职者面试指南:Spring、Spring Boot、Spring MVC与MyBatis技术解析
Java求职者面试指南:Spring、Spring Boot、Spring MVC与MyBatis技术解析 一、第一轮基础概念问题 1. Spring框架的核心容器是什么?它的作用是什么? Spring框架的核心容器是IoC(控制反转)容器。它的主要作用是管理对…...
嵌入式学习之系统编程(九)OSI模型、TCP/IP模型、UDP协议网络相关编程(6.3)
目录 一、网络编程--OSI模型 二、网络编程--TCP/IP模型 三、网络接口 四、UDP网络相关编程及主要函数 编辑编辑 UDP的特征 socke函数 bind函数 recvfrom函数(接收函数) sendto函数(发送函数) 五、网络编程之 UDP 用…...
从物理机到云原生:全面解析计算虚拟化技术的演进与应用
前言:我的虚拟化技术探索之旅 我最早接触"虚拟机"的概念是从Java开始的——JVM(Java Virtual Machine)让"一次编写,到处运行"成为可能。这个软件层面的虚拟化让我着迷,但直到后来接触VMware和Doc…...
