Part V · 第 17 章 网络架构 · 17.2Part V · Ch. 17 Network Architectures · 17.2

RNN 与状态空间模型RNNs & State-Space Models

机器人的一帧传感器读数往往不够:速度要从几帧位置里推出来,负载要从关节怎样响应里看出来。循环神经网络(RNN)给网络一个随时间更新的隐藏状态,它就是 13.2 节的状态空间模型,只是矩阵从数据里学出来。本节在浏览器里现场训练 RNN 估计关节速度,看梯度为什么会随时间消失或爆炸、LSTM 与 GRU 的门怎样修好它,再看 S4、Mamba 这类线性状态空间层:它们能像卷积一样并行训练、像滤波器一样逐步推理,Mamba 还让步长随输入变化,从而学会“挑着记”。 One frame of sensor readings is often not enough for a robot: velocity has to be inferred from several frames of position, a payload from how the joints respond. A recurrent neural network (RNN) gives the network a hidden state that is updated over time; it is the state-space model of Lesson 13.2 with matrices learned from data. In this lesson you train an RNN live in the browser to estimate joint velocity, see why gradients vanish or explode through time and how LSTM and GRU gates fix that, and then meet linear state-space layers such as S4 and Mamba: they train in parallel like a convolution and run step by step like a filter, and Mamba lets the step size depend on the input, so it learns what to remember.

约 45 分钟~45 min 前置:16.3 反向传播 · 13.2 状态空间与稳定性 · 4.8 卡尔曼滤波 · 17.1 MLP 与 CNNPrereqs: 16.3 Backpropagation · 13.2 State space & stability · 4.8 Kalman filter · 17.1 MLPs & CNNs 6 个交互6 interactives

    1为什么机器人需要它Why robots need this

    17.1 节的 MLP 和 CNN 都是“一次看一张”:同样的输入永远给出同样的输出。可机器人关心的很多量不在任何一帧读数里。关节编码器只给角度,速度要靠前后几帧之差;腿式机器人的本体感觉(proprioception,关节角、角速度、IMU)里没有“地面有多滑”这一项,只有当腿踩下去、关节怎样响应时才看得出来;夹爪闭合后物体被手挡住,相机这一帧看不到它,但上一秒看到过。这些问题的共同点是:答案藏在历史里,用 20.1 节的话说,观测只是部分可观测的。

    经典的答案是滤波:4.8 节的卡尔曼滤波维护一个状态估计,每来一个测量就更新一次,更新规则来自人写的运动模型和噪声模型。学习的答案是同一个结构,但让数据来写规则:给网络一个隐藏状态 \(\mathbf h_t\),每一步用当前输入和上一步的状态算出新的状态。这就是循环神经网络(RNN)。它有两个大家族:带非线性和“门”的 RNN(LSTM、GRU),以及把递推保持为线性的状态空间模型(S4、Mamba),后者正是 13.2 节的 \(\mathbf x_{k+1}=A_d\mathbf x_k+B_d\mathbf u_k\),矩阵由训练得到。

    为什么不干脆把最近 \(n\) 帧拼起来喂给 MLP,或者用 17.3 节的 Transformer 看整段历史?也可以,而且很多机器人系统就是这样做的(第 6 节)。循环模型的卖点是:每个控制周期只花固定的计算和固定的内存,历史再长也一样;这在几十到几百赫兹的控制回路、跑在机载计算机上的策略里很重要。本节从“状态 = 记忆”出发,现场训练一个 RNN,看清它训练时的主要困难(梯度随时间消失或爆炸)和各种解法。

    The MLPs and CNNs of Lesson 17.1 look at one input at a time: the same input always gives the same output. Yet many quantities a robot cares about are not in any single frame of readings. A joint encoder gives the angle; velocity needs the difference between frames. The proprioception of a legged robot (joint angles, joint velocities, the IMU) contains no entry called "how slippery is the ground"; it shows only in how the joints respond when a foot comes down. Once the gripper closes, the hand hides the object from the camera, which saw it a second ago. These problems share one feature: the answer lies in the history; in the words of Lesson 20.1, the observation is only partially observable.

    The classical answer is filtering: the Kalman filter of Lesson 4.8 keeps a state estimate and updates it with every measurement, using rules derived from a hand-written motion model and noise model. The learning answer has the same structure but lets data write the rules: give the network a hidden state \(\mathbf h_t\), and at every step compute the new state from the current input and the previous state. That is a recurrent neural network (RNN). There are two big families: RNNs with nonlinearities and "gates" (LSTM, GRU), and state-space models (S4, Mamba) that keep the recurrence linear; the latter are exactly the \(\mathbf x_{k+1}=A_d\mathbf x_k+B_d\mathbf u_k\) of Lesson 13.2 with matrices obtained by training.

    Why not just stack the last \(n\) frames and feed them to an MLP, or let the Transformer of Lesson 17.3 look at the whole history? That works too, and many robot systems do exactly that (Section 6). The selling point of a recurrent model is that each control cycle costs a fixed amount of computation and memory, however long the history; this matters for control loops running at tens to hundreds of hertz and for policies on an onboard computer. This lesson starts from "state = memory", trains an RNN live, and looks closely at the main difficulty in training it (gradients that vanish or explode through time) and at the ways around it.

    2直觉:状态是一段压缩的记忆,特征值决定它记多久Intuition: the state is a compressed memory, and eigenvalues decide how long it lasts

    RNN 的全部定义就是一个递推式:

    An RNN is defined entirely by one recurrence:

    $$ \hl{h}{\mathbf h_t}=\phi\big(W_h\,\mathbf h_{t-1}+W_x\,\mathbf x_t+\mathbf b\big),\qquad \hat{\mathbf y}_t=W_y\,\mathbf h_t+\mathbf b_y,\qquad \mathbf h_0=\mathbf 0 . $$

    \(\mathbf x_t\) 是第 \(t\) 步的输入(比如关节角读数),\(\mathbf h_t\) 是隐藏状态,\(\hat{\mathbf y}_t\) 是输出,\(\phi\) 通常是 \(\tanh\)。所有时刻共用同一组参数 \(\theta=(W_h,W_x,\mathbf b,W_y,\mathbf b_y)\):这和 CNN 在空间上共用卷积核是同一个想法,只是换到了时间上。注意记号:13.2 节里 \(\mathbf x\) 是状态、\(\mathbf u\) 是输入;机器学习的习惯是 \(\mathbf x\) 为输入、\(\mathbf h\) 为状态,本节沿用后者。把 \(\phi\) 换成恒等映射,RNN 就是 13.2 节的离散线性系统,\(W_h\) 对应 \(A_d\),\(W_x\) 对应 \(B_d\)。

    线性的情形最好理解记忆。在第 5 步给一个脉冲 \(\mathbf x_5\),之后输入为零,则 \(\mathbf h_{5+k}=W_h^k W_x\mathbf x_5\):脉冲的痕迹每一步乘一次 \(W_h\)。把 \(W_h\) 分解到特征向量上,每个分量按特征值 \(\hl{lam}{\lambda}\) 的幂变化:\(|\lambda|<1\) 时按 \(|\lambda|^k\) 衰减,半衰期是 \(\ln\tfrac12/\ln|\lambda|\) 步;\(|\lambda|>1\) 时指数增长;复特征值 \(\lambda=\rho e^{\pm i\omega}\) 让状态每步转过 \(\omega\) 弧度,在平面上画出螺旋。这正是 13.2 节“离散时间稳定 \(\iff\) 特征值在单位圆内”。下图是一个 2 维隐藏状态,\(W_h=\rho R(\omega)\)(旋转乘缩放),它的特征值就是 \(\rho e^{\pm i\omega}\);拖动特征值,看同一个脉冲被记住多久。

    \(\mathbf x_t\) is the input at step \(t\) (say a joint-angle reading), \(\mathbf h_t\) the hidden state, \(\hat{\mathbf y}_t\) the output, and \(\phi\) usually \(\tanh\). Every time step shares the same parameters \(\theta=(W_h,W_x,\mathbf b,W_y,\mathbf b_y)\): the same idea as a CNN sharing its kernel across space, moved to time. A note on notation: in Lesson 13.2 \(\mathbf x\) is the state and \(\mathbf u\) the input; machine learning writes \(\mathbf x\) for the input and \(\mathbf h\) for the state, and this lesson follows that habit. Replace \(\phi\) by the identity and the RNN is the discrete linear system of Lesson 13.2, with \(W_h\) in the role of \(A_d\) and \(W_x\) in the role of \(B_d\).

    Memory is easiest to see in the linear case. Give a pulse \(\mathbf x_5\) at step 5 and zero input afterwards; then \(\mathbf h_{5+k}=W_h^k W_x\mathbf x_5\): the trace of the pulse is multiplied by \(W_h\) once per step. Decompose along the eigenvectors of \(W_h\) and each component evolves as a power of its eigenvalue \(\hl{lam}{\lambda}\): for \(|\lambda|<1\) it decays like \(|\lambda|^k\), with a half-life of \(\ln\tfrac12/\ln|\lambda|\) steps; for \(|\lambda|>1\) it grows exponentially; a complex eigenvalue \(\lambda=\rho e^{\pm i\omega}\) turns the state by \(\omega\) radians per step, tracing a spiral in the plane. This is the "discrete-time stable \(\iff\) eigenvalues inside the unit circle" of Lesson 13.2. Below is a 2-dimensional hidden state with \(W_h=\rho R(\omega)\) (a rotation times a scaling), whose eigenvalues are exactly \(\rho e^{\pm i\omega}\); drag the eigenvalue and see how long the same pulse is remembered.

    FIG 1记忆就是特征值:一个脉冲在 2 维隐藏状态里能留多久Memory is an eigenvalue: how long a pulse survives in a 2-dimensional hidden state
    左:复平面。青色虚线是单位圆,琥珀色实心点是可拖动的特征值 \(\lambda=\rho e^{i\omega}\),空心圈是它的共轭 \(\bar\lambda\)(实矩阵的复特征值总是成对出现)。右:输入与状态随时间的变化,第 5 步有一个大小为 \(A\) 的青色脉冲(只进入 \(h_1\)),琥珀线是 \(h_1\),紫线是 \(h_2\),蓝色虚线是线性情形的包络 \(\pm A\rho^{k}\)。纵轴固定在 ±2.2,超出部分被裁掉,真实的最大值看读数。“tanh”模式把 \(\phi\) 换成 \(\tanh\),其余不变。 Left: the complex plane. The cyan dashed circle is the unit circle, the filled amber dot is the draggable eigenvalue \(\lambda=\rho e^{i\omega}\), the hollow ring its conjugate \(\bar\lambda\) (complex eigenvalues of a real matrix always come in pairs). Right: input and state over time; at step 5 a cyan pulse of size \(A\) enters \(h_1\) only; the amber line is \(h_1\), the purple line \(h_2\), the blue dashed lines the envelope \(\pm A\rho^{k}\) of the linear case. The vertical axis is fixed at ±2.2 and anything beyond is clipped; the readout gives the true maximum. "tanh" mode replaces \(\phi\) by \(\tanh\) and changes nothing else.
    试一试Try this
    • 拖动特征值,让脉冲的半衰期至少 20 步,同时仍然稳定(\(|\lambda|<1\))。读数会告诉你需要 \(|\lambda|\ge0.966\):长记忆意味着特征值紧贴单位圆。Drag the eigenvalue so the pulse's half-life is at least 20 steps while staying stable (\(|\lambda|<1\)). The readout shows that this needs \(|\lambda|\ge0.966\): long memory means eigenvalues hugging the unit circle.
    • 在“线性”模式把 \(|\lambda|\) 拉到 1.05 以上,状态无界增长;再切到“tanh”:状态被限制在 ±1 之内,但它落到一个自激的圆周运动上,不再回到 0,而且换不同的脉冲大小 \(A\),最后转的圈几乎一样大:它已经不再记录输入了。In "linear" mode pull \(|\lambda|\) above 1.05: the state grows without bound. Then switch to "tanh": the state stays within ±1, but it settles on a self-sustained circling motion, never returns to 0, and for different pulse sizes \(A\) the final circle is almost the same size: it no longer records the input.
    核心洞见Key insight

    隐藏状态是网络为自己写的“历史摘要”,它记多久、记成什么形状,由递推矩阵的特征值决定:贴近单位圆才记得久,越过单位圆就失控。后面会看到,同一组特征值也决定了训练时梯度能沿时间传回多远(第 4 节),所以“记得住”和“学得会”是同一个问题的两面。

    The hidden state is a "summary of the history" that the network writes for itself; how long it remembers, and in what shape, is decided by the eigenvalues of the recurrent matrix: close to the unit circle it remembers long, beyond it the state runs away. We will see that the same eigenvalues decide how far gradients travel back in time during training (Section 4), so "able to remember" and "able to learn" are two faces of one problem.

    3动手:现场训练一个 RNN 速度估计器Play: train an RNN velocity estimator live

    任务:一个关节的角度传感器有噪声(标准差 \(\sigma\),单位 rad;比如廉价电位器或从图像估计的角度),以 50 Hz 采样(\(\Delta t=0.02\) s)。我们要从读数序列 \(z_1,z_2,\dots\) 实时估计关节角速度 \(\dot q_t\)。关节的运动是两个随机正弦之和(频率 0.3 到 1.5 Hz,幅值 0.15 到 0.6 rad),每段 80 步(1.6 s)。三种估计器同台比较:

    • 差分:\((z_t-z_{t-1})/\Delta t\)。几乎没有偏差(只滞后半步),但噪声被放大 \(\sqrt2/\Delta t\) 倍,\(\sigma=0.01\) rad 时就是约 0.7 rad/s 的抖动。
    • 卡尔曼滤波(4.8 节):常速度模型 \([q,\dot q]\),加速度当白噪声,过程噪声强度在另一批轨迹上网格搜索调到最好。
    • RNN:12 个 tanh 隐藏单元,输入 \(x_t=2z_t\),输出 \(\hat y_t\approx\dot q_t/3\)(缩放只为让数值在 1 附近)。每步训练抽 8 段新轨迹,损失是前 10 步(0.2 s 的热身)之后的均方误差,用 Adam(学习率 0.01 并逐渐减小,梯度范数裁剪到 1)更新。

    怎么求梯度?把递推按时间展开:80 步的 RNN 就是一个 80 层、每层权重相同的深网络,再用 16.3 节的反向传播从最后一步往回算。这就叫沿时间反向传播(BPTT)。因为每一层是同一个 \(W_h\),它的梯度是各步贡献之和。长序列上常用截断 BPTT:每 \(K\) 步把往回传的梯度切断(状态照样往前传,只是梯度不再往更早传),省内存,也让每次更新更快。下面的 \(K\) 就是它。

    The task: a joint-angle sensor is noisy (standard deviation \(\sigma\), in rad; think of a cheap potentiometer or an angle estimated from images) and sampled at 50 Hz (\(\Delta t=0.02\) s). From the readings \(z_1,z_2,\dots\) we want to estimate the joint velocity \(\dot q_t\) online. The joint moves as a sum of two random sinusoids (0.3 to 1.5 Hz, amplitude 0.15 to 0.6 rad), in clips of 80 steps (1.6 s). Three estimators compete:

    • Finite difference: \((z_t-z_{t-1})/\Delta t\). Almost no bias (it lags by only half a step), but it amplifies the noise by \(\sqrt2/\Delta t\); at \(\sigma=0.01\) rad that is about 0.7 rad/s of jitter.
    • Kalman filter (Lesson 4.8): a constant-velocity model \([q,\dot q]\) with acceleration treated as white noise, its intensity tuned for the best result by grid search on a separate set of trajectories.
    • RNN: 12 tanh hidden units, input \(x_t=2z_t\), output \(\hat y_t\approx\dot q_t/3\) (the scalings only keep the numbers near 1). Each training step draws 8 fresh trajectories; the loss is the mean squared error after the first 10 steps (a 0.2 s warm-up); Adam updates the weights (learning rate 0.01, slowly decreasing; gradient norm clipped at 1).

    How do we get the gradient? Unroll the recurrence in time: an RNN run for 80 steps is an 80-layer deep network whose layers all share the same weights, and the backpropagation of Lesson 16.3 works backwards from the last step. This is backpropagation through time (BPTT). Because every layer is the same \(W_h\), its gradient is the sum of the contributions of all steps. On long sequences one often uses truncated BPTT: every \(K\) steps the backward-flowing gradient is cut (the state still flows forward; only the gradient stops reaching earlier steps), which saves memory and makes each update cheaper. That \(K\) is the one below.

    FIG 2从带噪角度估计角速度:差分、卡尔曼滤波和一个现场训练的 RNNVelocity from noisy angles: finite differences, a Kalman filter, and an RNN trained live
    左上:一段测试轨迹的角速度(rad/s)。琥珀色是真值,青色细线是差分,紫色是卡尔曼滤波,绿色是 RNN;左侧的阴影是不计入误差的 0.2 s 热身。左下:RNN 的 12 个隐藏单元 \(h_t\) 随时间的取值,蓝为正、红为负,颜色越浓绝对值越大。右:32 段固定测试轨迹上的均方根误差(对数坐标)随训练步数的变化,虚线是两个基线。改变 \(\sigma\) 时网络保留,测试集和卡尔曼滤波按新的 \(\sigma\) 重建;改变 \(K\) 会从头训练。所有随机数都有固定种子,所以同样的操作给出同样的曲线。 Top left: the joint velocity (rad/s) on one test trajectory. Amber is the truth, the thin cyan line the finite difference, purple the Kalman filter, green the RNN; the shaded strip on the left is the 0.2 s warm-up, which is not scored. Bottom left: the 12 hidden units \(h_t\) of the RNN over time, blue positive, red negative, stronger colour for larger magnitude. Right: the RMS error on 32 fixed test trajectories (log scale) against training steps; the dashed lines are the two baselines. Changing \(\sigma\) keeps the network and rebuilds the test set and the Kalman filter for the new \(\sigma\); changing \(K\) restarts training. Every random number is seeded, so the same actions give the same curves.
    • 保持默认设置按“训练”:约 150 步后 RNN 超过差分,约 300 步后超过卡尔曼滤波(0.45 rad/s),1000 步左右稳定在约 0.27 rad/s。Keep the defaults and press "Train": after about 150 steps the RNN beats the finite difference, after about 300 the Kalman filter (0.45 rad/s), and by about 1000 steps it settles near 0.27 rad/s.
    • 把截断长度设为 \(K=1\)(会从头训练),训练至少 500 步:误差在 0.6 到 0.8 rad/s 附近徘徊,始终比不上卡尔曼滤波。Set the truncation to \(K=1\) (this restarts training) and train for at least 500 steps: the error hovers around 0.6 to 0.8 rad/s and never gets below the Kalman filter.
    有意思的细节Things worth noticing

    (1) RNN 为什么能赢卡尔曼滤波?不是因为卡尔曼滤波“错了”:在模型正确的线性高斯系统上它就是最优的。这里它用的是通用的常速度模型,把加速度当成白噪声,而这些轨迹其实是平滑的低频正弦。RNN 从数据里学到了“这类轨迹长什么样”的先验,于是能平滑得更狠而不滞后。反过来说,它也只懂训练数据里那类运动:遇到别的运动就是 16.2 节讲的分布偏移。 (2) \(K=1\) 为什么不行?它照样把状态往前传,也照样用上一步的状态,但梯度从不告诉它“现在存下什么,几步之后才有用”:它学会了利用状态,却学不会往状态里写什么。截断长度要覆盖任务需要的记忆跨度。 (3) 换噪声:在 \(\sigma=0.01\) 训练 2000 步之后把 \(\sigma\) 拉到 0.03,网络不变,误差立刻是 0.62 rad/s,已经好于按新噪声重新调好的卡尔曼滤波(0.76)和差分(2.09);继续训练 600 步降到约 0.48。

    (1) Why can the RNN beat the Kalman filter? Not because the Kalman filter is "wrong": on a linear-Gaussian system with the right model it is optimal. Here it uses a generic constant-velocity model that treats acceleration as white noise, while these trajectories are smooth, low-frequency sinusoids. The RNN learned a prior for "what such trajectories look like" from data, so it can smooth harder without lagging. The flip side is that it only knows the kind of motion it was trained on: other motions are the distribution shift of Lesson 16.2. (2) Why does \(K=1\) fail? It still carries the state forward and still uses the previous state, but the gradient never tells it "store this now, it will be useful a few steps later": it learns to use its state but not what to write into it. The truncation length has to cover the memory span the task needs. (3) Changing the noise: after 2000 training steps at \(\sigma=0.01\), move \(\sigma\) to 0.03; with the network unchanged the error is immediately 0.62 rad/s, already better than the Kalman filter retuned for the new noise (0.76) and the finite difference (2.09); another 600 steps of training bring it to about 0.48.

    4另外几个视角:梯度、门、线性状态空间层与选择性More views: gradients, gates, linear state-space layers and selectivity

    梯度沿时间消失或爆炸Gradients vanish or explode through time

    BPTT 里,第 \(T\) 步的误差要影响第 \(T-k\) 步的参数,必须穿过 \(k\) 个雅可比的乘积 \(\partial\mathbf h_T/\partial\mathbf h_{T-k}=J_T J_{T-1}\cdots J_{T-k+1}\),每个 \(J_t=\operatorname{diag}(\phi'(\mathbf a_t))\,W_h\)。16.3 节在深的前馈网络里已经见过这种乘积;时间上的版本更糟,因为每一层都是同一个 \(W_h\),乘积就像矩阵幂:典型的增益略小于 1,几十步后就小到没有意义(消失);略大于 1,就大到数值溢出(爆炸)。下图对随机初始化的网络直接把这个乘积算出来(隐藏维数 16,输入是随机噪声),画它的最大奇异值随 \(k\) 的变化。三种单元:普通 tanh RNN、GRU、LSTM(门的定义见下一小节和第 5 节)。“增益” \(g\) 是循环权重的尺度(谱半径约为 \(g\)),“门偏置” \(b\) 让门偏向“保留”:LSTM 的遗忘门偏置取 \(+b\),GRU 的更新门偏置取 \(-b\)。

    In BPTT, for the error at step \(T\) to influence the parameters at step \(T-k\), it must pass through a product of \(k\) Jacobians \(\partial\mathbf h_T/\partial\mathbf h_{T-k}=J_T J_{T-1}\cdots J_{T-k+1}\), each \(J_t=\operatorname{diag}(\phi'(\mathbf a_t))\,W_h\). Lesson 16.3 met such products in deep feed-forward nets; the version in time is worse, because every layer is the same \(W_h\), so the product behaves like a matrix power: a typical gain a little below 1 makes it meaninglessly small after a few dozen steps (vanishing); a little above 1 makes it overflow (exploding). The figure computes this product directly for randomly initialized networks (hidden size 16, driven by random noise) and plots its largest singular value against \(k\). Three cells: a plain tanh RNN, a GRU and an LSTM (their gates are defined in the next subsection and in Section 5). The "gain" \(g\) is the scale of the recurrent weights (spectral radius about \(g\)); the "gate bias" \(b\) tilts the gates towards "keep": the LSTM forget gate gets bias \(+b\), the GRU update gate bias \(-b\).

    FIG 3梯度穿过 \(k\) 步之后还剩多少:\(\|\partial\mathbf h_T/\partial\mathbf h_{T-k}\|\)How much gradient survives \(k\) steps: \(\|\partial\mathbf h_T/\partial\mathbf h_{T-k}\|\)
    纵轴是对数刻度的雅可比乘积最大奇异值,横轴是回传的步数 \(k\)。红:tanh RNN;绿:GRU;蓝:LSTM(状态是 \([\mathbf c;\mathbf h]\),32 维)。青色带是 \(10^{-2}\) 到 \(10^{2}\),梯度在其中才算“有用”。每个雅可比用中心差分逐列算出,乘积的范数用幂迭代求,所以这是真实网络的真实数值,不是公式里的上界。低于 \(10^{-24}\) 的部分画在下边缘之外。 The vertical axis is the largest singular value of the Jacobian product on a log scale; the horizontal axis is the number of steps \(k\) travelled back. Red: tanh RNN; green: GRU; blue: LSTM (its state is \([\mathbf c;\mathbf h]\), 32-dimensional). The cyan band spans \(10^{-2}\) to \(10^{2}\), where a gradient is still "useful". Every Jacobian is computed column by column with central differences and the norm of the product by power iteration, so these are the true numbers of real networks, not the upper bound of a formula. Anything below \(10^{-24}\) is drawn past the lower edge.
    • 把增益 \(g\) 推到 2.5 左右:RNN 的梯度不再衰减,50 步后反而放大了 10 倍以上(爆炸)。Push the gain \(g\) to about 2.5: the RNN gradient stops decaying and is amplified more than tenfold after 50 steps (exploding).
    • 把增益放回 1 附近,把门偏置调到 3 或更高:100 步后 LSTM 和 GRU 的梯度都还在 \(10^{-1.5}\) 以上,而同样增益的 RNN 已低于 \(10^{-10}\)。Return the gain to about 1 and set the gate bias to 3 or more: after 100 steps both the LSTM and the GRU gradients are still above \(10^{-1.5}\), while the RNN at the same gain is below \(10^{-10}\).

    爆炸好办:训练时把梯度范数裁剪到一个上限(FIG 2 就裁剪到 1),方向不变只缩短步长(Pascanu 等,2013)。消失难办得多:梯度小到不出错也不报警,网络只是学不会长程依赖。门控单元给出的解法是:给记忆开一条加法的通路。

    Explosion is easy to handle: clip the gradient norm to a ceiling during training (FIG 2 clips at 1), which keeps the direction and only shortens the step (Pascanu et al., 2013). Vanishing is much harder: a tiny gradient raises no error and no alarm; the network simply never learns the long-range dependency. Gated cells answer it by giving memory an additive path.

    门:LSTM 与 GRUGates: LSTM and GRU

    LSTM(Hochreiter 与 Schmidhuber,1997;遗忘门由 Gers 等在 2000 年加入)另设一个“细胞状态” \(\mathbf c_t\),更新方式是 \(\mathbf c_t=\mathbf f_t\odot\mathbf c_{t-1}+\mathbf i_t\odot\mathbf g_t\):遗忘门 \(\mathbf f_t\) 决定保留多少旧内容,输入门 \(\mathbf i_t\) 决定写入多少新内容,门都是 0 到 1 之间的 sigmoid,由当前输入和上一步输出算出。沿 \(\mathbf c\) 这条直通路径,\(\partial\mathbf c_t/\partial\mathbf c_{t-1}=\operatorname{diag}(\mathbf f_t)\):没有矩阵相乘、没有 tanh 的压缩,只要 \(\mathbf f_t\approx1\),梯度就几乎原样传回去。GRU(Cho 等,2014)更省:只有一个状态,用更新门 \(\hl{gate}{\mathbf z_t}\) 在“保留旧状态”和“换成候选值”之间插值,\(\mathbf h_t=(1-\mathbf z_t)\odot\mathbf h_{t-1}+\mathbf z_t\odot\tilde{\mathbf h}_t\),\(\mathbf z_t\approx0\) 就是原样保留。

    下面用一个需要长记忆的任务对比普通 RNN 和 GRU。机器人在 \(t=0\) 看到一个提示(比如“放进左边还是右边的箱子”,编码为 \(+1\) 或 \(-1\)),接下来 \(D\) 步同一个通道上只有干扰噪声(标准差 1,和提示一样大),最后一步来一个“执行”信号,网络要输出当初的提示。两个网络都是 8 个隐藏单元,用同样的种子、同样的数据、同样的优化器同时训练。GRU 的更新门偏置初始化为 \(-3\)(\(z\approx0.05\),每步保留 95%),这和给 LSTM 的遗忘门加正偏置是同一个技巧。

    The LSTM (Hochreiter and Schmidhuber, 1997; the forget gate was added by Gers et al. in 2000) keeps a separate "cell state" \(\mathbf c_t\) updated as \(\mathbf c_t=\mathbf f_t\odot\mathbf c_{t-1}+\mathbf i_t\odot\mathbf g_t\): the forget gate \(\mathbf f_t\) decides how much of the old content to keep, the input gate \(\mathbf i_t\) how much new content to write; the gates are sigmoids between 0 and 1 computed from the current input and the previous output. Along the direct path through \(\mathbf c\), \(\partial\mathbf c_t/\partial\mathbf c_{t-1}=\operatorname{diag}(\mathbf f_t)\): no matrix product and no tanh squashing, so as long as \(\mathbf f_t\approx1\) the gradient travels back almost unchanged. The GRU (Cho et al., 2014) is leaner: a single state, and an update gate \(\hl{gate}{\mathbf z_t}\) interpolates between "keep the old state" and "take the candidate", \(\mathbf h_t=(1-\mathbf z_t)\odot\mathbf h_{t-1}+\mathbf z_t\odot\tilde{\mathbf h}_t\); \(\mathbf z_t\approx0\) means keep as is.

    Below, a task that needs long memory compares a plain RNN with a GRU. At \(t=0\) the robot sees a cue (say "drop it in the left or the right bin", coded \(+1\) or \(-1\)); for the next \(D\) steps the same channel carries only distractor noise (standard deviation 1, as large as the cue); at the last step a "go" signal arrives and the network must output the original cue. Both networks have 8 hidden units and are trained side by side with the same seed, the same data and the same optimizer. The GRU's update-gate bias is initialized to \(-3\) (\(z\approx0.05\), keeping 95% per step), the same trick as giving an LSTM forget gate a positive bias.

    FIG 4延迟回忆:普通 RNN 对 GRUDelayed recall: plain RNN versus GRU
    左,从上到下:一条测试序列的输入通道(琥珀色竖条是 \(t=0\) 的提示,青色是干扰,最右端的标记是“执行”信号);RNN 的 8 个隐藏单元;GRU 的 8 个隐藏单元(蓝正 红负);GRU 的更新门 \(z\)(越接近琥珀色越接近 1,即“覆盖”;越接近底色越接近 0,即“保留”)。右:200 条测试序列上的正确率随训练步数的变化,红为 RNN,绿为 GRU,虚线是 50%(瞎猜)与 95%。训练最多 2000 步后自动停止。 Left, top to bottom: the input channel of one test sequence (the amber bar is the cue at \(t=0\), cyan the distractors, the marker at the right end the "go" signal); the 8 hidden units of the RNN; the 8 hidden units of the GRU (blue positive, red negative); the GRU update gate \(z\) (closer to amber means closer to 1, "overwrite"; closer to the background means closer to 0, "keep"). Right: accuracy on 200 test sequences against training steps, red for the RNN, green for the GRU; the dashed lines are 50% (guessing) and 95%. Training stops by itself after at most 2000 steps.
    • 选延迟 \(D=10\) 并训练:两个网络都在几百步内达到 95% 以上,短记忆对普通 RNN 不成问题。Choose delay \(D=10\) and train: both networks pass 95% within a few hundred steps; short memory is no problem for a plain RNN.
    • 选 \(D=60\)(更新门偏置保持 \(-3\))并训练:GRU 约 300 步就超过 95%,RNN 一直在瞎猜附近(低于 70%)。按“换种子”多试几次:在种子 1 到 10 里,RNN 碰巧学会了 3 次(一次在 300 步时,另两次要 1000 步以上),GRU 每次都在 300 到 500 步内学会。Choose \(D=60\) (update-gate bias left at \(-3\)) and train: the GRU passes 95% after about 300 steps while the RNN stays near guessing (below 70%). Press "New seed" a few times: over seeds 1 to 10 the RNN got lucky 3 times (once at 300 steps, the other two only after 1000 or more), while the GRU learned every time within 300 to 500 steps.

    还可以把 GRU 的门偏置改成 0 再训练 \(D=30\) 或 \(D=60\):默认种子下 2000 步内 GRU 也学不会。门本身只提供了“可以保留”的通路,初始化得让网络一开始就倾向于保留,梯度才过得去:结构和初始化缺一不可。

    You can also set the GRU's gate bias to 0 and train \(D=30\) or \(D=60\): with the default seed the GRU fails too within 2000 steps. The gate only provides a path that can keep; the initialization must make the network lean towards keeping from the start, or the gradient never gets through. Structure and initialization both matter.

    线性状态空间层:卷积着训练,递推着推理Linear state-space layers: train as a convolution, run as a recurrence

    另一条路是反过来:把递推里的非线性去掉,非线性放到层与层之间。一层就是一个连续时间线性系统 \(\dot{\mathbf h}=A\mathbf h+B x,\ y=C\mathbf h\)(每个输入通道一份),按步长 \(\Delta\) 用 13.2 节的零阶保持离散化:\(\bar A=e^{\Delta A}\),\(\bar B=A^{-1}(e^{\Delta A}-I)B\),于是 \(\mathbf h_t=\bar A\mathbf h_{t-1}+\bar Bx_t\)。线性时不变带来一个大礼:把递推展开,

    The other route goes the opposite way: remove the nonlinearity from the recurrence and put it between layers instead. A layer is then a continuous-time linear system \(\dot{\mathbf h}=A\mathbf h+B x,\ y=C\mathbf h\) (one copy per input channel), discretized with step \(\Delta\) by the zero-order hold of Lesson 13.2: \(\bar A=e^{\Delta A}\), \(\bar B=A^{-1}(e^{\Delta A}-I)B\), so that \(\mathbf h_t=\bar A\mathbf h_{t-1}+\bar Bx_t\). Being linear and time-invariant brings a big gift: unroll the recurrence and

    $$ y_t=\sum_{k=0}^{t} C\bar A^{k}\bar B\,x_{t-k}=(\hl{kernel}{\bar{\mathbf K}}*x)_t,\qquad \bar{\mathbf K}=\big(C\bar B,\ C\bar A\bar B,\ C\bar A^2\bar B,\ \dots\big). $$

    整层就是输入与一个固定卷积核 \(\bar{\mathbf K}\) 的卷积。训练时整段序列已知,先算出卷积核,再用 FFT 一次卷完,\(O(L\log L)\) 且在时间上完全并行;推理时又可以退回递推,每步只做 \(O(N)\) 的运算、只存 \(N\) 维状态。S4(Gu、Goel 与 Ré,2022)用 HiPPO 理论设计 \(A\) 的结构与初值,让状态能记很长的历史;之后的 S4D 把 \(A\) 取成对角复矩阵,例如 S4D-Lin 的 \(A_n=-\tfrac12+i\pi n\),每个模态就是一个独立的复数标量递推。步长 \(\Delta\) 是可学习的“时间尺度”:卷积核的长度与 \(1/\Delta\) 成正比。

    递推本身也能并行。\(h_t=a_th_{t-1}+b_t\) 是仿射映射的复合,而复合满足结合律:\((a_2,b_2)\hl{scan}{\bullet}(a_1,b_1)=(a_2a_1,\ a_2b_1+b_2)\)。所以所有前缀 \(h_1,\dots,h_L\) 可以用并行前缀扫描(parallel scan)在 \(\lceil\log_2L\rceil\) 轮里算完,每一轮所有位置同时计算。扫描的另一个好处是:它不要求 \(a_t\) 与 \(t\) 无关;卷积则要求。这一点对下一小节至关重要。

    The whole layer is a convolution of the input with one fixed kernel \(\bar{\mathbf K}\). During training the whole sequence is known, so compute the kernel and convolve in one go with an FFT, \(O(L\log L)\) and fully parallel in time; at inference fall back to the recurrence, with \(O(N)\) work and an \(N\)-dimensional state per step. S4 (Gu, Goel and Ré, 2022) uses HiPPO theory to design the structure and initialization of \(A\) so that the state can remember a long history; the later S4D takes \(A\) diagonal and complex, for instance S4D-Lin with \(A_n=-\tfrac12+i\pi n\), so each mode is an independent complex scalar recurrence. The step \(\Delta\) is a learnable "timescale": the length of the kernel is proportional to \(1/\Delta\).

    The recurrence itself can be parallelized too. \(h_t=a_th_{t-1}+b_t\) is a composition of affine maps, and composition is associative: \((a_2,b_2)\hl{scan}{\bullet}(a_1,b_1)=(a_2a_1,\ a_2b_1+b_2)\). So all prefixes \(h_1,\dots,h_L\) can be computed by a parallel prefix scan in \(\lceil\log_2L\rceil\) rounds, with all positions computed simultaneously in each round. The scan has another advantage: it does not require \(a_t\) to be independent of \(t\), whereas the convolution does. That is crucial for the next subsection.

    FIG 5一个对角状态空间层的三种算法:递推、卷积、并行扫描Three ways to compute one diagonal state-space layer: recurrence, convolution, parallel scan
    左上:卷积核 \(\bar K_k\)(蓝)。左下:输入(青色,一段 200 步的关节力矩指令:随机阶跃加噪声)和三种方法算出的输出:递推(琥珀色粗线)、卷积(紫色虚线)、并行扫描(绿点)。右:长度 16 的 Hillis–Steele 扫描。每一行是一轮,第 \(\ell\) 轮把位置 \(t\) 与位置 \(t-2^{\ell-1}\) 的结果用 \(\bullet\) 合并(琥珀色箭头);绿色实心点表示该位置的前缀已经完整(等于真正的 \(h_t\))。“Δ 随输入变化”时,每一步的步长是 \(\Delta_t=\Delta\,(0.2+1.8\,\sigma(3x_t))\),系统不再时不变,卷积只能用平均步长去近似。 Top left: the kernel \(\bar K_k\) (blue). Bottom left: the input (cyan, a 200-step joint-torque command: random steps plus noise) and the output computed three ways: recurrence (thick amber line), convolution (purple dashed), parallel scan (green dots). Right: a Hillis–Steele scan of length 16. Each row is one round; round \(\ell\) combines position \(t\) with position \(t-2^{\ell-1}\) by \(\bullet\) (amber arrows); a filled green dot means that position's prefix is complete (equals the true \(h_t\)). With "Δ depends on the input", each step uses \(\Delta_t=\Delta\,(0.2+1.8\,\sigma(3x_t))\): the system is no longer time-invariant, and the convolution can only approximate it with the average step.
    • 按“下一轮扫描”走完全部 4 轮:16 个前缀全部完整,读数显示它们与递推算出的状态之差在 \(10^{-12}\) 以下。递推要 16 个先后相继的步骤,扫描只要 4 轮。Press "Next scan round" through all 4 rounds: all 16 prefixes are complete, and the readout shows they differ from the recurrently computed states by less than \(10^{-12}\). The recurrence needs 16 strictly sequential steps; the scan needs 4 rounds.
    • 切到“Δ 随输入变化”:卷积的误差变得和输出本身一样大(读数里大于 0.1),扫描的误差仍是舍入误差级别。Switch to "Δ depends on the input": the convolution's error becomes as large as the output itself (above 0.1 in the readout), while the scan's error stays at round-off level.

    拖动 \(\Delta\) 看卷积核:S4D-Lin、8 个模态时,\(\Delta=0.05\) 的核在约 190 步后衰减到峰值的 1% 以下,\(\Delta=0.01\) 时约 960 步:\(\Delta\) 缩小 5 倍,记忆拉长 5 倍。直观地说,\(\Delta\) 决定了“一步”在连续时间里有多长,模态衰减率 \(\operatorname{Re}A_n=-\tfrac12\) 是按连续时间计的。

    Drag \(\Delta\) and watch the kernel: with S4D-Lin and 8 modes, at \(\Delta=0.05\) the kernel falls below 1% of its peak after about 190 steps, at \(\Delta=0.01\) after about 960: shrink \(\Delta\) fivefold and the memory grows fivefold. Intuitively, \(\Delta\) is how long "one step" lasts in continuous time, while the decay rate \(\operatorname{Re}A_n=-\tfrac12\) is measured in continuous time.

    选择性:让步长取决于输入(Mamba)Selectivity: let the step depend on the input (Mamba)

    线性时不变的层有个根本局限:它对每个输入一视同仁,同一个卷积核作用在所有位置上,没办法“这一帧重要就记住,那一帧是垃圾就跳过”。Mamba(Gu 与 Dao,2023)的做法是让 \(\Delta,B,C\) 都成为当前输入的函数,例如 \(\hl{delta}{\Delta_t}=\operatorname{softplus}(\mathbf w^\top\mathbf x_t+\beta)\)。取最简单的标量 \(A=-1\)、\(B=1\),零阶保持给出

    A linear time-invariant layer has a fundamental limitation: it treats every input alike, applying the same kernel at every position, with no way to say "this frame matters, remember it; that one is junk, skip it". Mamba (Gu and Dao, 2023) makes \(\Delta,B,C\) functions of the current input, e.g. \(\hl{delta}{\Delta_t}=\operatorname{softplus}(\mathbf w^\top\mathbf x_t+\beta)\). Take the simplest scalar case \(A=-1\), \(B=1\); the zero-order hold gives

    $$ h_t=e^{-\Delta_t}\,h_{t-1}+\big(1-e^{-\Delta_t}\big)\,x_t . $$

    \(\Delta_t\to0\) 时 \(h_t\approx h_{t-1}\):保留旧状态,忽略这一步的输入;\(\Delta_t\gg1\) 时 \(h_t\approx x_t\):用这一步的输入覆盖状态。这就是 GRU 的更新门 \(z_t=1-e^{-\Delta_t}\)!区别在于:门只由输入决定、不依赖 \(h_{t-1}\),状态更新仍然是线性的,所以依旧可以并行扫描(但不能再用卷积)。下面的任务需要这种能力:一串传感器读数 \(v_t\) 里只有带标记 \(m_t=1\) 的才有效(比如只有在足端着地时力传感器的读数才有意义,或者在夹爪闭合那一刻要锁存一个读数),目标是输出最近一次被标记的读数。一个是 4 个模态、所有参数都可学的线性时不变层;一个是只有 1 个模态、5 个参数的选择性层。

    For \(\Delta_t\to0\), \(h_t\approx h_{t-1}\): keep the old state and ignore this step's input; for \(\Delta_t\gg1\), \(h_t\approx x_t\): overwrite the state with this step's input. That is the update gate of a GRU, \(z_t=1-e^{-\Delta_t}\)! The differences: the gate depends only on the input, not on \(h_{t-1}\), and the state update stays linear, so it can still be computed with a parallel scan (though no longer as a convolution). The task below needs exactly this ability: in a stream of sensor readings \(v_t\), only those flagged \(m_t=1\) are valid (say, a force reading means something only while the foot is on the ground, or a reading must be latched at the moment the gripper closes), and the target is the most recently flagged reading. One model is a linear time-invariant layer with 4 modes and every parameter learnable; the other a selective layer with a single mode and 5 parameters.

    FIG 6采样保持:时不变的 SSM 做不到,选择性 SSM 一学就会Sample and hold: impossible for a time-invariant SSM, easy for a selective one
    左上:一条 64 步的测试序列。青色点是读数 \(v_t\),琥珀色竖虚线标出被标记的步,琥珀色阶梯是目标,紫色是时不变层的输出,绿色是选择性层的输出。左下:选择性层每一步的“写入量” \(1-e^{-\Delta_t}\)(蓝色条,0 到 1)。右:64 条测试序列上的均方误差(对数坐标),虚线是“永远输出 0”的误差。“冻结 Δ”把训练好的选择性层的 \(\Delta_t\) 换成它在这条序列上的平均值:参数一个不变,只是去掉了对输入的依赖。 Top left: one 64-step test sequence. Cyan dots are the readings \(v_t\), dashed amber verticals mark the flagged steps, the amber staircase is the target, purple the output of the time-invariant layer, green that of the selective layer. Bottom left: the selective layer's "write amount" \(1-e^{-\Delta_t}\) at every step (blue bars, 0 to 1). Right: the mean squared error on 64 test sequences (log scale); the dashed line is the error of "always output 0". "Freeze Δ" replaces the trained selective layer's \(\Delta_t\) by its average over the sequence: not a single parameter changes, only the dependence on the input is removed.
    • 按“训练”:时不变层很快卡在约 0.25(只比永远输出 0 好 8% 左右),选择性层约 400 步后误差低于它的 1%。Press "Train": the time-invariant layer quickly gets stuck near 0.25 (only about 8% better than always outputting 0), while after about 400 steps the selective layer's error is below 1% of it.
    • 训练好之后(选择性层误差低于 0.01)切到“冻结 Δ”:误差跳回 0.2 以上,和时不变层一样差。本领全在“步长随输入变化”这一点上。Once trained (selective error below 0.01), switch to "Freeze Δ": the error jumps back above 0.2, as bad as the time-invariant layer. Its whole skill lies in the step depending on the input.
    一个递推,几种看法One recurrence, several views

    卡尔曼滤波:人写模型的线性 RNN,稳态时 \(\hat{\mathbf x}_k=(I-KH)F\hat{\mathbf x}_{k-1}+K\mathbf z_k\)(第 5 节)。 RNN / LSTM / GRU:学出来的非线性递推,门让记忆有一条加法通路。 S4 类状态空间层:学出来的线性时不变递推,可以当卷积训练、当滤波器运行。 Mamba:线性递推加上只依赖输入的门,用扫描训练,相当于“不看自己状态的 GRU”。 Transformer(17.3 节):不压缩成状态,每一步直接回看整段历史,换来的是随历史增长的计算与内存。

    Kalman filter: a linear RNN with a hand-written model; at steady state \(\hat{\mathbf x}_k=(I-KH)F\hat{\mathbf x}_{k-1}+K\mathbf z_k\) (Section 5). RNN / LSTM / GRU: learned nonlinear recurrences, with gates giving memory an additive path. S4-style state-space layers: learned linear time-invariant recurrences, trained as a convolution and run as a filter. Mamba: a linear recurrence with gates that depend only on the input, trained with a scan; a "GRU that does not look at its own state". Transformer (Lesson 17.3): no compression into a state; every step looks back at the whole history directly, at the price of computation and memory that grow with the history.

    5再看数学The math

    提示:把鼠标悬停在公式中带底色的符号上,图中对应的元素会被高亮(FIG 1 的特征值与状态曲线、FIG 2 的隐藏状态、FIG 3 的梯度曲线、FIG 4 的更新门、FIG 5 的卷积核与扫描箭头、FIG 6 的写入量)。Tip: hover the highlighted symbols in the formulas; the matching elements in the figures light up (FIG 1's eigenvalue and state curves, FIG 2's hidden states, FIG 3's gradient curves, FIG 4's update gate, FIG 5's kernel and scan arrows, FIG 6's write amounts).

    沿时间反向传播Backpropagation through time

    记预激活 \(\mathbf a_t=W_h\mathbf h_{t-1}+W_x\mathbf x_t+\mathbf b\),\(\mathbf h_t=\phi(\mathbf a_t)\),总损失 \(L=\sum_t\ell_t(\hat{\mathbf y}_t,\mathbf y_t)\)。令 \(\bar{\mathbf g}_t=\partial L/\partial\mathbf h_t\) 为对 \(\mathbf h_t\) 的全导数(既经过本步输出,也经过所有未来步)。链式法则给出从后往前的递推:

    Write the pre-activation \(\mathbf a_t=W_h\mathbf h_{t-1}+W_x\mathbf x_t+\mathbf b\), \(\mathbf h_t=\phi(\mathbf a_t)\), and the total loss \(L=\sum_t\ell_t(\hat{\mathbf y}_t,\mathbf y_t)\). Let \(\bar{\mathbf g}_t=\partial L/\partial\mathbf h_t\) be the total derivative with respect to \(\mathbf h_t\) (through this step's output and through all future steps). The chain rule gives a recursion that runs backwards:

    $$ \bar{\mathbf g}_t=W_y^\top\frac{\partial\ell_t}{\partial\hat{\mathbf y}_t}+W_h^\top\boldsymbol\delta_{t+1},\qquad \boldsymbol\delta_t=\phi'(\mathbf a_t)\odot\bar{\mathbf g}_t,\qquad \frac{\partial L}{\partial W_h}=\sum_t\boldsymbol\delta_t\,\mathbf h_{t-1}^\top,\quad \frac{\partial L}{\partial W_x}=\sum_t\boldsymbol\delta_t\,\mathbf x_t^\top,\quad \frac{\partial L}{\partial\mathbf b}=\sum_t\boldsymbol\delta_t $$

    递推从 \(\boldsymbol\delta_{T+1}=\mathbf 0\) 开始。这就是 16.3 节反向传播在展开图上的样子:前向时要存下全部 \(\mathbf h_t\)(内存 \(O(TH)\)),反向的计算量是前向的一个小倍数。截断 BPTT 只改一处:若 \(t+1\) 是一个长度为 \(K\) 的块的起点,就把 \(W_h^\top\boldsymbol\delta_{t+1}\) 这一项置零。FIG 2 的训练代码就是这几行,页面里的实现用中心差分做过梯度检查(误差小于 \(10^{-8}\))。

    The recursion starts from \(\boldsymbol\delta_{T+1}=\mathbf 0\). This is the backpropagation of Lesson 16.3 on the unrolled graph: the forward pass must store every \(\mathbf h_t\) (memory \(O(TH)\)), and the backward pass costs a small multiple of the forward one. Truncated BPTT changes one thing: if \(t+1\) starts a block of length \(K\), the term \(W_h^\top\boldsymbol\delta_{t+1}\) is set to zero. FIG 2's training code is exactly these lines; the implementation in the page was gradient-checked against central differences (agreement better than \(10^{-8}\)).

    为什么会消失或爆炸Why gradients vanish or explode

    把递推展开,第 \(T\) 步对第 \(t\) 步状态的敏感度是

    Unrolling the recursion, the sensitivity of step \(T\) to the state at step \(t\) is

    $$ \hl{grad}{\frac{\partial\mathbf h_T}{\partial\mathbf h_t}=\prod_{s=t+1}^{T}\operatorname{diag}\big(\phi'(\mathbf a_s)\big)\,W_h},\qquad \Big\|\frac{\partial\mathbf h_T}{\partial\mathbf h_t}\Big\|_2\le\big(\gamma\,\sigma_{\max}(W_h)\big)^{T-t},\quad \gamma=\sup|\phi'| . $$

    tanh 的 \(\gamma=1\)。所以 \(W_h\) 的最大奇异值小于 1 时梯度必然按指数消失;反过来,最大奇异值大于 \(1/\gamma\) 是爆炸的必要条件(Pascanu 等,2013)。实际网络还要乘上 \(\phi'(\mathbf a_s)\le1\):输入越大、tanh 越饱和,有效增益越小,所以 FIG 3 里 \(g=1\) 时 RNN 仍在消失,要到 \(g\approx1.8\) 左右才不再衰减,\(g\approx2\) 以上才开始爆炸。爆炸用梯度裁剪 \(\mathbf g\leftarrow\mathbf g\cdot\min(1,c/\|\mathbf g\|)\) 处理;消失要靠结构(门、线性递推)和初始化。

    For tanh, \(\gamma=1\). So when the largest singular value of \(W_h\) is below 1, the gradient must vanish exponentially; conversely, a largest singular value above \(1/\gamma\) is a necessary condition for explosion (Pascanu et al., 2013). A real network also multiplies by \(\phi'(\mathbf a_s)\le1\): the larger the inputs and the more saturated the tanh, the smaller the effective gain, which is why in FIG 3 the RNN still vanishes at \(g=1\), stops decaying only around \(g\approx1.8\), and starts exploding only above \(g\approx2\). Explosion is handled by gradient clipping \(\mathbf g\leftarrow\mathbf g\cdot\min(1,c/\|\mathbf g\|)\); vanishing needs structure (gates, linear recurrences) and initialization.

    LSTM 与 GRU 的方程The LSTM and GRU equations

    LSTM(四个门与候选值都由 \(\mathbf x_t\) 和 \(\mathbf h_{t-1}\) 算出):

    The LSTM (all gates and the candidate are computed from \(\mathbf x_t\) and \(\mathbf h_{t-1}\)):

    $$ \begin{aligned} &\mathbf f_t=\sigma(W_f\mathbf x_t+U_f\mathbf h_{t-1}+\mathbf b_f),\quad \mathbf i_t=\sigma(W_i\mathbf x_t+U_i\mathbf h_{t-1}+\mathbf b_i),\quad \mathbf o_t=\sigma(W_o\mathbf x_t+U_o\mathbf h_{t-1}+\mathbf b_o),\\ &\mathbf g_t=\tanh(W_g\mathbf x_t+U_g\mathbf h_{t-1}+\mathbf b_g),\qquad \mathbf c_t=\mathbf f_t\odot\mathbf c_{t-1}+\mathbf i_t\odot\mathbf g_t,\qquad \mathbf h_t=\mathbf o_t\odot\tanh(\mathbf c_t). \end{aligned} $$

    GRU(更新门 \(\mathbf z_t\)、重置门 \(\mathbf r_t\)、候选值 \(\tilde{\mathbf h}_t\)):

    The GRU (update gate \(\mathbf z_t\), reset gate \(\mathbf r_t\), candidate \(\tilde{\mathbf h}_t\)):

    $$ \begin{aligned} &\hl{gate}{\mathbf z_t}=\sigma(W_z\mathbf x_t+U_z\mathbf h_{t-1}+\mathbf b_z),\quad \mathbf r_t=\sigma(W_r\mathbf x_t+U_r\mathbf h_{t-1}+\mathbf b_r),\\ &\tilde{\mathbf h}_t=\tanh\big(W_n\mathbf x_t+U_n(\mathbf r_t\odot\mathbf h_{t-1})+\mathbf b_n\big),\qquad \mathbf h_t=(1-\mathbf z_t)\odot\mathbf h_{t-1}+\mathbf z_t\odot\tilde{\mathbf h}_t . \end{aligned} $$

    LSTM 沿细胞状态的直通雅可比是 \(\partial\mathbf c_t/\partial\mathbf c_{t-1}=\operatorname{diag}(\mathbf f_t)\),GRU 的雅可比里有一项 \(\operatorname{diag}(1-\mathbf z_t)\),再加上经过门和候选值的其余项;门偏向“保留”时,这一项接近单位阵,乘很多次也不衰减。所以常把 LSTM 的 \(\mathbf b_f\) 初始化为 1 或更大(Jozefowicz 等,2015 推荐 1),GRU 的 \(\mathbf b_z\) 取负值(FIG 4 取 \(-3\))。两点约定上的差别要留意:PyTorch 的 GRU 写成 \(\mathbf h_t=(1-\mathbf z_t)\odot\tilde{\mathbf h}_t+\mathbf z_t\odot\mathbf h_{t-1}\),它的 \(\mathbf z\) 是这里的 \(1-\mathbf z\);它还把 \(\mathbf r_t\) 乘在 \(U_n\mathbf h_{t-1}\) 之后而不是之前,是一个小变体。

    The LSTM's direct Jacobian along the cell state is \(\partial\mathbf c_t/\partial\mathbf c_{t-1}=\operatorname{diag}(\mathbf f_t)\); the GRU's Jacobian contains the term \(\operatorname{diag}(1-\mathbf z_t)\) plus the remaining terms through the gates and the candidate. When the gates lean towards "keep", that term is close to the identity and survives many multiplications. Hence the habit of initializing the LSTM's \(\mathbf b_f\) to 1 or more (Jozefowicz et al., 2015 recommend 1) and the GRU's \(\mathbf b_z\) negative (FIG 4 uses \(-3\)). Mind two conventions: PyTorch's GRU writes \(\mathbf h_t=(1-\mathbf z_t)\odot\tilde{\mathbf h}_t+\mathbf z_t\odot\mathbf h_{t-1}\), so its \(\mathbf z\) is our \(1-\mathbf z\); it also applies \(\mathbf r_t\) after \(U_n\mathbf h_{t-1}\) rather than before, a minor variant.

    卡尔曼滤波就是一个线性 RNNA Kalman filter is a linear RNN

    沿用 4.8 节的记号(那里 \(\mathbf x\) 是状态、\(\mathbf z\) 是测量):预测 \(\hat{\mathbf x}^-=F\hat{\mathbf x}_{k-1}\),更新 \(\hat{\mathbf x}_k=\hat{\mathbf x}^-+K_k(\mathbf z_k-H\hat{\mathbf x}^-)\)。代入得

    In the notation of Lesson 4.8 (where \(\mathbf x\) is the state and \(\mathbf z\) the measurement): predict \(\hat{\mathbf x}^-=F\hat{\mathbf x}_{k-1}\), update \(\hat{\mathbf x}_k=\hat{\mathbf x}^-+K_k(\mathbf z_k-H\hat{\mathbf x}^-)\). Substituting gives

    $$ \hat{\mathbf x}_k=\underbrace{(I-K_kH)F}_{W_h}\,\hat{\mathbf x}_{k-1}+\underbrace{K_k}_{W_x}\,\mathbf z_k . $$

    增益 \(K_k\) 很快收敛到稳态值,此后这就是一个 \(\phi\) 为恒等映射、参数固定的线性 RNN,状态维数 2(FIG 2 的卡尔曼基线就是它,输出取速度分量)。差别只在参数从哪里来:卡尔曼滤波从模型 \((F,H,Q,R)\) 推出来,RNN 从数据里学出来。这也解释了 FIG 2:当模型(常速度、白噪声加速度)与真实运动不符时,从数据学参数的那一方有机会赢。

    The gain \(K_k\) quickly converges to its steady-state value, after which this is a linear RNN with identity \(\phi\), fixed parameters and a 2-dimensional state (it is FIG 2's Kalman baseline, with the velocity component as output). The only difference is where the parameters come from: the Kalman filter derives them from a model \((F,H,Q,R)\), the RNN learns them from data. This also explains FIG 2: when the model (constant velocity, white-noise acceleration) does not match the real motion, the side that learns its parameters from data has a chance to win.

    状态空间层:离散化、卷积核与稳定性State-space layers: discretization, kernel and stability

    对角化之后每个模态 \(n\) 独立:

    After diagonalization every mode \(n\) is independent:

    $$ \bar A_n=e^{\Delta A_n},\qquad \bar B_n=\frac{e^{\Delta A_n}-1}{A_n}\,B_n,\qquad h_{t,n}=\bar A_nh_{t-1,n}+\bar B_nx_t,\qquad y_t=\sum_n 2\operatorname{Re}\big(C_nh_{t,n}\big),\qquad \hl{kernel}{\bar K_k}=\sum_n2\operatorname{Re}\big(C_n\bar A_n^{\,k}\bar B_n\big). $$

    复模态成对出现(\(A_n\) 与 \(\bar A_n\) 共轭),只存一半再取 \(2\operatorname{Re}\) 就得到实数输出。只要 \(\operatorname{Re}A_n<0\),任何步长下都有 \(|\bar A_n|=e^{\Delta\operatorname{Re}A_n}<1\):零阶保持把左半平面映进单位圆(13.2 节),所以这样参数化的层在训练中不会变得不稳定,这正是 FIG 1 那种“越过单位圆就失控”的问题的结构性解法。实际实现里常把 \(\operatorname{Re}A_n\) 写成 \(-e^{p_n}\) 之类的形式,保证它恒为负(FIG 6 的时不变层用 \(\bar a_n=e^{-\operatorname{softplus}(p_n)}\in(0,1)\),同一个道理)。

    Complex modes come in conjugate pairs (\(A_n\) and its conjugate); storing one of each pair and taking \(2\operatorname{Re}\) gives a real output. As long as \(\operatorname{Re}A_n<0\), every step size gives \(|\bar A_n|=e^{\Delta\operatorname{Re}A_n}<1\): the zero-order hold maps the left half-plane into the unit disc (Lesson 13.2), so a layer parametrized this way can not become unstable during training, a structural cure for FIG 1's "cross the unit circle and the state runs away". Implementations often write \(\operatorname{Re}A_n\) as something like \(-e^{p_n}\) to keep it negative (FIG 6's time-invariant layer uses \(\bar a_n=e^{-\operatorname{softplus}(p_n)}\in(0,1)\), the same idea).

    并行扫描为什么成立Why the parallel scan works

    把第 \(t\) 步写成元素 \(e_t=(a_t,b_t)\),表示映射 \(h\mapsto a_th+b_t\)。两个映射先后作用的结果仍是这种形式:

    Write step \(t\) as an element \(e_t=(a_t,b_t)\) standing for the map \(h\mapsto a_th+b_t\). Applying two such maps in turn gives another one of the same form:

    $$ e_2\hl{scan}{\bullet}e_1=(a_2a_1,\ a_2b_1+b_2),\qquad (e_3\bullet e_2)\bullet e_1=e_3\bullet(e_2\bullet e_1)=(a_3a_2a_1,\ a_3a_2b_1+a_3b_2+b_3),\qquad h_t=\big[e_t\bullet\cdots\bullet e_1\big]_b\ \ (h_0=0). $$

    有结合律就可以随意加括号,于是“所有前缀积”能分轮并行计算。FIG 5 用的 Hillis–Steele 扫描在第 \(\ell\) 轮让每个 \(t\ge2^{\ell-1}\) 同时做 \(e_t\leftarrow e_t\bullet e_{t-2^{\ell-1}}\),\(\lceil\log_2L\rceil\) 轮后完成,总工作量 \(O(L\log L)\);Blelloch(1990)的工作量最优版本只需 \(O(L)\) 次合并、约 \(2\log_2L\) 轮。注意整个推导只用到“\(a_t,b_t\) 已知”,从没用到它们与 \(t\) 无关,所以选择性的 \(a_t=e^{-\Delta_t}\) 照样适用;Mamba 正是用一个针对 GPU 内存层级优化过的扫描来训练的。

    Associativity means the brackets can go anywhere, so "all prefix products" can be computed in parallel rounds. The Hillis–Steele scan of FIG 5 lets every \(t\ge2^{\ell-1}\) do \(e_t\leftarrow e_t\bullet e_{t-2^{\ell-1}}\) simultaneously in round \(\ell\), finishing after \(\lceil\log_2L\rceil\) rounds with total work \(O(L\log L)\); the work-efficient version of Blelloch (1990) needs only \(O(L)\) combinations in about \(2\log_2L\) rounds. Notice that the derivation only uses "\(a_t,b_t\) are known", never that they are independent of \(t\), so the selective \(a_t=e^{-\Delta_t}\) works just as well; Mamba is trained with exactly such a scan, optimized for the GPU memory hierarchy.

    选择性与时不变的极限Selectivity, and the limit of time invariance

    Mamba 让 \(\hl{delta}{\Delta_t}=\operatorname{softplus}(\mathbf w^\top\mathbf x_t+\beta)\),\(B_t\)、\(C_t\) 也是 \(\mathbf x_t\) 的线性函数,\(A\) 本身不依赖输入;FIG 6 的选择性层是它最小的版本:\(\Delta_t=\operatorname{softplus}(w_vv_t+w_mm_t+\beta)\),\(A=-1\),\(B=1\),\(y_t=c\,h_t+d\)。默认种子训练 1500 步后 \(w_m\approx9.8\)、\(\beta\approx-5.9\):有标记的步 \(\Delta_t\approx3.9\)(写入 98%),没有标记的步 \(\Delta_t\approx0.003\)(每步保留 99.7%),读数里能看到这几个数随训练变化。

    为什么时不变的层做不到?读数 \(v_t\) 在 \([-1,1]\) 上独立均匀分布(方差 \(\tfrac13\)),标记以概率 \(p=0.12\) 独立出现。任何时不变线性层的输出都形如 \(\hat y_t=\sum_k\alpha_kv_{t-k}+\sum_k\beta_km_{t-k}+c_0\)(\(c_0\) 为常数)。目标 \(y_t=v_{t-\tau}\),\(\tau\) 是距上一个标记的步数,\(P(\tau=k)=p(1-p)^k\),所以 \(\operatorname{Cov}(y_t,v_{t-k})=\tfrac13p(1-p)^k\),而 \(y_t\) 与所有 \(m_s\) 不相关(\(v\) 均值为零且与标记独立)。输入在时间上互不相关,最优系数就是 \(\alpha_k=p(1-p)^k\)、\(\beta_k=0\),能解释的方差比例为

    Mamba sets \(\hl{delta}{\Delta_t}=\operatorname{softplus}(\mathbf w^\top\mathbf x_t+\beta)\), with \(B_t\) and \(C_t\) also linear functions of \(\mathbf x_t\), while \(A\) itself does not depend on the input. FIG 6's selective layer is its smallest version: \(\Delta_t=\operatorname{softplus}(w_vv_t+w_mm_t+\beta)\), \(A=-1\), \(B=1\), \(y_t=c\,h_t+d\). After 1500 training steps with the default seed, \(w_m\approx9.8\) and \(\beta\approx-5.9\): flagged steps get \(\Delta_t\approx3.9\) (write 98%), unflagged steps \(\Delta_t\approx0.003\) (keep 99.7% per step); the readout shows these numbers evolving during training.

    Why can't a time-invariant layer do it? The readings \(v_t\) are independent and uniform on \([-1,1]\) (variance \(\tfrac13\)); flags appear independently with probability \(p=0.12\). The output of any time-invariant linear layer has the form \(\hat y_t=\sum_k\alpha_kv_{t-k}+\sum_k\beta_km_{t-k}+c_0\). The target is \(y_t=v_{t-\tau}\), where \(\tau\) is the number of steps since the last flag, \(P(\tau=k)=p(1-p)^k\), so \(\operatorname{Cov}(y_t,v_{t-k})=\tfrac13p(1-p)^k\), while \(y_t\) is uncorrelated with every \(m_s\) (\(v\) has zero mean and is independent of the flags). The inputs are uncorrelated in time, so the best coefficients are \(\alpha_k=p(1-p)^k\), \(\beta_k=0\), and the fraction of variance they explain is

    $$ \frac{\sum_{k\ge0}\big(\tfrac13p(1-p)^k\big)^2/\tfrac13}{\tfrac13}=\sum_{k\ge0}p^2(1-p)^{2k}=\frac{p}{2-p}\approx0.064\quad(p=0.12). $$

    (这是长序列的极限,此时 \(\operatorname{Var}(y_t)\to\tfrac13\)。)最好的时不变层也只能比“输出 0”好约 6%;FIG 6 里训练出的时不变层停在约 8%(64 步的短序列开头有一段目标恒为 0,比长序列极限稍容易一点),也就在这附近;它学到的衰减率是什么都无所谓,问题在结构。选择性层把乘积 \(m_t\cdot v_t\) 这种输入之间的乘法交互放进了递推,线性时不变系统天生没有这种能力。

    (This is the long-sequence limit, where \(\operatorname{Var}(y_t)\to\tfrac13\).) The best time-invariant layer is only about 6% better than "output 0"; FIG 6's trained time-invariant layer stops at about 8% (a 64-step sequence starts with a stretch where the target is 0, slightly easier than the long-sequence limit), right in that neighbourhood; whatever decay rates it learns, the problem is structural. The selective layer puts a multiplicative interaction between inputs (\(m_t\) deciding what happens to \(v_t\)) into the recurrence, which a linear time-invariant system fundamentally lacks.

    代价对比Costs compared

    推理时每步的计算compute per step at inference需要带着的记忆memory carried along在长度 \(L\) 的序列上训练training on a sequence of length \(L\)
    RNN / LSTM / GRU\(O(H^2)\)\(H\) 个数(LSTM 为 \(2H\))\(H\) numbers (\(2H\) for an LSTM)\(L\) 个先后相继的步骤\(L\) strictly sequential steps
    时不变 SSM(S4、S4D)time-invariant SSM (S4, S4D)每通道 \(O(N)\)\(O(N)\) per channel每通道 \(N\) 个数\(N\) numbers per channel卷积:FFT \(O(L\log L)\),并行convolution: FFT \(O(L\log L)\), parallel
    选择性 SSM(Mamba)selective SSM (Mamba)每通道 \(O(N)\)\(O(N)\) per channel每通道 \(N\) 个数\(N\) numbers per channel并行扫描:\(\lceil\log_2L\rceil\) 轮parallel scan: \(\lceil\log_2L\rceil\) rounds
    Transformer(17.3 节)Transformer (Lesson 17.3)第 \(t\) 步 \(O(t\,d)\)\(O(t\,d)\) at step \(t\)随 \(t\) 增长的 KV 缓存a KV cache growing with \(t\)注意力 \(O(L^2)\),并行attention \(O(L^2)\), parallel

    6机器人中的它:历史编码器与世界模型In robotics: history encoders and world models

    FIG 2 是一个缩小的典型用法:机器人测得到 \(q\),测不到 \(\dot q\),就从历史里推。放大之后,同样的思路用来推断那些根本没有传感器的量:地面摩擦和软硬、负载质量、电机实际输出的力矩、物体在手里的姿态。做法分两派:一派用固定长度的历史窗口(几十到几百步的本体感觉),交给 MLP、一维卷积(TCN)或 Transformer;另一派用循环状态,每个控制周期更新一次。前者训练简单、没有“状态带到哪里”的问题;后者每步代价固定、能记住窗口之外的东西。选哪个往往取决于控制频率、机载算力和任务需要的记忆长度。

    FIG 2 is a miniature of the typical use: the robot measures \(q\) but not \(\dot q\), so it infers it from the history. Scaled up, the same idea infers quantities for which no sensor exists at all: ground friction and softness, payload mass, the torque a motor actually delivers, the pose of an object in the hand. There are two camps: one uses a fixed-length history window (tens to hundreds of steps of proprioception) fed to an MLP, a 1-D convolution (TCN) or a Transformer; the other keeps a recurrent state updated once per control cycle. The first is simpler to train and has no "where does the state come from" problem; the second has a fixed cost per step and can remember things outside any window. The choice often comes down to the control rate, the onboard compute and how much memory the task needs.

    真实系统里In real systems

    灵巧手:OpenAI 的 Dactyl(Andrychowicz 等,IJRR 2020)在大量随机化的仿真里训练 LSTM 策略:有了记忆,策略可以从近期历史里推断当前这一局的物理参数。 腿式机器人:ANYmal 的野外行走(Lee 等,Science Robotics 2020)用一个时间卷积网络读一长段本体感觉历史;RMA(Kumar 等,2021)用一小段最近的状态和动作估计环境参数的隐变量,见 23.2 节;俄勒冈州立大学的 Cassie 双足机器人盲走楼梯(Siekmann 等,RSS 2021)用的是带记忆的循环策略,作者认为这项能力依赖于策略的记忆,因为不看地形走楼梯是部分可观测的。 世界模型:Dreamer 系列的 RSSM 用 GRU 做确定性的状态通路,再加随机隐变量,在想象中训练策略,见 24.3 节。 Transformer 与 SSM:人形机器人行走也有用因果 Transformer 读历史的工作(Radosavovic 等,Science Robotics 2024),原理见 17.3 节;Mamba 类模型在机器人上还比较新,已有模仿学习工作尝试用它替代 Transformer 作为策略主干,看重的正是“长上下文、每步固定代价”。 工具:PyTorch 的 nn.LSTM、nn.GRU(GPU 上调用 cuDNN 的融合实现);Mamba 的官方实现以 mamba-ssm 包发布,扫描是自定义的 CUDA 核。 递推策略的强化学习:从回放池里训练循环策略时,R2D2(Kapturowski 等,ICLR 2019)把隐藏状态一起存下,并先用一段“热身”序列把状态跑热再计算损失,FIG 2 里不计分的前 10 步是同一个思路。

    Dexterous hands: OpenAI's Dactyl (Andrychowicz et al., IJRR 2020) trained an LSTM policy in heavily randomized simulation: with memory, the policy can infer the current episode's physics from recent history. Legged robots: ANYmal's outdoor locomotion (Lee et al., Science Robotics 2020) reads a long proprioceptive history with a temporal convolutional network; RMA (Kumar et al., 2021) estimates a latent of the environment parameters from a short window of recent states and actions, see Lesson 23.2; the blind stair climbing of Oregon State's Cassie biped (Siekmann et al., RSS 2021) used a recurrent policy with memory, and the authors attribute the skill to that memory, since walking stairs blind is partially observable. World models: the RSSM of the Dreamer family uses a GRU as its deterministic state path plus stochastic latents, and trains policies in imagination, see Lesson 24.3. Transformers and SSMs: humanoid locomotion has also been done with a causal Transformer reading the history (Radosavovic et al., Science Robotics 2024), whose mechanism is in Lesson 17.3; Mamba-style models are still new in robotics, with imitation-learning work starting to try them as policy backbones in place of Transformers, precisely for "long context at a fixed cost per step". Tools: PyTorch's nn.LSTM and nn.GRU (calling cuDNN's fused kernels on a GPU); Mamba's official implementation is released as the mamba-ssm package, with the scan as a custom CUDA kernel. RL with recurrent policies: when training a recurrent policy from a replay buffer, R2D2 (Kapturowski et al., ICLR 2019) stores the hidden states with the data and first runs a "burn-in" stretch to warm the state up before computing the loss; FIG 2's 10 unscored steps are the same idea.

    7常见误区Common pitfalls

    误区 1:训练和部署时的状态不一致Pitfall 1: the state is handled differently in training and deployment

    FIG 2 的网络只在“从 \(\mathbf h_0=\mathbf 0\) 开始的 1.6 s 片段”上训练过。部署时如果每个控制周期都把状态清零,它就退化成一个只看一帧的网络;如果开机后一直带着状态跑几个小时,它就进入了训练中从未见过的状态区域,输出可能慢慢漂走。规则是:部署时怎样处理状态(何时清零、带多久),训练时就要见过同样的情形;常见做法是在一局开始时清零、训练用长短不一的序列,或者像 R2D2 那样先热身再计分。

    FIG 2's network was only ever trained on "1.6 s clips starting from \(\mathbf h_0=\mathbf 0\)". If deployment resets the state every control cycle, it degenerates into a network that sees one frame; if it carries the state for hours after power-up, it enters regions of state space it never saw in training and its output may slowly drift. The rule: however the state is handled in deployment (when it is reset, how long it is carried), training must have seen the same; common practice is to reset at the start of an episode, to train on sequences of varied length, or to burn in before scoring as R2D2 does.

    误区 2:截断太短,却以为“状态反正会往前传”Pitfall 2: truncating too short, reasoning that "the state is carried forward anyway"

    截断不限制状态能携带多远的信息,但限制了网络能学会携带多远:梯度到不了的地方,就没人教它“这里该写下什么”。FIG 2 的 \(K=1\) 就是这样失败的。截断长度要不短于任务需要的记忆跨度,否则就换一种能看到更长历史的训练方式。

    Truncation does not limit how far the state can carry information, but it limits how far the network can learn to carry it: where the gradient does not reach, nobody teaches it "write this down here". That is how FIG 2's \(K=1\) fails. The truncation length must be no shorter than the memory span the task needs; otherwise train in a way that sees longer histories.

    误区 3:只防爆炸,不管消失Pitfall 3: guarding against explosion but not against vanishing

    梯度裁剪能挡住爆炸(损失突然变成 NaN 的那种),但对消失毫无作用:消失的梯度不报错,网络只是安静地学不会长程依赖,损失卡在一个平台上(FIG 4 里 RNN 在 \(D=60\) 时的正确率曲线)。用门控单元或线性递推,并把门偏置初始化成“保留”;要验证模型确实用到了长历史,就像 FIG 4 那样专门构造一个需要长记忆的测试。

    Gradient clipping stops explosion (the kind where the loss suddenly turns into NaN) but does nothing against vanishing: a vanishing gradient raises no error; the network just quietly fails to learn the long-range dependency and the loss sits on a plateau (FIG 4's RNN accuracy curve at \(D=60\)). Use gated cells or linear recurrences and initialize the gate biases towards "keep"; to check that a model really uses the long history, build a test that needs long memory, as FIG 4 does.

    误区 4:换了控制频率却照用原来的网络Pitfall 4: changing the control rate and reusing the network as is

    离散 RNN 学到的是“每一步”的动态:FIG 1 里一个脉冲每步乘 \(\lambda\)。把 50 Hz 训练的网络放到 100 Hz 的回路里,同样的 \(\lambda\) 意味着连续时间里的记忆短了一半,学到的速度估计(FIG 2 里隐含的 \(\Delta t=0.02\) s)也全错了。时间步不均匀(通信抖动、丢帧)也是同样的问题。状态空间层显式地有步长 \(\Delta\),原则上可以按新的采样率改 \(\Delta\)(S4 的论文演示过换采样率直接测试),但层间的非线性部分并不知道时间单位变了,最稳妥的仍是在部署频率上训练,或把 \(\Delta t\) 作为输入喂给网络。

    A discrete RNN learns per-step dynamics: in FIG 1 a pulse is multiplied by \(\lambda\) once per step. Put a network trained at 50 Hz into a 100 Hz loop and the same \(\lambda\) means half the memory in continuous time, and the learned velocity estimate (with FIG 2's implicit \(\Delta t=0.02\) s) is simply wrong. Uneven time steps (communication jitter, dropped frames) are the same problem. A state-space layer has an explicit step \(\Delta\) and in principle can be given a new \(\Delta\) for a new sampling rate (the S4 paper demonstrated testing directly at a changed sampling rate), but the nonlinear parts between layers do not know that the time unit changed; the safe course is still to train at the deployment rate, or to feed \(\Delta t\) to the network as an input.

    误区 5:把“线性 SSM”和“RNN”当成可以随意互换Pitfall 5: treating "linear SSM" and "RNN" as freely interchangeable

    时不变的线性层能并行训练、不会失稳,但它不能根据内容决定记什么(FIG 6,第 5 节的界);要这种能力得加选择性,而选择性又让卷积失效,只能用扫描(FIG 5)。反过来,非线性 RNN 什么都能表示,却只能顺序训练、且梯度难传。还要注意稳定性要靠参数化来保证:直接把 \(\bar A\) 当自由参数学,训练中特征值一旦越过单位圆(FIG 1),状态就会爆掉;应像第 5 节那样让 \(\operatorname{Re}A<0\) 恒成立。

    A time-invariant linear layer trains in parallel and cannot become unstable, but it cannot decide what to remember based on content (FIG 6, the bound in Section 5); that needs selectivity, which in turn breaks the convolution and requires a scan (FIG 5). Conversely, a nonlinear RNN can represent anything but trains only sequentially and passes gradients poorly. Also, stability must come from the parametrization: learn \(\bar A\) as a free parameter and the moment an eigenvalue crosses the unit circle during training (FIG 1), the state blows up; keep \(\operatorname{Re}A<0\) by construction as in Section 5.

    8小练习Check yourself

    1. 一个线性 RNN 的 \(W_h\) 有两个实特征值,绝对值分别是 0.9 和 0.5。在 \(t=0\) 给一个脉冲,20 步之后慢模态里还剩原来的多少?1. A linear RNN's \(W_h\) has two real eigenvalues of magnitude 0.9 and 0.5. A pulse arrives at \(t=0\). After 20 steps, what fraction remains in the slow mode?
    每一步乘一次特征值,20 步后是 \(0.9^{20}\approx0.12\);它的半衰期是 \(\ln\tfrac12/\ln0.9\approx6.6\) 步。选项 C 是快模态的 \(0.5^{20}\approx10^{-6}\)。长期来看状态几乎只剩慢模态:记忆长度由最接近单位圆的特征值决定(FIG 1)。Each step multiplies by the eigenvalue, so after 20 steps \(0.9^{20}\approx0.12\) remains; its half-life is \(\ln\tfrac12/\ln0.9\approx6.6\) steps. Option C is the fast mode's \(0.5^{20}\approx10^{-6}\). In the long run almost only the slow mode is left: memory length is decided by the eigenvalue closest to the unit circle (FIG 1).
    2. FIG 2 里用截断长度 \(K=1\) 训练的 RNN 始终比不上卡尔曼滤波。根本原因是?2. In FIG 2, an RNN trained with truncation \(K=1\) never beats the Kalman filter. What is the root cause?
    截断只切断反向传播的梯度,状态照样往前传(所以选项 A 错)。可速度估计要求网络在第 \(t-1\) 步就把位置存进状态,以便第 \(t\) 步做差、并在多步上平滑;\(K=1\) 时第 \(t\) 步的误差永远传不到第 \(t-1\) 步的写入操作。同样的 12 个单元用完整 BPTT 训练能做到约 0.27 rad/s,可见容量不是问题(选项 D 错)。Truncation only cuts the backward gradient; the state still flows forward (so option A is wrong). But velocity estimation requires the network to store the position in its state at step \(t-1\) so that it can take a difference at step \(t\) and smooth over many steps; with \(K=1\) the error at step \(t\) never reaches the write at step \(t-1\). The same 12 units trained with full BPTT reach about 0.27 rad/s, so capacity is not the problem (option D is wrong).
    3. LSTM 沿细胞状态的直通路径上,\(\partial\mathbf c_t/\partial\mathbf c_{t-1}\) 等于?3. Along the LSTM's direct cell-state path, what is \(\partial\mathbf c_t/\partial\mathbf c_{t-1}\)?
    由 \(\mathbf c_t=\mathbf f_t\odot\mathbf c_{t-1}+\mathbf i_t\odot\mathbf g_t\),对 \(\mathbf c_{t-1}\) 直接求导得 \(\operatorname{diag}(\mathbf f_t)\):没有循环矩阵,也没有 tanh 的导数。只要遗忘门接近 1,乘很多步也不衰减,这就是 FIG 3 里遗忘门偏置大时 LSTM 曲线保持平坦的原因。选项 C 是普通 tanh RNN 的单步雅可比。From \(\mathbf c_t=\mathbf f_t\odot\mathbf c_{t-1}+\mathbf i_t\odot\mathbf g_t\), the direct derivative with respect to \(\mathbf c_{t-1}\) is \(\operatorname{diag}(\mathbf f_t)\): no recurrent matrix, no tanh derivative. As long as the forget gate is near 1, many multiplications do not shrink it, which is why FIG 3's LSTM curve stays flat for a large forget-gate bias. Option C is the one-step Jacobian of a plain tanh RNN.
    4. 下面哪一种层,整段序列的输出可以写成输入与一个固定卷积核的卷积?4. For which layer can the output over a whole sequence be written as the convolution of the input with one fixed kernel?
    卷积核 \(\bar K_k=C\bar A^k\bar B\) 要求每一步的 \(\bar A,\bar B,C\) 都相同,即线性且时不变。GRU 和 LSTM 是非线性的;选择性 SSM 是线性的,但 \(\bar A_t\) 随输入变化,没有单一的卷积核(FIG 5 切到“Δ 随输入变化”时卷积误差变大)。它仍然可以用并行扫描训练,因为扫描只需要结合律。The kernel \(\bar K_k=C\bar A^k\bar B\) requires the same \(\bar A,\bar B,C\) at every step: linear and time-invariant. The GRU and LSTM are nonlinear; the selective SSM is linear, but \(\bar A_t\) changes with the input, so there is no single kernel (FIG 5's convolution error grows under "Δ depends on the input"). It can still be trained with a parallel scan, which only needs associativity.
    5. 选择性层 \(h_t=e^{-\Delta_t}h_{t-1}+(1-e^{-\Delta_t})v_t\) 在 FIG 6 里训练好之后,在没有标记的步上 \(\Delta_t\) 是什么样?5. After FIG 6's selective layer \(h_t=e^{-\Delta_t}h_{t-1}+(1-e^{-\Delta_t})v_t\) is trained, what does \(\Delta_t\) look like on unflagged steps?
    没有标记的读数是要忽略的,所以 \(e^{-\Delta_t}\approx1\),即 \(\Delta_t\approx0\):训练 1500 步后约为 0.003,每步保留 99.7%。有标记时 \(\Delta_t\approx3.9\),一步写入 98%。\(\Delta_t=\operatorname{softplus}(\cdot)\) 恒为正,所以选项 D 不可能。这正是 GRU 的更新门 \(z_t=1-e^{-\Delta_t}\):在该保留的地方关上。Unflagged readings are to be ignored, so \(e^{-\Delta_t}\approx1\), i.e. \(\Delta_t\approx0\): about 0.003 after 1500 training steps, keeping 99.7% per step. On flagged steps \(\Delta_t\approx3.9\), writing 98% in one step. \(\Delta_t=\operatorname{softplus}(\cdot)\) is always positive, so option D is impossible. This is exactly a GRU update gate \(z_t=1-e^{-\Delta_t}\), closed where the state should be kept.

    9延伸阅读Further reading

    • J. L. Elman, Finding Structure in Time, Cognitive Science, 1990 — 简单循环网络(Elman 网络)the simple recurrent ("Elman") network
    • P. J. Werbos, Backpropagation Through Time: What It Does and How to Do It, Proceedings of the IEEE, 1990 — BPTT 的经典讲解the classic account of BPTT
    • Y. Bengio, P. Simard & P. Frasconi, Learning Long-Term Dependencies with Gradient Descent is Difficult, IEEE Transactions on Neural Networks, 1994 — 梯度消失问题the vanishing-gradient problem
    • S. Hochreiter & J. Schmidhuber, Long Short-Term Memory, Neural Computation, 1997;F. A. Gers, J. Schmidhuber & F. Cummins, Learning to Forget: Continual Prediction with LSTM, Neural Computation, 2000 — LSTM 与遗忘门the LSTM and its forget gate
    • K. Cho et al., Learning Phrase Representations using RNN Encoder–Decoder for Statistical Machine Translation, EMNLP 2014 — GRU 的出处where the GRU comes from
    • R. Pascanu, T. Mikolov & Y. Bengio, On the Difficulty of Training Recurrent Neural Networks, ICML 2013 — 消失与爆炸的条件,梯度裁剪conditions for vanishing and exploding, gradient clipping
    • R. Jozefowicz, W. Zaremba & I. Sutskever, An Empirical Exploration of Recurrent Network Architectures, ICML 2015 — 大规模比较门控结构,遗忘门偏置取 1a large comparison of gated architectures; forget-gate bias of 1
    • A. Gu, K. Goel & C. Ré, Efficiently Modeling Long Sequences with Structured State Spaces, ICLR 2022 — S4S4
    • A. Gu, A. Gupta, K. Goel & C. Ré, On the Parameterization and Initialization of Diagonal State Space Models, NeurIPS 2022 — S4D,FIG 5 的初始化S4D, the initializations of FIG 5
    • J. T. H. Smith, A. Warrington & S. W. Linderman, Simplified State Space Layers for Sequence Modeling, ICLR 2023 — S5:用并行扫描计算状态空间层S5: state-space layers computed with a parallel scan
    • A. Gu & T. Dao, Mamba: Linear-Time Sequence Modeling with Selective State Spaces, 2023 (COLM 2024) — 选择性状态空间模型selective state-space models
    • G. E. Blelloch, Prefix Sums and Their Applications, Carnegie Mellon University technical report, 1990 — 并行前缀扫描parallel prefix scans
    • OpenAI: M. Andrychowicz et al., Learning Dexterous In-Hand Manipulation, International Journal of Robotics Research, 2020 — 随机化仿真中训练的 LSTM 灵巧手策略an LSTM dexterous-hand policy trained in randomized simulation