讲师中心 微信公众号
AI工具推荐 视频效率加速

PyTorch中获取中间张量梯度值的实用指南

老明大大_8296

老明大大_8296

发布时间:2025-09-17 13:42:11

|

926人浏览过

|

来源于php中文网

原创

PyTorch中获取中间张量梯度值的实用指南

本文旨在解决PyTorch反向传播过程中获取非叶子节点(中间张量)梯度的问题。传统的register_backward_hook主要用于模块参数,对中间张量无效。我们将介绍一种通过retain_grad()方法结合张量引用存储来有效捕获并打印这些中间梯度的方法,并提供详细的代码示例与注意事项,帮助开发者更好地理解和调试模型。

理解PyTorch中的梯度与反向传播

在pytorch中,当我们构建一个神经网络并执行前向传播后,可以通过loss.backward()触发反向传播,计算模型参数的梯度。这些梯度是优化器更新参数的基础。然而,有时为了调试或深入理解模型的内部工作机制,我们可能需要查看非叶子节点(即计算图中的中间张量)的梯度。

PyTorch的自动微分系统(Autograd)默认情况下,在反向传播完成后会释放中间张量的梯度,以节省内存。此外,torch.nn.Module提供的register_full_backward_hook等钩子函数主要设计用于捕获模块输入和输出的梯度,或与模块参数相关的梯度,而非直接用于任意中间张量的梯度。

错误的尝试:使用钩子获取中间张量梯度

许多开发者可能会尝试使用模块的后向钩子来捕获中间张量的梯度,例如以下代码所示:

import torch
import torch.nn as nn

class func_NN(nn.Module):
    def __init__(self):
        super().__init__()
        self.a = nn.Parameter(torch.rand(1))
        self.b = nn.Parameter(torch.rand(1))

    def forward(self, inp):
        mul_x = torch.cos(self.a.view(-1, 1) * inp)
        sum_x = mul_x - self.b
        return sum_x

# 钩子函数
def backward_hook(module, grad_input, grad_output):
    print("module: ", module)
    print("inp_grad: ", grad_input)
    print("out_grad: ", grad_output)

# 模拟训练过程
a_true = torch.Tensor([0.5])
b_true = torch.Tensor([0.8])
x = torch.linspace(-1, 1, 10)
y = a_true * x + (0.1**0.5) * torch.randn_like(x) * (0.001) + b_true
inp = torch.linspace(-1, 1, 10)

foo = func_NN()
# 注册一个全反向传播钩子
handle_ = foo.register_full_backward_hook(backward_hook)

loss_fn = nn.MSELoss()
optimizer = torch.optim.Adam(foo.parameters(), lr=0.001)

print("--- 尝试使用钩子 ---")
for i in range(1): # 只运行一次以观察输出
    optimizer.zero_grad()
    output = foo.forward(inp=inp)
    loss = loss_fn(y, output)
    loss.backward()
    optimizer.step()

handle_.remove() # 移除钩子

上述代码中的backward_hook会打印func_NN模块的输入梯度和输出梯度,但它并不能直接提供mul_x或sum_x这些模块内部计算产生的中间张量的梯度。这是因为register_full_backward_hook捕获的是模块作为整体的输入和输出梯度,而不是其内部任意子表达式的梯度。

正确的方法:使用 retain_grad() 捕获中间张量梯度

要获取中间张量的梯度,我们需要明确告诉PyTorch的Autograd系统不要在反向传播后释放这些张量的梯度。这可以通过调用张量的retain_grad()方法来实现。此外,由于局部变量在函数结束后会超出作用域,我们需要将这些中间张量的引用存储在某个地方(例如作为nn.Module的属性),以便在反向传播完成后访问它们的.grad属性。

PyTorch Linux版 2.11.0
PyTorch Linux版 2.11.0

PyTorch 2.11.0 历史版本下载,来自 PyPI 官方发布,适合旧项目兼容、实验复现和指定环境安装。

下载

以下是修改后的代码示例:

import torch
import torch.nn as nn

class func_NN_RetainGrad(nn.Module):
    def __init__(self):
        super().__init__()
        self.a = nn.Parameter(torch.rand(1))
        self.b = nn.Parameter(torch.rand(1))
        # 用于存储中间张量的引用
        self.mul_x = None
        self.sum_x = None

    def forward(self, inp):
        mul_x = torch.cos(self.a.view(-1, 1) * inp)
        sum_x = mul_x - self.b

        # 关键步骤1: 对需要保留梯度的中间张量调用 retain_grad()
        mul_x.retain_grad()
        sum_x.retain_grad()

        # 关键步骤2: 存储中间张量的引用,以便反向传播后访问其 .grad 属性
        self.mul_x = mul_x
        self.sum_x = sum_x

        return sum_x

# 模拟数据
a_true = torch.Tensor([0.5])
b_true = torch.Tensor([0.8])
x = torch.linspace(-1, 1, 10)
y = a_true * x + (0.1**0.5) * torch.randn_like(x) * (0.001) + b_true
inp = torch.linspace(-1, 1, 10)

foo_retain = func_NN_RetainGrad()
loss_fn = nn.MSELoss()
optimizer = torch.optim.Adam(foo_retain.parameters(), lr=0.001)

print("\n--- 使用 retain_grad() 获取中间张量梯度 ---")

# 执行一次前向传播和反向传播
output = foo_retain.forward(inp=inp)
loss = loss_fn(y, output)
loss.backward() # 执行反向传播

# 反向传播完成后,现在可以访问中间张量的 .grad 属性
print("mul_x 的梯度:\n", foo_retain.mul_x.grad)
print("sum_x 的梯度:\n", foo_retain.sum_x.grad)

# 验证参数梯度是否正常计算
print("参数 a 的梯度:\n", foo_retain.a.grad)
print("参数 b 的梯度:\n", foo_retain.b.grad)

在这个修正后的示例中:

  1. 我们在forward方法中计算mul_x和sum_x之后,立即调用了它们的retain_grad()方法。这告诉Autograd在反向传播过程中不要清除这些张量的梯度信息。
  2. 我们将mul_x和sum_x赋值给self.mul_x和self.sum_x,将它们的引用存储在模块实例中。这样,即使forward方法执行完毕,我们仍然可以通过foo_retain.mul_x和foo_retain.sum_x访问到这些张量。
  3. 在调用loss.backward()之后,这些被保留的中间张量的梯度就可以通过它们的.grad属性被访问到并打印出来。

注意事项与最佳实践

  • 内存消耗: retain_grad()会阻止Autograd释放中间张量的梯度,这会增加内存消耗。因此,应仅在调试或特定需求时使用,并在不再需要时移除或避免在生产代码中大量使用。
  • 适用场景: retain_grad()适用于获取计算图中的任意中间张量的梯度。而模块钩子(如register_full_backward_hook)更适用于监控模块的输入/输出梯度,或者在模块级别执行一些操作。参数钩子(如param.register_hook)则用于直接修改或观察参数的梯度。
  • 调试工具: retain_grad()是一个强大的调试工具,可以帮助我们理解梯度流,发现潜在的梯度消失或梯度爆炸问题,或者验证自定义反向传播的正确性。
  • 何时调用: 必须在执行loss.backward()之前调用retain_grad()。如果在一个张量上多次调用retain_grad(),不会有额外影响。
  • 叶子节点: 对于叶子节点(如nn.Parameter),其梯度默认会被保留(如果requires_grad=True),无需调用retain_grad()。

总结

在PyTorch中获取非叶子节点(中间张量)的梯度,不能直接依赖于nn.Module的后向钩子。正确的做法是利用张量的retain_grad()方法,并在前向传播时将这些中间张量存储为模块的属性。这样,在反向传播完成后,我们就可以通过访问这些属性的.grad字段来获取其梯度。理解并正确使用retain_grad()对于深入调试和优化PyTorch模型至关重要,但同时也要注意其可能带来的内存开销。

热门AI工具

更多
PixTV
PixTV Hot

PixTV是一款面向AIGC内容创作的AI视频生成工具。

切问学术

切问学术是一款AI论文写作工具,复旦大学NLP团队推出的AI学术智能体。

DeepSeek

DeepSeek是一款面向对话、写作、编程和推理场景的AI大模型工具。

火山引擎

火山引擎是一款面向企业的云计算与AI服务平台。

WorkBuddy

一款AI办公效率工具,主要用于腾讯云推出的AI原生桌面智能体工作台,适合需要提升相关任务效率的用户。

Seko
Seko Hot

一款AI视频创作工具,主要用于商汤科技推出的创编一体的AI短视频创作Agent,适合需要提升相关任务效率的用户。

豆包大模型

豆包大模型是一款由字节跳动推出的企业级大语言模型服务平台。

墨刀AI
墨刀AI Hot

一款AI图像与设计工具,主要用于产品经理的专属智能体,适合需要提升相关任务效率的用户。

立刻MV
立刻MV Hot

立刻MV是一款AI文本写作工具,AI 音乐视频(MV)创作工具。

相关专题

更多
pytorch是干嘛的
pytorch是干嘛的

pytorch是一个基于python的深度学习框架,提供以下主要功能:动态图计算,提供灵活性。强大的张量操作,实现高效处理。自动微分,简化梯度计算。预构建的神经网络模块,简化模型构建。各种优化器,用于性能优化。想了解更多pytorch的相关内容,可以阅读本专题下面的文章。

1983

2024.05.29

Python AI机器学习PyTorch教程_Python怎么用PyTorch和TensorFlow做机器学习
Python AI机器学习PyTorch教程_Python怎么用PyTorch和TensorFlow做机器学习

PyTorch 是一种用于构建深度学习模型的功能完备框架,是一种通常用于图像识别和语言处理等应用程序的机器学习。 使用Python 编写,因此对于大多数机器学习开发者而言,学习和使用起来相对简单。 PyTorch 的独特之处在于,它完全支持GPU,并且使用反向模式自动微分技术,因此可以动态修改计算图形。

68

2025.12.22

LLVM自定义Pass怎么写
LLVM自定义Pass怎么写

本专题聚焦LLVM自定义Pass开发,整理Pass类结构、run()方法、PreservedAnalyses、CMake构建、插件注册、-load-pass-plugin加载和测试用例编写流程。

80

2026.09.30

LLVM RISC-V参数配置教程
LLVM RISC-V参数配置教程

本专题介绍LLVM对RISC-V基础ISA和扩展的支持方式,涵盖RV32、RV64、标准扩展、实验性扩展、厂商扩展、-menable-experimental-extensions和版本差异。

80

2026.09.30

LLVM IR中间表示入门指南
LLVM IR中间表示入门指南

本专题整理LLVM IR的核心概念,包括中间表示作用、模块结构、函数、基本块、SSA形式、类型系统和常见语法,帮助新手理解LLVM编译流程中的关键层。

40

2026.09.30

PDF转图片方法
PDF转图片方法

需要把 PDF 页面用于上传、预览、分享或图片归档时,PDF 转图片方法专题整理 JPG/PNG 格式选择、逐页导出、清晰度设置、批量下载和结果检查等流程,帮助用户稳定完成 PDF 图片化处理。

40

2026.09.30

PixTV AI视频生成与无限画布创作
PixTV AI视频生成与无限画布创作

PixTV专题整理AI视频与视觉内容创作相关功能使用教程,涵盖AI生图、视频生成、无限画布、多模型创作、素材管理、声音音乐及视频剪辑等功能,帮助用户快速掌握PixTV从创意到成片的完整制作方法。

60

2026.09.29

Buffalo框架数据库开发全教程
Buffalo框架数据库开发全教程

本专题围绕Buffalo框架数据库开发,讲解database.yml多环境配置、soda与fizz迁移生成回滚、模型结构体标签、增删改查与条件查询、一对多与多对多关联、数据校验、回调钩子、事务处理及原生SQL执行能力。

280

2026.09.23

Buffalo框架路由与请求处理实操指南
Buffalo框架路由与请求处理实操指南

本专题讲解Buffalo框架路由与请求处理机制,涵盖路由注册与分组、资源路由、Handler编写规范、Context上下文方法、参数绑定、中间件编写挂载、Session与Cookie读写、Flash消息及错误页面定制方法。

160

2026.09.23

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
Buffalo框架快速入门指南
Buffalo框架快速入门指南

共0课时 | 0人学习

Conan 2 高级依赖模型介绍
Conan 2 高级依赖模型介绍

共0课时 | 0人学习

Pandas 官方文档与用户指南
Pandas 官方文档与用户指南

共0课时 | 0人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn