新闻详情

新闻详情

首页 / 资讯中心 / 详情

昇思25天学习打卡营第6天 | 函数式自动微分:grad与stop_gradient配置实战

发布时间:2026/9/29 4:02:09来源:尧图网络
昇思25天学习打卡营第6天 | 函数式自动微分:grad与stop_gradient配置实战
1. 从一次梯度对不上的调试说起如果你正在跟昇思25天学习打卡营第6天大概率会卡在同一个地方明明照着示例写了mindspore.grad可一旦函数多返回了一个z求出来的w、b梯度就跟预期对不上数值直接翻倍。这不是你抄错了而是函数式自动微分里一个非常典型的现象——多输出函数的梯度会累加所有输出项对参数的贡献。MindSpore 的函数式自动微分Functional AutoDiff核心就两个接口grad和value_and_grad。它们把求导这件事做成了一种“函数变换”你给它一个函数它还你一个求导后的函数。这跟数学里d/dx算子的语义几乎一致所以叫“函数式”。而stop_gradient则是配套的“截断开关”用来告诉框架这个张量在反向传播时当作常数梯度到这儿就停。这篇内容面向两类人一是打卡营里想把第6天作业真正跑通的学员二是刚接触深度学习、对“梯度到底怎么流”还没建立直觉的入门者。我会用一个单层线性变换 二值交叉熵的最小例子把grad的grad_position参数、stop_gradient的截断效果、以及has_aux这个更省事的替代方案串起来。每一步都给可复制的代码和预期输出你照着敲一遍梯度控制逻辑基本就通了。需要说明的是下面所有实验都在 CPU 上跑MindSpore 版本建议 2.x。如果你还没装环境先pip install mindspore即可不需要 GPU 也能验证全部结论。2. TaoToken 前置把模型对话和接入文档放在手边打卡营的代码本身不依赖外部服务但学习过程中有两类问题很容易卡住一是 MindSpore 报错信息看不懂二是想对照某个 API 的官方语义。这时候我会开一个模型对话窗口把报错原文贴进去让它解释比翻文档快很多。如果你也想用这种方式辅助学习可以先把入口准备好。模型对话入口在https://taotoken.net/models?utm_sourcetaotoken_aicg_blog_endutm_contentmodel_chatutm_campaignrewrite适合贴报错、问概念、让它帮你逐行解释梯度代码。接入相关的文档在https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_contentdocutm_campaignrewrite里面能查到接口调用的基本约定。真正要写代码调 API 的时候Key 在https://taotoken.net/api-keys?utm_sourcetaotoken_aicg_blog_endutm_contentapi_keysutm_campaignrewrite生成API 基地址是https://taotoken.net/api。注意这个/api地址后面不加任何查询参数直接作为 base_url 用就行。如果你后面要长期做编码类任务或者搭 Agent可以看下 Coding Planhttps://taotoken.net/coding-plan?utm_sourcetaotoken_aicg_blog_endutm_contentcoding_planutm_campaignrewrite它更适合高频调用场景。这一节不是必须的但把对话和文档两个页面开着遇到grad_position该填几、has_aux返回结构是什么这类问题时能省不少来回搜索的时间。3. 可复制配置grad 与 stop_gradient 的最小骨架先把依赖和计算图搭起来。这个例子里x是 5 维输入w是 5×3 权重b是 3 维偏置y是 3 维标签。损失用binary_cross_entropy_with_logits它内部自带 sigmoid所以z不需要再过激活函数。import numpy as np import mindspore from mindspore import nn, ops from mindspore import Tensor, Parameter # 输入与标签 x ops.ones(5, mindspore.float32) y ops.zeros(3, mindspore.float32) # 可训练参数 w Parameter(Tensor(np.random.randn(5, 3), mindspore.float32), namew) b Parameter(Tensor(np.random.randn(3,), mindspore.float32), nameb) def function(x, y, w, b): z ops.matmul(x, w) b loss ops.binary_cross_entropy_with_logits( z, y, ops.ones_like(z), ops.ones_like(z) ) return loss loss function(x, y, w, b) print(loss)跑出来是一个标量类似0.17323041。到这里只是前向计算还没有求导。关键在下一步。mindspore.grad的第一个参数是待求导函数第二个参数grad_position指定对第几个入参求导。注意它是从 0 开始数的x是 0y是 1w是 2b是 3。所以对w、b求导就填(2, 3)。grad_fn mindspore.grad(function, (2, 3)) grads grad_fn(x, y, w, b) print(grads)输出是两个 Tensor一个形状[5, 3]对应w的梯度一个形状[3]对应b的梯度。因为x全是 1所以w梯度矩阵的每一行都相同这是正常现象不是 bug。现在引入多输出的坑。把函数改成同时返回loss和zdef function_with_logits(x, y, w, b): z ops.matmul(x, w) b loss ops.binary_cross_entropy_with_logits( z, y, ops.ones_like(z), ops.ones_like(z) ) return loss, z grad_fn mindspore.grad(function_with_logits, (2, 3)) grads grad_fn(x, y, w, b) print(grads)你会发现梯度值变了比之前大了一截。原因是grad默认对所有输出求和后再求导z也参与了梯度贡献。如果你只想让loss影响梯度就得用stop_gradient把z截断def function_stop_gradient(x, y, w, b): z ops.matmul(x, w) b loss ops.binary_cross_entropy_with_logits( z, y, ops.ones_like(z), ops.ones_like(z) ) return loss, ops.stop_gradient(z) grad_fn mindspore.grad(function_stop_gradient, (2, 3)) grads grad_fn(x, y, w, b) print(grads)这次梯度值就回到和最初function一致了。ops.stop_gradient(z)的作用是前向传播时z的值照常返回但反向传播时把它当常数梯度不往它身上流。还有一个更省事的写法是has_auxTrue。它等价于自动帮你对辅助输出做stop_gradientgrad_fn mindspore.grad(function_with_logits, (2, 3), has_auxTrue) grads, (z,) grad_fn(x, y, w, b) print(grads, z)注意返回结构变成了(梯度元组, 辅助输出元组)所以解包时要写成grads, (z,)。梯度值和stop_gradient版本一致同时z还能拿到。4. 验证请求与成功结果用 value_and_grad 跑通神经网络反向传播前面都是纯函数实际训练里模型是nn.Cell的子类。把同样的逻辑搬到 Cell 上用value_and_grad一次拿到 loss 和梯度。class Network(nn.Cell): def __init__(self): super().__init__() self.w w self.b b def construct(self, x): return ops.matmul(x, self.w) self.b model Network() loss_fn nn.BCEWithLogitsLoss() def forward_fn(x, y): z model(x) return loss_fn(z, y) grad_fn mindspore.value_and_grad( forward_fn, None, weightsmodel.trainable_params() ) loss, grads grad_fn(x, y) print(loss) print(grads)这里value_and_grad的第二个参数传None表示不对输入求导只对weights指定的可训练参数求导。跑出来的梯度应该和前面function版本的w、b梯度完全一致。如果一致说明你已经把函数式自动微分和面向对象的 Cell 模型打通了。验证成功的标志有三个一是loss是标量且数值合理二是grads里w梯度形状[5, 3]、b梯度形状[3]三是数值和纯函数版本对得上。三个都满足这一天的核心目标就达成了。5. 本篇常见错排查报错一grad_position填错导致梯度形状不对。最常见的是把(2, 3)写成(1, 2)结果对y和w求了导y是常量标签梯度自然不对。记住入参顺序x0, y1, w2, b3。如果你改了函数签名位置要重新数。报错二多输出时梯度翻倍却找不到原因。只要函数返回了多个 Tensorgrad就会对所有输出求和求导。解决办法二选一要么在返回前对辅助输出套ops.stop_gradient要么在grad里加has_auxTrue。后者更推荐因为不用改函数体。报错三has_auxTrue后解包报too many values to unpack。这是因为返回结构从grads变成了(grads, aux)。正确写法是grads, (z,) grad_fn(...)注意z外面那层括号不能少因为辅助输出本身是个元组。报错四value_and_grad里weights传了空列表。如果model.trainable_params()返回空说明参数没有用Parameter包装或者没挂到 Cell 属性上。检查self.w w里的w是不是Parameter类型。报错五CPU 上跑ops.ones_like报 dtype 不匹配。binary_cross_entropy_with_logits的权重参数要求 float32如果你前面用了 float64 建张量这里会报错。统一用mindspore.float32就行。6. 继续往下走把梯度控制用起来函数式自动微分的价值不在于会调grad而在于你能精确控制“哪些输出影响梯度、哪些不影响”。stop_gradient和has_aux就是两个最常用的控制手段前者用于手动截断后者用于多输出场景的自动处理。如果你在打卡营后续要搭更复杂的模型比如多任务学习里只想让某个分支的 loss 回传或者预训练层冻结只训新加层这两个接口会反复出现。建议把上面的代码存成一个.py文件改改grad_position和has_aux多跑几组观察梯度数值的变化比只看文档印象深得多。遇到 MindSpore 的报错拿不准时把完整 traceback 贴到模型对话里问一下通常能快速定位到是grad_position还是has_aux的问题。接入文档里也有grad和value_and_grad的参数说明配合着看效率更高。
网站建设高端定制企业官网
RELATED

相关资讯

更多精彩内容,欢迎继续阅读

较早相关资讯

最新相关资讯

读书笔记:软件架构设计原则 - 组件原则(Principles of Component)(中英文对照) 2026/9/29 7:40:41

读书笔记:软件架构设计原则 - 组件原则(Principles of Component)(中英文对照)

读【美】Robert C. Martin(罗伯特 C. 马丁)的《架构整洁之道》(Clean Architecture)有感,做个整理。本文不是逐字翻译向,算是个人见解的注释。 组件内聚原则 组件内聚原则主要讨论拿些类应该聚合在一个组件…

阅读更多 →
从手动调参到AutoML:用TPOT自动构造机器学习pipeline的完整实践 2026/9/29 7:40:41

从手动调参到AutoML:用TPOT自动构造机器学习pipeline的完整实践

1. 从手动调参到AutoML:我为什么最终留下了TPOT先交代一下背景。我大部分时间在做表格类机器学习项目,客户那边的数据基本在几万到几十万行量级,变量几十到几百个。这类项目最花时间的不是写模型代码,而是把数据预处理、特征选择、…

阅读更多 →
FanControl完整教程:从安装到静音配置,5步搞定Windows风扇控制 2026/9/29 7:40:40

FanControl完整教程:从安装到静音配置,5步搞定Windows风扇控制

FanControl完整教程:从安装到静音配置,5步搞定Windows风扇控制 【免费下载链接】FanControl.Releases This is the release repository for Fan Control, a highly customizable fan controlling software for Windows. 项目地址: https://gitcode.com…

阅读更多 →
基于MCP与Docker构建LLM Agent持久记忆系统实战 2026/9/29 7:40:32

基于MCP与Docker构建LLM Agent持久记忆系统实战

1. 从“hindsight”说起:为什么我们需要给Agent装上记忆“hindsight”这个词本身很有意思,字面意思是“事后的洞察力”,也就是我们常说的“后见之明”。放在LLM Agent的语境里,它指向一个非常具体且棘手的问题:Agent如…

阅读更多 →
Model-Optimizer 模型优化实战:从图优化、量化到剪枝蒸馏的工程落地指南 2026/9/29 7:40:32

Model-Optimizer 模型优化实战:从图优化、量化到剪枝蒸馏的工程落地指南

模型优化这件事,很多人第一反应是调参、换网络结构、加数据。但真正在工程一线待过的人都知道,一个模型从实验室的 checkpoint 到线上可用的服务,中间隔着的往往不是算法问题,而是一整套系统性的优化工程。Model-Optimizer 这个方…

阅读更多 →
C++初阶—模板初阶 2026/9/29 7:40:25

C++初阶—模板初阶

第一章:泛型编程如何实现一个通用的交换函数呢?void Swap(int& left, int& right) {int temp left;left right;right temp; }void Swap(double& left, double& right) {double temp left;left right;right temp; }void Swap(char&…

阅读更多 →

今日资讯

本周资讯

本月资讯

看完文章仍有疑问?

联系尧图顾问,获取一对一建站咨询

立即免费咨询 📞 400-888-8888
📞 ✉