当前位置: 首页 > news >正文

获取非叶子节点的grad(retain_grad()、hook)【为了解决grad值是None的问题】

在调试过程中, 有时候我们需要对中间变量梯度进行监控, 以确保网络的有效性, 这个时候我们需要打印出非叶节点的梯度, 为了实现这个目的, 我们可以通过两种手段进行, 分别是:

  • retain_grad()
  • hook

不过我感觉“hook”比“retain_grad()”要麻烦.....,所以我感觉还是使用“retain_grad()”吧

1、retain_grad()

retain_grad()显式地保存非叶节点的梯度, 代价就是会增加显存的消耗(对比hook函数的方法则是在反向计算时直接打印, 因此不会增加显存消耗.)

使用方法:

直接在forward中对你想要输出gred的tensor“.retain_grad()”即可:tensor.retain_grad()

import torchdef forwrad(x, y, w1, w2):# 其中 x,y 为输入数据,w为该函数所需要的参数z_1 = torch.mm(w1, x)z_1.retain_grad()y_1 = torch.sigmoid(z_1)y_1.retain_grad()z_2 = torch.mm(w2, y_1)z_2.retain_grad()y_2 = torch.sigmoid(z_2)# y_2.retain_grad()loss = 1 / 2 * (((y_2 - y) ** 2).sum())return loss, z_1, y_1, z_2, y_2# 测试代码
x = torch.tensor([[1.0]])
y = torch.tensor([[1.0], [0.0]])
w1 = torch.tensor([[1.0], [2.0]], requires_grad=True)
w2 = torch.tensor([[3.0, 4.0], [5.0, 6.0]], requires_grad=True)
# 正向
loss, z_1, y_1, z_2, y_2 = forwrad(x, y, w1, w2)
# 反向
loss.backward()  # 反向传播,计算梯度print(loss.grad)print(y_2.grad)print(z_2.grad)# 输出结果是否是None,如果是None-->True
def is_none(obj):return obj is None
# 打印出非叶子结点的gred
print(is_none(z_1.grad))
print(is_none(y_2.grad))
print(z_2.grad)

注意:不要对保存梯度的变量做任何修改,例如:z_1, y_1, z_2, y_2,修改为gred_list = [z_1, y_1, z_2, y_2],然后输入梯度值,那是错误的,要直接一个一个输出,不要做任何操作

2、hook的使用

使用retain_grad会消耗额外的显存, 我们可以使用hook在反向计算的时候进行保存. 还是上面的例子, 我们使用hook来完成.

import torch# 我们可以定义一个hook来保存中间的变量
grads = {} # 存储节点名称与节点的grad
def save_grad(name):def hook(grad):grads[name] = gradreturn hookdef forwrad(x, y, w1, w2):# 其中 x,y 为输入数据,w为该函数所需要的参数z_1 = torch.mm(w1, x)y_1 = torch.sigmoid(z_1)z_2 = torch.mm(w2, y_1)y_2 = torch.sigmoid(z_2)loss = 1/2*(((y_2 - y)**2).sum())return loss, z_1, y_1, z_2, y_2# 测试代码
x = torch.tensor([[1.0]])
y = torch.tensor([[1.0], [0.0]])
w1 = torch.tensor([[1.0], [2.0]], requires_grad=True)
w2 = torch.tensor([[3.0, 4.0], [5.0, 6.0]], requires_grad=True)
# 正向传播
loss, z_1, y_1, z_2, y_2 = forwrad(x, y, w1, w2)# hook中间节点
z_1.register_hook(save_grad('z_1'))
y_1.register_hook(save_grad('y_1'))
z_2.register_hook(save_grad('z_2'))
y_2.register_hook(save_grad('y_2'))# 反向传播
loss.backward()
print(grads['z_1'])
print(grads['y_1'])
print(grads['z_2'])
print(grads['y_2'])

https://www.cnblogs.com/dxscode/p/16146470.html

pytorch | loss不收敛或者训练中梯度grad为None的问题_pytorch梯度为none_Rilkean heart的博客-CSDN博客

http://www.lryc.cn/news/101783.html

相关文章:

  • JMeter(八):响应断言详解
  • 【网络编程】IO复用的应用一:非阻塞connect
  • Spring注解开发,bean的作用范围及生命周期、Spring注解开发依赖注入
  • C#设计模式之---原型模式
  • STM32入门学习之外部中断
  • Jenkins 配置maven和jdk
  • Leetcode | Binary search | 22. 74. 162. 33. 34. 153.
  • 生命在于折腾——面试问题汇总
  • <Java>Map<String,Object>中解析Object类型数据为数组格式
  • 别再分库分表了,试试TiDB!
  • Java进阶之Dump文件初体验
  • 基于扩展(EKF)和无迹卡尔曼滤波(UKF)的电力系统动态状态估计(Matlab代码实现)
  • 曲线拟合(MATLAB拟合工具箱)位置前馈量计算(压力闭环控制应用)
  • 小程序使用echarts
  • 面向对象——封装
  • 【LeetCode】160.相交链表
  • 【JWT的使用】
  • Python获取音视频时长
  • TCP四次握手为什么客户端等待的时间是2MSL
  • Android Studio 启用设备远程调试配置完整步聚
  • 玩转LaTeX(三)【数学公式(基础)、​矩阵、多行公式】
  • jenkins 配置git
  • 单机部署MinIo并设置开机自启
  • Latex | 使用MATLAB生成.eps矢量图并导入Latex中的方法
  • 宝塔面板定时任务重启各种服务
  • Ansible playbook编写
  • 个人博客系统 -- 登录页面添加图片验证码
  • 剑指offer10-I.斐波那契数列
  • 13年测试经验,性能测试-压力测试指标分析总结,看这篇就够了...
  • 大数据课程D3——hadoop的Source