MXNet autograd 自动微分实战指南:从梯度计算到自定义反向传播
深度学习人工智能机器学习分布式训练【免费下载链接】mxnetLightweight, Portable, Flexible Distributed/Mobile Deep Learning with Dynamic, Mutation-aware Dataflow Dep Scheduler; for Python, R, Julia, Scala, Go, Javascript and more项目地址https://gitcode.com/gh_mirrors/mx/mxnet点击查看免费下载本教程是 MXNet Crash Course 快速入门系列的第三步围绕mxnet.autograd包讲解如何在 Gluon 训练流程中完成梯度计算。你将掌握attach_grad()为 NDArray 挂载梯度、autograd.record()记录计算图、backward()触发反向传播、retain_graph控制计算图生命周期以及通过autograd.Function自定义前向/反向传播实现定制梯度。读完本节你可以无缝衔接本系列的 Step 4训练神经网络的必要组件。基本用法三步完成一次反向传播自动微分Autograd是训练神经网络的核心机制。MXNet 的autograd包会记录你在record()作用域内执行的运算并在调用backward()时按照链式法则自动计算梯度。使用前需要导入相关包并调用npx.set_np()启用 NumPy 兼容的 NDArray 接口from mxnet import np, npx from mxnet import autograd npx.set_np()以一个简单的标量函数 $f(x) 2x^2$ 为例推导可得 $\frac{dy}{dx} 4x$。首先为参数 $x$ 赋一个初始值x np.array([[1, 2], [3, 4]]) x接下来通过三步完成自动微分第一步调用attach_grad()申请梯度存储空间。在计算梯度之前需要告诉 MXNet 你打算为这个 NDArray 保存梯度x.attach_grad()从源码看attach_grad()会先为梯度分配一个与x同形状、同 dtype 的全零数组然后调用 C APIMXAutogradMarkVariables将x标记为需要计算梯度的变量见 ndarray.py 与 c_api_ndarray.cc。它的完整签名是attach_grad(grad_reqwrite, stypeNone)grad_req梯度累积方式可选write每次 backward 覆盖旧梯度默认、add每次 backward 累加到已有梯度上常用于梯度累积或null不计算梯度。内部通过_GRAD_REQ_MAP {null: 0, write: 1, add: 3}映射为整型传给底层引擎见 ndarray.pystype梯度数组的存储类型默认与x的存储类型一致可用于稀疏梯度场景。第二步在autograd.record()作用域内定义函数。把 $yf(x)$ 的表达式放在record()上下文中MXNet 就会记录下这段前向计算的执行轨迹以便后续求导with autograd.record(): y 2 * x * x第三步调用y.backward()触发反向传播y.backward()此时x.grad中保存的就是自动计算出的梯度。由于 $y2x^2$、$\frac{dy}{dx}4x$预期结果为[[4, 8], [12, 16]]验证如下x.gradbackward()的底层实现对应 C APIMXAutogradBackwardEx见 c_api_ndarray.ccPython 层的NDArray.backward(out_gradNone, retain_graphFalse, train_modeTrue)还额外支持传入out_grad指定头节点的梯度、通过retain_graph保留计算图、通过train_mode控制求导时的训练/推理模式见 ndarray.py。深入y.backward()等价于对和求导当 $y$ 包含多个元素时y.backward()等价于y.sum().backward()即先对输出求和再反向传播。下面这段代码与上面的结果完全一致with autograd.record(): y np.sum(2 * x * x) y.backward() x.grad这一设计保证了梯度可以顺利传播标量化的损失函数是训练中最常见的反向传播入口。retain_graph计算图默认只能用一次MXNet 默认在一次backward()之后就会释放计算图。若需要对同一计算图执行多次反向传播必须在调用时传入retain_graphTrue保留图结构。下面的示例演示了两种写法的差异with autograd.record(): y np.sum(2 * x * x) y.backward(retain_graphTrue) print(x.grad) print(Since you have retained your previous graph you can run backward again) y.backward() print(x.grad) try: y.backward() except: print(However, you cant do backward twice unless you retain the graph.)这段代码的执行流程是第一次backward(retain_graphTrue)保留计算图之后可以再次调用backward()第二次backward()未传retain_graph执行后计算图被释放第三次直接调用backward()会因计算图已不存在而抛出异常被try/except捕获。对应地在测试用例 test_autograd.py 中test_retain_graph也验证了「同一计算图不传retain_graph连续反向传播两次会失败而传retain_graphTrue后可以继续传播」的行为。此外NDArray还提供了drop_grad()主动释放已标记数组的梯度内存见 ndarray.py。自定义 MXNet ndarray 运算用autograd.Function改写梯度要真正理解backward()最好先弄清楚如何创建自定义运算。MXNet 的算子本质上是带有forward和backward两个方法的类其契约如下backward()的入参数目必须等于forward()的返回项数目即反向收到的梯度个数 前向的输出个数forward()的入参数目必须等于backward()的返回项数目即前向的输入个数 反向返回的梯度个数。因此你完全可以在backward()中修改梯度返回与真实导数不同的自定义梯度。下面的例子定义了一个三输入三输出的自定义算子并在反向中返回了「自定义」的梯度class MyFirstCustomOperation(autograd.Function): def __init__(self): super().__init__() def forward(self,x,y): return 2 * x, 2 * x * y, 2 * y def backward(self, dx, dxy, dy): The input number of arguments must match the number of outputs from forward. Furthermore, the number of output arguments must match the number of inputs from forward. return x, y使用这个自定义算子的方式与内置算子完全一致x np.random.uniform(-1, 1, (2, 3)) y np.random.uniform(-1, 1, (2, 3)) x.attach_grad() y.attach_grad() with autograd.record(): z MyFirstCustomOperation() z1, z2, z3 z(x, y) out z1 z2 z3 out.backward() print(np.array_equiv(x.asnumpy(), x.asnumpy())) print(np.array_equiv(y.asnumpy(), y.asnumpy()))从实现细节看autograd.Function.__call__会先临时关闭记录状态执行forward()再将自定义的反向回调通过MXCustomFunctionRecord注册进计算图反向传播时backward_entry会按grad_reqwrite/add等把自定义 backward 的返回值写入梯度缓冲区并严格校验「返回的 NDArray 个数必须等于 forward 的输入个数」见 autograd.py。每个Function实例只能被调用一次重复调用会触发断言需要每次新建实例。类中还提供了save_for_backward(*args)在forward中暂存中间张量供backward通过saved_tensors读取——这是实现数值稳定版 sigmoid 等自定义算子的常用手法见 autograd.py 中的完整示例。训练/推理模式is_training()与train_mode有时你希望函数在训练阶段和推理阶段表现不同例如 Dropout 随机丢弃、BatchNorm 使用批统计量。通过autograd.is_training()可以查询当前是否处于训练模式并据此分支def my_first_function(x): if autograd.is_training(): # Return something else when training return(4 * x) else: return(x)autograd.record()的默认行为是train_modeTrue你也可以显式指定y my_first_function(x) print(np.array_equiv(y.asnumpy(), x.asnumpy())) with autograd.record(train_modeFalse): y my_first_function(x) y.backward() print(x.grad) with autograd.record(train_modeTrue): # train_mode True by default y my_first_function(x) y.backward() print(x.grad)record(train_modeTrue)返回一个_RecordingStateScope上下文它会同时设置「记录状态」和「训练状态」两个全局开关对应的set_recording/set_training分别调用MXAutogradSetIsRecording/MXAutogradSetIsTraining并返回切换前的旧值退出with块时自动恢复见 autograd.py。除了recordautograd 模块还提供pause()在记录过程中临时停止记录常用于测试、IO 或参数更新等无需梯度的代码段train_mode()/predict_mode()只切换训练/推理状态而不改变记录状态例如在record()内部对某个子网络强制以推理模式前向。train_mode的语义在测试 test_is_train 中有完整覆盖其中还演示了backward(train_modeFalse)与record(train_modeFalse)必须配对使用否则梯度未定义。记录执行轨迹面向控制流的自动微分与静态图框架不同MXNet 的 autograd 是动态的它记录的是代码实际执行的计算轨迹因此天然支持while循环、if/else分支等控制流。下面的函数把输入a反复翻倍直到其norm这里用绝对值之和近似超过 1000再根据元素和的正负从b中挑选一个元素返回def f(a): b a * 2 while np.abs(b).sum() 1000: b b * 2 if b.sum() 0: c b[0] else: c b[1] return c记录执行轨迹并喂入一个随机初始值a np.random.uniform(size2) a.attach_grad() with autograd.record(): c f(a) c.backward()由于b是a的线性函数而c是从b中选出的某个元素因此a的梯度要么是[c/a[0], 0]要么是[0, c/a[1]]取决于最终选中了b的哪个元素。可以用下面的代码验证a.grad c / a如文档所述这里沿维度 0 存在 3 个值沿该轴取mean等价于先求和再乘以1/3这是读者在验证时需要注意的广播细节。这个例子直观展示了 MXNet 自动微分「按实际执行路径求导」的动态特性——记录的是运行时真实发生的运算序列而非静态展开的公式。进阶attach_grad()会切断梯度链路你可以针对不同的 ndarray 运算精细控制梯度传播。一个容易踩坑的点是attach_grad()会自动把自身从计算图中「分离」。这意味着在record()作用域内一旦对某个中间结果y调用了attach_grad()从该节点往前的输入x便不再出现在y的梯度回传路径上。对比下面两段代码即可看出差异。第一段代码对中间结果y调用了attach_grad()with autograd.record(): y 3 * x y.attach_grad() z 4 * y 2 * x z.backward() print(x.grad) print(y.grad)第二段代码没有调用with autograd.record(): y 3 * x z 4 * y 2 * x z.backward() print(x.grad) print(y.grad)两段代码中x.grad与y.grad的结果并不相同第一段里y被attach_grad()标记为新的变量起点梯度只回传到y为止第二段里梯度会继续穿过y回传到x。在源码层面attach_grad()通过MXAutogradMarkVariables把该数组登记为一个独立的变量节点从而切断了它与更早计算图的关联若想显式切断某一支路且不申请梯度缓冲也可以使用NDArray.detach()见 ndarray.py测试 test_detach_updated_grad 对该行为做了专门验证。组合使用把record()封装进函数autograd.record()完全可以封装进普通函数中这样调用方无需关心记录逻辑def my_second_function(x): with autograd.record(): return(2 * x)y my_second_function(x) y.backward() print(x.grad)多个这样的函数还可以互相组合梯度会沿着嵌套的记录作用域正确传播y my_second_function(x) with autograd.record(): z my_second_function(y) 2 z.backward() print(x.grad)这一模式正是 Gluon 模块的底层工作方式nn.Block的前向计算内部自动管理记录作用域用户在训练循环中只需写出with autograd.record(): output net(data)的范式。小结与下一步本节覆盖了 MXNet autograd 的完整使用路径基础流程attach_grad()申请梯度 →record()记录前向 →backward()反向传播 →x.grad读取梯度关键参数grad_req控制梯度写入/累加方式retain_graph控制计算图是否可复用train_mode控制训练/推理语义自定义算子继承autograd.Function重写forward/backward可注入自定义梯度契约是「backward 入参 forward 输出数backward 返回 forward 输入数」动态图特性autograd 按实际执行轨迹求导天然支持循环与分支控制流梯度切断attach_grad()与detach()会在指定节点截断梯度回传。本系列的后续内容将在此基础上展开接下来学习如何初始化权重、选择损失函数、评估指标与优化器请继续阅读 Step 4: Necessary components to train the neural network。若想复习本教程的前置知识可回顾 Step 1NDArray 与 NumPy 兼容接口 与 Step 2创建神经网络。完整的快速入门课程目录见 Crash Course 索引本系列各小节可独立阅读也可按顺序通读。赞分享深度学习人工智能机器学习分布式训练【免费下载链接】mxnetLightweight, Portable, Flexible Distributed/Mobile Deep Learning with Dynamic, Mutation-aware Dataflow Dep Scheduler; for Python, R, Julia, Scala, Go, Javascript and more项目地址https://gitcode.com/gh_mirrors/mx/mxnet点击查看免费下载相关推荐MXNet 自动微分实战指南mxnet.autograd 记录式计算图、反向传播与自定义梯度MXNet 自动微分实战指南mxnet.autograd 记录式计算图、反向传播与自定义梯度 导读 mxnet.autograd 是 MXNet 的命令式自动深度学习人工智能机器学习分布式训练MXNet autograd 自动微分实战指南从 NDArray 梯度计算到动态控制流MXNet autograd 自动微分实战指南从 NDArray 梯度计算到动态控制流 autograd 是 MXNet 的自动微分引擎它让求损失函数对权深度学习机器学习人工智能Warp 自动微分完全指南Tape 反向传播、Jacobian 计算与自定义梯度Warp 自动微分完全指南Tape 反向传播、Jacobian 计算与自定义梯度 本篇技术指南围绕 NVIDIA WarpGPU 加速的仿真、机器人与机器学高性能计算物理引擎图形学机器人创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

相关新闻

分形维数Matlab实现:差分盒维数、功率谱法与结构函数法详解

分形维数Matlab实现:差分盒维数、功率谱法与结构函数法详解

简介:面向图像处理、信号分析与复杂系统研究,这套MATLAB分形维数计算资源包提供了差分盒维数、功率谱和结构函数三种主要算法的代码实现,能够帮助解决非规则几何对象难以量化建模的问题。压缩包内共5个m文件,整体仅3KB&#xff0c…

2026/9/22 5:49:03 阅读更多 →
chezmoi 集成 gopass 密码管理器:gopass 模板函数配置与实现原理

chezmoi 集成 gopass 密码管理器:gopass 模板函数配置与实现原理

开发工具CLI配置管理 【免费下载链接】chezmoi Manage your dotfiles across multiple diverse machines, securely. 项目地址: https://gitcode.com/gh_mirrors/ch/chezmoi 点击查看 免费下载 导读 本指南围绕 chezmoi 提供的 gopass* 系列模板函数展开&#xff…

2026/9/20 23:47:54 阅读更多 →
Flow 静态类型检查实战:修复 `untyped-type-import` 错误,避免类型导入退化为 `any`

Flow 静态类型检查实战:修复 `untyped-type-import` 错误,避免类型导入退化为 `any`

开发工具静态分析代码质量 【免费下载链接】flow Adds static typing to JavaScript to improve developer productivity and code quality. 项目地址: https://gitcode.com/gh_mirrors/flow30/flow 点击查看 免费下载 导读 本文以 Flow 仓库中 lint_019_untyped_…

2026/9/20 23:47:54 阅读更多 →

最新新闻

昂达平板电脑root与汇编语言王爽对比选型

昂达平板电脑root与汇编语言王爽对比选型

昂达平板电脑root实战:避开高频面试题里的3个致命坑 刚接手昂达V818s老机子,想装个Xposed框架,结果刷完机一开机,屏幕炸出满屏红字。 java.lang.SecurityException: Permission denied…

2026/9/22 5:48:45 阅读更多 →
手写实现tcpmp核心协议,3天搞定面试原理难题

手写实现tcpmp核心协议,3天搞定面试原理难题

手写实现tcpmp核心协议,3天搞定面试原理难题 面试被问TCP原理,你只能背三次握手?面试官追问滑动窗口怎么控制,你支支吾吾答不上来?别慌,今天带你 手写实现 一个简化版的 tcpmp…

2026/9/22 5:48:45 阅读更多 →
建筑拆除考证入门到精通:5个致命坑与通过率真相

建筑拆除考证入门到精通:5个致命坑与通过率真相

建筑拆除考证入门到精通:5个致命坑与通过率真相 官方文档翻了三遍还是云里雾里?别慌,这不是你的问题。《注册建造师》或《安全工程师》关于建筑拆除的章节,官方大纲写得像天书,考点散落在全书各章,新手根本抓不住重点。很多人以为背完教材就能过,结果…

2026/9/22 5:48:45 阅读更多 →
3个坑搞懂rhr:新手避坑指南与实战选型对比

3个坑搞懂rhr:新手避坑指南与实战选型对比

3个坑搞懂rhr:新手避坑指南与实战选型对比 配置环境就卡半天,是不是你也经历过这种绝望?下载完依赖, npm install 转了十分钟,最后报一堆红色错误,日志里全是 ERR! 或者 ECONNRESET…

2026/9/22 5:47:44 阅读更多 →
fjtc配置卡壳?3步避坑指南让源码跑通

fjtc配置卡壳?3步避坑指南让源码跑通

fjtc配置卡壳?3步避坑指南让源码跑通 配置环境就卡半天,是不是觉得电脑要炸了?别慌,这不仅是你的问题,更是 fjtc 这类底层工具在集成时的典型“水土不服”。…

2026/9/22 5:47:44 阅读更多 →
西安华为研究所面试避坑 3 个手写实现核心考点拆解

西安华为研究所面试避坑 3 个手写实现核心考点拆解

西安华为研究所面试避坑 3 个手写实现核心考点拆解 报错堆满屏幕,StackTrace 长得像天书,面试官盯着你问底层逻辑?别慌。在西安华为研究所的面试实战中,光背八股文根本过不了关。很多候选人卡在 手写实现…

2026/9/22 5:47:44 阅读更多 →

日新闻

3台商务办公笔记本实测:手写实现环境配置,告别卡半天

3台商务办公笔记本实测:手写实现环境配置,告别卡半天

3台商务办公笔记本实测:手写实现环境配置,告别卡半天 配置环境就卡半天?别怪机器慢,多半是你没选对工具链。在Java、Go或Python的项目现场, 手写实现…

2026/9/22 0:00:41 阅读更多 →
剑帝加点速查手册:3分钟搞懂核心逻辑

剑帝加点速查手册:3分钟搞懂核心逻辑

剑帝加点速查手册:3分钟搞懂核心逻辑 面试被问原理答不上来,是不是常态?别慌。很多开发者对着 GitHub 开源仓库里的代码发呆,看似简单实则暗藏玄机。今天这份【剑帝加点】速查手册,直接带你拆解核心实现,把面试必考的原理讲透。…

2026/9/22 0:00:41 阅读更多 →
手写实现图片压缩网站核心:搞定WebP转换与质量调优

手写实现图片压缩网站核心:搞定WebP转换与质量调优

手写实现图片压缩网站核心:搞定WebP转换与质量调优 复制来的代码跑不通不知道怎么调?别慌,这种“复制粘贴地狱”在开发圈太常见了。尤其是做 图片压缩网站…

2026/9/22 0:00:41 阅读更多 →

周新闻

Flutter for OpenHarmony游戏卡片渐变背景实战:从原理到性能优化

Flutter for OpenHarmony游戏卡片渐变背景实战:从原理到性能优化

直接铺开项目本身吧。这几个月我一直在折腾一件事:用Flutter给OpenHarmony做一款游戏集合类的App,说白了就是把若干小游戏塞进一个壳里,用统一入口分发。这个方向本身不算新鲜,真正让我花了不少心思的,是首页那堆游戏卡…

2026/9/22 4:32:41 阅读更多 →
Word表格编号全攻略:从列表编号到题注交叉引用

Word表格编号全攻略:从列表编号到题注交叉引用

写Word文档,最让人头疼的往往是那些“看起来不起眼”的小问题。比如表格编号这事:今天在表后面多加了两个空白行,明天给客户交稿前发现整个章节的编号全部错位,光是挨个改序号就能耗掉大半个下午。我前阵子帮人整理一份上百页的技…

2026/9/22 4:38:57 阅读更多 →
从第一个站到第二个站:独立开发者的静态网站选型与落地实践

从第一个站到第二个站:独立开发者的静态网站选型与落地实践

1. 项目概述1.1 核心需求解析做独立开发者这几年,说实话,第一个网站上线的那天晚上我兴奋得没睡着。但等它跑了半年,流量惨淡、功能臃肿、代码自己都懒得看第二遍之后,我才慢慢琢磨明白一个道理:第一个网站是练手&…

2026/9/21 4:51:05 阅读更多 →

月新闻

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能分类:[AI/大模型]细分主题:AI 增强型 CI/CD 流水线自动化与 GitOps 实践:Agent 工作流、工具调用与任务拆解:从原型到生产的验收清单很多团队在尝试用大…

2026/9/21 15:36:51 阅读更多 →
容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场

容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场

容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场分类:[工程技术]细分主题:Kubernetes 生产环境运维与排障实战:可复制的项目复盘模板与决策记录大部分团队的事故复盘报告,最后都变成了躺在 Confluence 或钉…

2026/9/21 15:36:51 阅读更多 →
容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步

容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步

容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步分类:[工程技术]细分主题:Docker 容器化技术与镜像安全管理:核心链路的逐步实现与关键代码取舍面对一个积累了五六年历史包袱的单体架构应用(包含 Web 接口、后台…

2026/9/22 2:43:42 阅读更多 →