一句话:计算图(Computational Graph)是把一次计算里「谁依赖谁、每一步算出了什么」记录下来的有向无环图;有了它,反向传播(backpropagation)才能沿着原路倒着走,用链式法则把梯度一项项乘回去。
前向:一边算,一边记账
假设要算 f(x, y, z) = (x + y) * z。代码只有一行,但运行时框架会把它拆成两个节点:先 a = x + y,再 f = a * z。加上 x、y、z 三个叶子,就得到一张小图:x、y 指向加法节点,加法节点和 z 指向乘法节点。
关键在于,算的过程中间结果 a 被留了下来。回头求导时要用它——乘法对加法那一路的导数正好是 z,对 z 的导数正好是 a。不记这笔账,反向时就得全部重算。
拿公司做比方:前向是生产流水线,每一步都记下「我这批货用了谁的料、用了多少」;反向就是客户退货后逐级追责,每个环节按当初的用料比例分摊责任。责任不能凭空估计,得翻账本。
反向:沿着边倒着走
从最终的标量损失出发,初始梯度是 1。每经过一个节点,就把上游传下来的梯度乘以本地的局部导数,继续往上游传。如果一个变量同时被两条分支用到(比如 x 既进加法又进乘法),两条路传回来的梯度要相加——这样它所有的贡献都不会被漏掉。
这也解释了反向模式的价值:深度学习是「几百万参数进去、一个标量损失出来」,反向走一遍就能拿到全部参数的梯度。
| 前向模式 | 反向模式 | |
|---|---|---|
| 遍历方向 | 输入 → 输出 | 输出 → 输入 |
| 一次遍历得到 | 一个输入的导数 | 全部参数的导数 |
| 适合场景 | 输入少、输出多 | 输入多、输出少(深度学习) |
和相邻概念的区别
自动微分(automatic differentiation)是算法,计算图是它跑起来的载体;数值微分用差分近似,符号微分直接对表达式求导,都不走这条「记账」路线。另外要区分动态图与静态图:前者边算边建,调试直观;后者先定义后执行,便于整体优化,部署中常见。具体行为以官方文档为准。
对从业者的实际意义
- 梯度是累加的:所以每轮训练前要手动清零,否则上一轮的贡献会混进来。
- 中间结果占显存:图的规模就是显存的主要开销之一,长序列、大 batch 都会把它撑大。
- 切断图就省资源:推理时用 no_grad 一类的方式不建图,只做前向,速度和内存都明显好转。
- AI 词典:梯度检查点">梯度检查点(gradient checkpointing)是拿计算换内存:丢掉中间结果,反向时再算一遍。
对普通人来说,这张图解释了训练为什么又慢又贵:不是模型「想」得慢,而是每一步都要为后面的追责留好凭证。
