动手
前面各部分读的是 burn 的源码。这一部分反过来:不依赖 burn,用标准库自己把求导主线写一遍。张量是 Vec<f32> 加形状,计算图是一条按创建顺序追加节点的 tape,backward 按下标倒着走。写完之后让 burn 在 Device::flex().autodiff() 上算同一个模型的梯度,两边对一对。
- 写一个迷你自动微分:库 265 行代码,
add、mul、matmul、relu、sum五个算子各带反向。节点在Vec里的下标就是一个拓扑序,backward不用排序,和 burn 按深度分桶的做法对照。七个有限差分测试逐个核对算子,一个两层 MLP 用普通 SGD 学会 XOR,同一个 MLP 的梯度和 burn 逐位相同。把梯度累加换成覆盖,XOR 照样收敛,只有有限差分和对照 burn 能发现。最后一张表列出 burn 多出来的东西(对任意后端的装饰、检查点、按需释放节点、图合并、多后端、融合)和讲它们的页。
flowchart TB ten["Tensor Vec f32 加形状"] --> tape["Tape 追加节点"] tape --> bw["backward 下标倒序"] bw --> grads["Gradients 按 id"] grads --> fd["有限差分核对"] grads --> xor["SGD 训练 XOR"] grads --> cmp["和 burn Flex 对梯度"]
💬 关联讨论
发起讨论加载中...