返回 M01~M90 教材库
M03 · 预习教材教材已备 ≠ 学习已完成

M03:用 PyTorch autograd 重建并检查梯度

autograd 根据张量运算动态建立计算图并执行向量—雅可比积,梯度检查则用数值扰动验证其结果是否符合预期。

2026-08-26PyTorch、autograd、有限差分、CPU、MPS

内容类型:预习教材(不代表已完成)
日期:2026-08-26
阶段:P1 · AI Model Engineering 90
周次:W1 · 张量、梯度、autograd
节奏:周三引导练习
状态:教材已备;学习未完成
标签:PyTorch、autograd、有限差分、CPU、MPS

一句话定义

autograd 根据张量运算动态建立计算图并执行向量—雅可比积,梯度检查则用数值扰动验证其结果是否符合预期。

学习目标

  1. 用 PyTorch 重建 M02 的同一表达式并查看梯度。
  2. 理解叶子张量、grad_fn、detach 与 no_grad 的差别。
  3. 会用中心有限差分检查一个参数的梯度。
  4. 知道 CPU/MPS 对比应控制输入、dtype 和随机性。

核心知识

当 requires_grad=True 的张量参与运算时,PyTorch 会为后续结果保存反向所需的信息。用户创建且不是其他运算结果的可训练参数通常是叶子张量,它的 grad 在 backward 后可见;中间张量默认不保留 grad,但带有 grad_fn,表示它由哪个反向算子产生。

backward 对标量输出计算梯度;若输出是向量,需要显式提供同形状的上游向量,本质上计算向量—雅可比积。计算图默认在一次 backward 后释放,再次反向需重新正向计算,或在确有需要时保留图。训练循环通常每轮重新建图,这让 Python 控制流也能参与模型定义。

detach 返回共享数据但脱离当前计算图的张量;no_grad 是作用域级开关,常用于评估和参数更新。两者都不是简单的“节省内存按钮”:错误地截断图会导致预期参数没有梯度。

机制与推导

对参数 θ,中心差分 g_num = [L(θ+ε)-L(θ-ε)]/(2ε)。autograd 给出 g_auto。可以比较绝对误差 |g_auto-g_num|,更稳妥的是相对误差 |差值|/(|g_auto|+|g_num|+δ)。双精度和适中的 ε 更适合检查;float32、MPS 或非光滑点附近可能产生更大偏差。

CPU/MPS 对比需要区分三类问题:能否执行、数值是否在容差内一致、性能是否更好。先用相同数据和参数在 CPU 建立基线,再把模型与数据一起迁移;跨设备张量不能直接运算。小任务的单次耗时容易被首次编译、同步和数据搬运扭曲,因此本日重点是机制观察,不做性能结论。

最小练习

  1. 用标量张量复现 M02 的正向公式,保留与手算相同的中间节点。
  2. 调用一次 backward,记录叶子参数的 grad,并与手算表达式逐项对应。
  3. 在 no_grad 作用域中分别扰动参数 ±ε,算中心差分。
  4. 若 MPS 可用,用完全相同的输入重复正反向,只记录是否执行与容差观察。
  5. 对一个中间张量调用 detach,预测哪条梯度路径会消失,再决定是否实验。

常见误区

  • 把 tensor.grad 为 None 一律当作错误;中间张量默认就不保留梯度。
  • 在同一图上连续 backward,却不知道图已释放或梯度在累加。
  • 用 detach 取数后继续计算,误以为原路径仍可求导。
  • CPU 与 MPS 出现末位差异就判断实现错误;浮点运算顺序可能不同。
  • 只检查一个随机点;在饱和区、非光滑点或梯度接近零时检查可能失真。

场景连接

自定义金融损失、排序目标或风险惩罚项比标准分类损失更容易写错。先在小张量和双精度上做有限差分,可以把“目标设计有问题”与“梯度实现有 bug”分开。

自检问题

  1. 为什么非标量输出调用 backward 时需要上游梯度?
  2. detach 和 no_grad 分别作用在什么层面?
  3. 为什么有限差分通常使用中心形式而不是单边形式?
  4. CPU/MPS 的一次耗时为何不能直接代表真实吞吐?

专业课程对齐

  • PyTorch Autograd 教程:对应计算图、Jacobian-vector product、梯度关闭与累积,是本日主教材。
  • PyTorch Tutorials:对应 autograd 与模型训练的官方示例,重点查阅张量梯度、优化循环和梯度检查相关内容。
  • Stanford CS229 Materials:对应数值优化基础,为有限差分为何只能近似梯度提供数学背景。

深入学习提示

按“autograd 精读 → 官方训练示例对照 → CS229 选读”的顺序进行。代码上同时保留解析梯度、autograd 梯度和中心差分三列,使用相对误差而非只看绝对差,并扫描多个 ε;过大时截断误差明显,过小时浮点消减会放大。观察非叶子张量默认为何没有 .graddetach() 如何切断图、原地操作何时破坏反传需要的中间值。反例应包含 ReLU 在零点不可导、float32 下极小 ε 检查失败、损失未缩放导致梯度量级变化;结论应是梯度检查能发现实现不一致,却不能证明目标函数或数据设计正确。

学后填写区

  • autograd 与手算的对应:____
  • 梯度检查设置:____
  • CPU/MPS 实际观察(未运行可留空):____
  • 新出现的问题:____
  • 实际学习日期与用时:____
学完后,请把自己的理解、练习结果和仍不确定的问题写入文末“学后填写区”,再到唯一进度账本更新状态。预先阅读后续教材不会自动增加完成数。