返回首页

Post

舍入误差、Taylor 系数与 reverse-mode 的数值分析前史

Linnainmaa 1976 年论文从有限精度计算出发,把累计舍入误差写成局部误差的 Taylor 展开,并由此暴露出 reverse-mode automatic differentiation 后来长期面对的两件事:反向累积影响系数与保存计算轨迹的存储代价。

分类
标签
合集

Linnainmaa 讨论的对象是有限精度计算中的舍入误差。一个数值过程在实数域里可以写成精确的运算序列,但机器实际执行时每一步都会经过浮点舍入,最终结果便会偏离无舍入时的理想结果。论文把最终偏差称为 accumulated rounding error,把每一步单独产生的偏差称为 local rounding error。它要解决的问题很具体:最终累计误差能否表示成各个局部误差的函数,这种函数的 Taylor 展开系数能否通过算法系统求出。

这篇文章还没有进入神经网络训练语境,也没有使用今天 automatic differentiation 教材中的术语。它的历史价值在于,论文已经把一个复合计算过程中的“末端量对中间扰动源的敏感性”组织成可递推的系数计算问题。后来的 reverse-mode AD 抽象出的是标量末端量对中间变量的导数累积;再往后的 backpropagation 则把这种反向累积用于损失函数对激活和参数的梯度。对象不同,但反向组织局部影响的骨架已经在这里出现。

舍入误差作为复合计算问题

论文先把计算过程写成一个有序变量序列

u1,u2,,uN,u_1,u_2,\dots,u_N,

其中部分变量是初值,其余变量由较早出现的变量通过二元运算得到:

ui=Qi(uj,uk),j,k<i.u_i = Q_i(u_j,u_k),\qquad j,k<i.

QiQ_i 可以代表加、减、乘、除等基本运算。实际浮点计算得到的是 uiu_i',它来自对本步精确运算结果的舍入:

ui=fl(Qi(uj,uk),t).u_i' = \mathrm{fl}(Q_i(u_j',u_k'),t).

本步局部舍入误差定义为

ri=uiQi(uj,uk),r_i = u_i' - Q_i(u_j',u_k'),

累计舍入误差定义为

Ri=uiui.R_i = u_i' - u_i.

这组定义把问题拆成了两个层次。本步运算会引入新的局部误差 rir_i,前序变量已经积累的误差 Rj,RkR_j,R_k 又会通过 QiQ_i 继续影响当前结果。由定义可得

Ri=ri+Qi(uj,uk)Qi(uj,uk).R_i = r_i + Q_i(u_j',u_k') - Q_i(u_j,u_k).

QiQ_i(uj,uk)(u_j,u_k) 附近做 Taylor 展开,就能把 RiR_i 写成 RjR_jRkR_k 和局部误差项的组合。保留一阶项时,核心关系可以写成

Riri+di,jRj+di,kRk,R_i \approx r_i + d_{i,j}R_j+d_{i,k}R_k,

其中

di,j=Qiuj,di,k=Qiuk.d_{i,j}=\frac{\partial Q_i}{\partial u_j},\qquad d_{i,k}=\frac{\partial Q_i}{\partial u_k}.

二阶和更高阶项对应 QiQ_i 的更高阶偏导数。论文明确指出,很多情形下一阶 Taylor 项已经能较准确地近似累计误差,因此全文重点放在一阶系数的确定上,同时讨论更高阶系数和存储需求。

一阶系数的反向闭合

Riri+di,jRj+di,kRkR_i \approx r_i + d_{i,j}R_j+d_{i,k}R_k

出发,真正要解决的不是把单步 Taylor 式写下来,而是怎样把整条计算链上的这些局部关系系统消去,最终得到 RNR_N 对所有局部误差的展开。若直接手工代入,很快会被分支依赖淹没;论文的重要一步,是把这个代入过程本身也组织成一趟可执行的递推。

先把反向阶段真正累积的对象说清楚。设 cic_i 表示“当前表达式里 RiR_i 的系数”。一开始目标就是最终累计误差本身,所以有

cN=1,ci=0 (iN).c_N=1,\qquad c_i=0\ (i\neq N).

若第 ii 步由 ui=Qi(uj,uk)u_i=Q_i(u_j,u_k) 生成,那么把表达式中的 ciRic_iR_i 用上一节的一阶式替换,就得到

ciRiciri+cidi,jRj+cidi,kRk.c_iR_i \approx c_ir_i + c_id_{i,j}R_j + c_id_{i,k}R_k.

这一步同时完成两件事。第一,cic_i 立刻成为局部误差 rir_iRNR_N 中的系数,因此可记

λi=ci.\lambda_i=c_i.

第二,同一个 cic_i 还要继续分发给它的前驱 Rj,RkR_j,R_k,因为更早的累计误差正是通过第 ii 步传到末端的。于是,一趟按 i=N,N1,i=N,N-1,\dots 逆序进行的扫描就闭合了整个一阶求解:处理到第 ii 步时,先把当前的 cic_i 记作 λi\lambda_i,再把 cidi,jc_id_{i,j}cidi,kc_id_{i,k} 分别累加到 cjc_jckc_k 上。扫描结束后便得到

RNiOλiri,R_N \approx \sum_{i\in\mathcal O}\lambda_ir_i,

其中 O\mathcal O 表示真正执行舍入的运算步骤集合。

若把某个前序变量 usu_s 的总系数单独写出来,这个逆序扫描满足

cs=:us 是 Q 的输入cd,s,cN=1.c_s=\sum_{\ell:\,u_s\text{ 是 }Q_\ell\text{ 的输入}} c_\ell d_{\ell,s},\qquad c_N=1.

这里求和必须遍历 usu_s 的所有直接后继 \ell,而不是只沿某一条链回代。原因很简单:一个中间变量可能同时被多步运算复用,它对最终累计误差的一阶影响会沿多条下游路径传播,只有把这些路径在第一跳上的贡献全部加回 csc_s,敏感性才真正闭合。

一个最小例子就能看出这种“后继求和”为何不可省略:

graph TD subgraph F["前向依赖"] U1["u1"] --> U4["u4 = Q4(u1,u2)"] U2["u2"] --> U4 U2 --> U5["u5 = Q5(u2,u3)"] U3["u3"] --> U5 U4 --> U6["u6 = Q6(u4,u5)"] U5 --> U6 end subgraph B["反向系数"] C6["末端初始化<br/>c6 = 1"] --> C45["先传给直接前驱<br/>c4 += c6 d6,4<br/>c5 += c6 d6,5"] C45 --> C2["u2 的总系数要汇总两条后继路径<br/>c2 += c4 d4,2 + c5 d5,2"] end

这个结构已经非常接近今天所说的 reverse-mode:前向阶段生成有序依赖,后向阶段不再枚举每个局部误差到末端的所有完整路径,而是把“到达当前节点的总影响”压缩成一个系数,再向更早的节点继续传递。差别只在于,这里反向组织的是累计舍入误差对局部舍入源的影响系数,而不是损失函数对参数的梯度。

计算轨迹与存储代价

Linnainmaa 在引言中把存储问题直接摆了出来:若要在计算完成后再以算法方式求这些 Taylor 系数,就不能只保留最后的数值结果,还得保留足以重建局部递推的信息。上一节的 cic_i 递推也说明了这一点。反向扫描处理第 ii 步时,至少要知道两类对象:这一步究竟是由哪一个 QiQ_i 和哪几个前驱变量生成的,以及求 di,j,di,kd_{i,j},d_{i,k} 时所需的前向值。没有这些信息,cic_i 就无法继续分发给更早的节点。

因此,一趟前向计算如果把中间状态完全丢掉,后向阶段就失去了可执行对象;要么存下操作轨迹与必要中间值,要么付出额外重算去把它们恢复出来。反向组织一阶系数确实避免了对每个局部误差单独做一次完整前向扰动,但代价并没有消失,而是转化成了另一类资源问题:前向信息要保留多少,后向阶段又要依赖这些信息到什么程度。

这正是后来的 reverse-mode AD 会反复遇到的同一结构。现代系统常把前向留下来的记录叫作 tape、trace 或 computational graph;神经网络训练里更常见的说法则是保存激活、释放中间张量或用重算换存储。术语不同,约束相同:只要反向阶段要沿依赖关系恢复局部敏感性,前向轨迹就不再是一次性消耗品。

reverse-mode 前史中的三条线索

把 Linnainmaa 1976 放进反向传播起源序列时,最应保留三条线索。第一,论文把累计舍入误差写成局部舍入误差的 Taylor 展开,明确了复合计算过程中局部扰动如何影响末端结果。第二,它把一阶影响系数的求取变成一趟逆序可执行的递推:从末端初始化系数,再把系数沿依赖关系分发给前驱。第三,它很早就指出,这种反向组织并不免费,前向阶段必须留下足够的信息,存储成本因此可能成为实际瓶颈。

这条历史线的边界同样要守住。在舍入误差分析里,局部源是各步运算产生的 rir_i,末端量是累计误差 RNR_N;在更一般的 reverse-mode AD 里,反向累积的通常是某个标量输出对中间变量的敏感性,中间变量是导数链经过的节点,本身不必是误差源。到了神经网络训练里,末端对象变成损失 LL,反向经过的是样本相关的激活与 pre-activation,最终还要落到可学习参数的梯度上,由这些梯度驱动参数更新。

因此,更准确的历史关系是:Linnainmaa 1976 给出了在有序复合计算上反向组织一阶影响系数的数值分析原型;reverse-mode AD 把这种原型抽象成通用的导数计算方式;Rumelhart、Hinton 与 Williams 1986 则把它落实为多层网络中的误差回传与表征学习机制。它们确实相连,但不能靠“把对象简单替换一下”来压缩成同一个命题。

较新文章隐藏层的训练信号:重读 Back-Propagating Errors2026年4月23日更早文章Attention Is All You Need:全局注意力如何重写序列计算2026年4月22日

相关文章