自动求导
PyTorch 的 autograd 和 burn 的 autodiff 都是反向模式(reverse mode):前向时记一张图,backward() 时倒着走一遍。算出来的梯度两边对得上(主线 MLP 的 67 个梯度最大误差 1.49e-8)。不同的是「状态放在哪」:PyTorch 把要不要梯度、梯度本身、图都挂在张量上,用全局的模式开关(torch.no_grad())控制记不记图;burn 把「记不记图」放在设备上,梯度放在 backward() 返回的值里,图只能用一次。
这一部分按训练主线的顺序走,每页一个 PyTorch 习惯:
- 打开求导:
requires_grad=True在 burn 里是两步:Device::flex().autodiff()加require_grad();PyTorch 一个requires_grad标志对应 burn 的三个查询;哪些错误在运行期报、哪一个仍在编译期。 - backward 与梯度:
.grad对x.grad(&grads);每次backward()一个新容器,所以没有累加、也没有zero_grad;梯度累积用GradientsAccumulator;非标量输出、中间结果、二阶导数两边各怎么处理。 - 图只能用一次:
retain_graph=True没有对应;PyTorch 的第二次 backward 看有没有释放保存的张量,burn 一律拒绝;把 loss 先加起来是两边都对的写法。 - 不求导的区域:
torch.no_grad()对without_autodiff()、Module::valid()、不带 autodiff 的设备;detach两边语义不同;只前向不反向时 burn 的图会一直占内存。
flowchart TB dev["设备带 autodiff"] --> leaf["require_grad 叶子"] leaf --> fwd["forward 记图"] fwd --> bw["loss.backward"] bw --> grads["Gradients 容器"] grads --> get["x.grad 取梯度"] bw -.->|"图被消耗"| again["再 backward 就 panic"] plain["设备不带 autodiff"] --> infer["推理不记图"]
burn 内部怎么记图、怎么执行反向,见 burn 卷的自动微分。这一部分只讲从 PyTorch 过来要改的写法,机制链过去。
💬 关联讨论
发起讨论加载中...