Rust in Everything
基于 burn 0.22.1

动手

前面各部分读的是 burn 的源码。这一部分反过来:不依赖 burn,用标准库自己把求导主线写一遍。张量是 Vec<f32> 加形状,计算图是一条按创建顺序追加节点的 tape,backward 按下标倒着走。写完之后让 burn 在 Device::flex().autodiff() 上算同一个模型的梯度,两边对一对。

  1. 写一个迷你自动微分:库 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 对梯度"]

💬 关联讨论

发起讨论
加载中...