recurrent-state-and-credit.md · 可读全文

这里保留原文的中文、公式标记、代码和链接。可直接交给 Agent 读取,也可选取下方原文复制。此入口返回 HTML;原始 .md / .py 文件仍保留,完整候选包同时包含 UTF-8 原件。

# 状态在流动,梯度可以停在边界

课堂接续:[T10](https://codingai-lec05.pages.dev/classroom/T10.html?step=b0) · [T11](https://codingai-lec05.pages.dev/classroom/T11.html?step=b0) · [T12](https://codingai-lec05.pages.dev/classroom/T12.html?step=b0) · [T13](https://codingai-lec05.pages.dev/classroom/T13.html?step=b0) · [T14](https://codingai-lec05.pages.dev/classroom/T14.html?step=b0) · [T15](https://codingai-lec05.pages.dev/classroom/T15.html?step=b0) · [T16](https://codingai-lec05.pages.dev/classroom/T16.html?step=b0)。连续读本:[第2章](https://codingai-lec05.pages.dev/lecture.html#chapter-2);本主题提供独立定义、例子、代码与来源。

同一九单位给书句从我、昨天开始逐项进入共享状态。状态是当前前向的量,参数是在所有时间步共用的规则;门控与梯度又各自回答运行和学习的问题。下面先解释状态,再用两个四事件块说明截断,保留TBPTT、二维LSTM与GRU公式作为独立扩展。


[阅读本主题](https://codingai-lec05.pages.dev/course/knowledge/recurrent-state-and-credit.html) · [返回实验](https://deepnote.com/workspace/ise3309jingao-5ba66b0a-4283-4f5a-ae06-3f68d3201e99/project/Fall-26-Lecture-05-841ec8e7-e352-4840-b628-d3742b03d6d0/notebook/LAB-01-ec403d28cc2c400ba661cd270588669f?utm_content=ec403d28cc2c400ba661cd270588669f&utm_source=openai&utm_medium=mcp&utm_campaign=openaimcp&utm_term=get_notebook) · [与Agent共读全文](https://codingai-lec05.pages.dev/course/knowledge/recurrent-state-and-credit.md.read.html)

读本:[ CLS 01 · 序列目标与共享状态 ](https://deepnote.com/workspace/ise3309jingao-5ba66b0a-4283-4f5a-ae06-3f68d3201e99/project/Fall-26-Lecture-05-841ec8e7-e352-4840-b628-d3742b03d6d0/notebook/CLS-01-b1c8e2fd764441e8820b808fc40ec3cb?utm_content=b1c8e2fd764441e8820b808fc40ec3cb&utm_source=openai&utm_medium=mcp&utm_campaign=openaimcp&utm_term=get_notebook),查找“状态在流动,梯度可以停在边界”;实验中查找“C · 共享参数的梯度到底加了几次?”。


<span id="recurrent-state-and-credit-s01"></span>

## 输入、状态和输出接在哪里

源句为“我/昨天/给/了/他/一/本/书/。”,九个单位来自本课的教学切分。

把源句九单位送过encoder,取末隐藏状态形成固定源摘要 $c_{src}=h_n$,再通过 $s_0=g(c_{src})$ 建立decoder的初始状态。第一次预测先用BOS与 $s_0$ 更新出 $s_1$,再由 $s_1$ 形成I的词表分布;选中I后,本步新输入I与上一状态 $s_1$ 一起产生 $s_2$,再预测gave。写到 `I gave` 时,新送入的只有gave,它与上一状态 $s_2$ 更新出 $s_3$,随后才形成him的分布;him仍是候选,选中后才成为下一步输入。后续同样经过状态更新、词表分布、选择和反馈,依次接入him、a、book、yesterday与句号,最终选中EOS结束。图旁的完整前缀用于记下已生成内容,不表示每一步都把整段前缀重新送入这一个RNN。

![源摘要只初始化s0;每步由新token与上一状态更新,完整生成到EOS](https://codingai-lec05.pages.dev/assets/r72/classroom/T15-b9.svg)

`I gave him a book yesterday . EOS` 是这个教学任务的合适目标。这里展示的是合适目标及生成接口,不是受训模型在这句话上的实测输出。源长9、目标文本7项再加EOS,共8个预测目标;两侧长度不同没有矛盾。句号有自己的下一步预测,不能用它代替EOS。

固定的是源接口,不是每一步decoder状态或输出分布。图中的 $s$ 是decoder递推状态的总记号;采用LSTM时,它可包含hidden与cell,而 $c_{src}$ 只指源摘要。图保留 $c_{src}→s_0$ 作为初始化背景,后续活动连接是“上一状态+本步新输入→当前状态→词表分布”,源条件沿状态传递,不在每一步重新注入。另一种实现可以每步再次注入源条件;具体实验必须声明使用哪一种。原LAB02采用双向源编码、decoder零初始化和逐步注入,固定组对有效源状态取均值,动态组逐次读取。因此不能把本段末状态初始化的示意当成LAB02训练配置。

扩大状态、改进训练和门控都可能改善这个已经可用的接口。一个短例没有证明固定摘要装不下;有限维实向量也不是长句必然失败的数学定理。是否有必要保留源位置供每步读取,要用任务与受控结果继续判断。



|实际任务|输入/输出位置|最后一个状态是否足够|
|---|---|---|
|给每个词标人名/地名|每个词读入后接一个标签头|只取末状态会丢掉逐位置输出接口|
|判断整封短信是否垃圾|全部输入后接句子分类头,也可池化全部状态|是否足够是表示与任务的经验问题|
|流式门禁/下一词预测|每来一个事件就更新状态、产生预测|不能偷看未来事件|
|翻译一句话|源端编码结束后启动变长目标生成|固定状态或整列源状态是不同条件接口|

共享的是更新函数的参数;`h_2`和`h_8`是两次不同的状态数值。多层RNN又有层轴:同一时刻第2层读第1层状态;它不是把同一个序列多训练一遍。双向编码器从左右读已知完整源句,能让“bank”使用右侧river;在线生成未知未来词时不能沿反向支路偷读答案。

<span id="recurrent-state-and-credit-s02"></span>

## 状态随输入变,参数在时间上共享

九单位源句依次进入同一更新规则 $h_t=\tanh(Ue_t+Wh_{t-1}+b)$。$e_t$ 是当前输入的 embedding,$h_t$ 是这次处理后的状态,$U,W,b$ 是在时间位置共享的参数。$\tanh$逐坐标作非线性变换,把有限实数压到−1与1之间。运行到昨天时参数不会换一套,但状态必须使用已经处理“我”所得的结果。

取未训练的二维教学参数 $U=I,W=0.5I,b=0,h_0=(0,0)$,并给定 $e_{我}=(1,0),e_{昨天}=(0,1)$:

$$h_1=\tanh(1,0)\approx(.761594,0),$$
$$Ue_{昨天}+Wh_1=e_{昨天}+.5h_1=(.380797,1),$$
$$h_2=\tanh(.380797,1)\approx(.363399,.761594).$$

第二行把当前输入与旧状态的贡献相加,可以看到先前“我”的影响仍在。后七个单位继续用同一更新规则;未给其输入向量或实际运行结果时,只画符号状态,不伪造受训数值。

![我与昨天两步共享U、W,第二步得到(.363399,.761594)](https://codingai-lec05.pages.dev/assets/r72/classroom/T11-b2.svg)

状态保存能力与任务表现需要另行验证。“我昨天给了他一本封面很厚、里面夹着许多便签的书。”仍是给书事件,但序列多了修饰内容;扩展句的位置必须重新编号,不能沿用九单位图的索引。末尾需要的早期关系要经过更多状态更新,这说明依赖路径变长,没有提供一次已测得的失败。下面保留的钥匙配对与梯度检查是不同任务,用来分别检验早期事实是否必要、反向计算是否正确。

以下三步“我/昨天/给了”是旧六片段扩展,第三步不是当前九单位的“给”位置;保留其输入与数值便于复算。

本章用列向量书写单条序列。输入 $x_t\in\mathbb R^d$,状态 $h_t\in\mathbb R^H$,词表 logits $a_t\in\mathbb R^V$。一个基本 tanh RNN 为

$$u_t=W_xx_t+W_hh_{t-1}+b_h,\qquad h_t=\tanh(u_t),$$
$$a_t=W_yh_t+b_y,\qquad p_t=\operatorname{softmax}(a_t).$$

<span id="read-R15"></span>

$W_x$ 的形状为 $H\times d$,$W_h$ 为 $H\times H$,$W_y$ 为 $V\times H$。$h_0$ 可设为零、学得参数,或由条件输入产生;必须明确采用哪一种。每读一个 token,$h_t$ 改变,$W_x,W_h,W_y$ 在这次前向计算中保持不变。把网络画成很多时间格,只是在展示同一组参数被使用多次。

状态手算取暂略BOS的二维切片:$W_x=I_2,W_h=0.5I_2,b=0,h_0=0$,我、昨天、给了的输入分别为 $(1,0),(0,1),(1,1)$;得到 $(.761594,0)$、$(.363399,.761594)$、$(.827987,.881130)$。多位置训练图补回BOS后使用符号状态;未指定 BOS 向量,不能假称同一数值前向。

第二步最有意义的观察不是小数位,而是“昨天”到来时没有重新从零开始。$h_2$的输入中包含$0.5h_1$,所以“我”已经退出当前token位置,仍能通过上一状态影响这次结果。另一方面,$W_h$没有因为到了第二步而换一套。运行时变化的是状态,训练时优化的是参数;时间展开只是重复调用的账本。这里还没有保证早先每一项信息都保存得好。

作为课后独立复算,取一个标量例子:$h_0=0$、$W_x=0.5$、$W_h=0.8$、偏置为零,输入为 $(1,0)$。第一步 $h_1=\tanh(0.5)\approx0.462117$;第二步 $h_2=\tanh(0.8h_1)\approx0.353724$。第二个输入虽为零,状态并没有归零,因为它还带着前一步的影响。这个例子只证明计算有状态,不证明它已经学会了长距离任务。

把输出放在每一步,可以做 next-token LM 或逐位置标注;只从最后状态输出,可以做整句分类;用图像特征初始化状态并逐步预测词,可以做字幕。双向、分层或注意力会改变信息流,但不改变“参数与激活要分清”的基本要求。

<span id="read-R16"></span>

<span id="recurrent-state-and-credit-s03"></span>

## 展开之后,BPTT 就是链式法则

![旧版独立扩展:多位置loss在共享参数处汇合](https://codingai-lec05.pages.dev/assets/r71/classroom/S07-b3.svg)

单步更新说明怎样运行,多位置监督说明怎样学习。可以先在展开图上任选两个输出位置:它们各自产生loss,却都依赖同一$W_h$。若只保留某一次调用的梯度,就忽略了这项参数对其他位置的影响。因此需要沿时间依赖追溯,并把各次使用的贡献相加。完整训练图使用符号状态,不应将前面的二维$h_1,h_2$数值直接贴到新图。

设目标 $y_t$ 是与输入错位后的下一 token,总损失 $L=\sum_{t=1}^{T}\ell_t$,其中 $\ell_t=-\log p_t[y_t]$。为了写清反向传播,定义输出误差 $e_t=p_t-\operatorname{onehot}(y_t)$,再令 $\delta_t=\partial L/\partial u_t$。从最后一步反向递推:

$$\delta_t=\left(W_y^\top e_t+W_h^\top\delta_{t+1}\right)\odot(1-h_t\odot h_t),\qquad \delta_{T+1}=0.$$

括号里有两条来源。第一项是本时刻预测错误传回来的梯度;第二项是后续所有损失通过状态链传回来的梯度。漏掉第二项,模型仍可能降低局部预测损失,却没有正确学习当前状态对未来的作用。这就是 backpropagation through time 的核心。

共享参数的梯度汇总为

$$\nabla W_y=\sum_t e_th_t^\top,\qquad \nabla b_y=\sum_t e_t,$$
$$\nabla W_x=\sum_t\delta_tx_t^\top,\qquad
\nabla W_h=\sum_t\delta_th_{t-1}^\top,\qquad
\nabla b_h=\sum_t\delta_t.$$

若输入来自 embedding,$\partial L/\partial x_t=W_x^\top\delta_t$ 再累加到对应词表行;同一个词出现多次,需要相加,不能覆盖。若 $h_0$ 可训练,还要保留 $W_h^\top\delta_1$。这些式子使用“时间损失求和”的约定;若前向取平均,所有梯度也要除以相同的有效目标数。经典训练困难分析与梯度范数裁剪见 [Pascanu、Mikolov 与 Bengio,2013,§2–3](https://arxiv.org/abs/1211.5063)。

<span id="recurrent-state-and-credit-s04"></span>

## 同一条历史,两种不同的截断

以下只举两个四事件块的关系:第2条写入一个事实,第8条的查询需要它。第1–4条属于第一块,第5–8条属于第二块;这里仅规定位置和依赖,不提供新的训练成绩。第一块处理到 `h_4`。第二块用 `stop_gradient(h_4)` 作为起点,数值与 `h_4` 相同,所以第2条的信息若已被保留,仍可以影响第8条输出;但第8条loss的梯度不会穿过这个边界去改第2条的写入过程。第二块仍会对第5–8条使用的**同一组参数**产生梯度。若块间做了参数更新,携带状态还是旧参数算出的值,并没有重新编码全部过去。

```python
state = initial_state()
for chunk in stream_chunks:
    state = detach(state)       # 保留数值,截断本次求导历史
    outputs, state = rnn(chunk, state)
    loss(outputs, targets).backward()
    optimizer.step(); optimizer.zero_grad()
```

这是解释截断的伪代码,不对应新的训练成绩。若改成每块 `state=initial_state()`,那是同时清掉前向历史,改变了可用信息。将“detach”和“清零”混同,会误以为截断窗口就是模型能记住的最大长度。更长梯度跨度也不保证学会任务;它只是允许远处写入收到这次误差的信用信号。

<span id="recurrent-state-and-credit-s05"></span>

## 长序列为什么不一定是长依赖

一万条日志末尾两条就能判定的任务,不要求利用最早事件。LAB01 C用一对除了早期线索外后缀相同的序列,才迫使判断依赖远处差异;`gap`改变真实数据长度、距离和显示。保留DN1.1定义:总长gap+2,线索到QUERY距离gap+1。短的固定gap=3有限差分检查另列,不能把其数值叫成gap=32的检查。

观察准确率不升至少有四个解释:到早期状态的梯度太小;状态不再保留标签信息;信息仍在但当前读出头不会用;优化尚未成功。检查逐位置梯度、冻结状态训练简单探针、加易学的短距离版本、检查训练/验证分布,可以分别提供证据。探针读不出也不严格证明信息为零,只否定该探针与训练程序能读出的假设。现有12更新smoke只验证计算链,不足以裁决远距离能力。

<span id="recurrent-state-and-credit-s06"></span>

## 为什么远处的信用分配困难

先分清两个需要检验的问题:状态在前向中是否带来早先信息的影响,末尾损失在训练中是否能改变早期的处理。RNN计算图为二者提供了通路,但“箭头连得上”并不等于模型已经学会使用它。一个有判别力的任务要让答案真正随早先事实改变,而不能只靠常见标签或末尾词猜中。

考虑一条受控输入:“蓝扣钥匙放进赭色盒子”,接着给出若干不涉及钥匙的干扰事件,末尾问钥匙在哪里。正确答案必须依赖前面那条事实。我们可以把盒子颜色均匀随机,确保最后几个词不泄露答案,再改变事实与问题的距离。这样测到的才是对远处信息的利用;把 A→B→C 周期从 12 步加长到 18 步,只需要局部转移,并不构成这种证据。

<span id="read-R18"></span>

最直接的配对检查,是保持电话、杯子和末尾问题逐字相同,只把开头的赭色盒子改成灰色盒子。正确答案随之变化。任何只依赖共同后缀的确定性系统都无法同时答对这对样本;这给“使用远处信息”一个可以反驳的标准。逐步增加干扰距离,才是在给这条通路增加负担,而不是单纯把输入写得更长。

若末尾答错,loss要影响开头的写入,就必须穿过中间多次更新。基本 RNN 的单步状态 Jacobian 为

$$J_t=\frac{\partial h_t}{\partial h_{t-1}}=\operatorname{diag}(1-h_t^2)W_h,$$

从 $s$ 到 $t$ 的梯度包含 $J_tJ_{t-1}\cdots J_{s+1}$。许多小于 1 的因子连乘,远处损失就难以改变早期写入;许多较大的因子连乘,梯度可能爆炸。矩阵乘积还受方向、奇异值和非线性饱和影响,不能只看一个权重或把所有训练现象归结为单个特征值。tanh 饱和时导数接近零,会进一步削弱某些路径。

<span id="read-R19"></span>

梯度范数裁剪处理的是更新不稳定。把所有待更新参数的梯度拼成 $g$,设置阈值 $\tau$:

$$g\leftarrow g\,\min\left(1,\frac{\tau}{\|g\|_2}\right),\qquad
\|g\|_2=\sqrt{\sum_i g_i^2}.$$

零范数时保持零即可。超阈值后保持整体方向、压小长度;这不同于逐元素裁剪。裁剪可以防止一次大梯度把参数推得过远,不能恢复已经衰减到几乎零的远程信号。实验里应同时记录裁剪前范数、裁剪触发比例与任务准确率,避免仅凭损失不发散就宣称记忆问题已解决。

完整 BPTT 需要保存用于反向传播的时间激活。截断 BPTT 每隔若干步把状态与之前的计算图断开:前向状态的数值仍可传到下一段,梯度却不能穿过截断边界。这减少内存与计算,也限制了训练时直接分配长期信用的范围。不要把“状态没有清零”误认为“梯度仍能回到整条历史”。

<span id="read-R20"></span>

<span id="recurrent-state-and-credit-s07"></span>

## 一次完整的保留、写入和输出

LSTM显式区分记忆单元 $c_t$ 与用于对外计算的隐藏状态 $h_t$;它们也不同于翻译的源摘要 $c_{src}$。一次更新把旧内容的保留、候选内容的写入和对外输出分开:$c_t=f_t\odot c_{t-1}+i_t\odot g_t$,$h_t=o_t\odot\tanh(c_t)$。实际门值由当前输入与旧隐藏状态通过可学习参数算出。

为看清动作,先给定一个标量切片:$c_{t-1}=1,f_t=.9,i_t=.1,g_t=.5,o_t=.8$。于是 $c_t=.9\times1+.1\times.5=.95$,$h_t=.8\tanh(.95)\approx.591826$。保留0.9、写入0.05、再输出经过压缩的一部分,是这次给定门值的计算,不是模型已学会了哪一种语言记忆。下列二维完整参数算例继续打开门值怎样算出,保留原来的独立身份。

钥匙任务提示了三种应能分开调节的行为:事实出现时写入,无关事件经过时保留,查询出现时读出。只缩小梯度无法替状态决定哪些信息应当留下。因此,下一项结构选择把保存旧内容和写入新内容放进可区分的通路,并允许当前输出只暴露其中一部分。

LSTM 增加一个 cell 状态 $c_t$,把一条主要状态更新写成加性形式。本节采用常见的无 peephole、带 forget gate 版本;它不是逐字复刻 1997 年最初版本。令 $z_t=[h_{t-1};x_t]$,四个可学习变换为

$$f_t=\sigma(W_fz_t+b_f),\quad i_t=\sigma(W_iz_t+b_i),$$
$$o_t=\sigma(W_oz_t+b_o),\quad g_t=\tanh(W_gz_t+b_g),$$
$$c_t=f_t\odot c_{t-1}+i_t\odot g_t,\qquad
h_t=o_t\odot\tanh(c_t).$$

各门、候选与状态均为 $H$ 维。forget gate $f_t$ 决定保留旧 cell 的比例;input gate $i_t$ 决定候选 $g_t$ 写入多少;output gate $o_t$ 决定当前 cell 有多少经 tanh 暴露为 $h_t$。门值来自当前输入、旧 hidden 和已学参数,不是教师手动指定的语义开关。初始概念与后续 forget gate 分别可追到 [Hochreiter 与 Schmidhuber,Long Short-Term Memory,1997](https://www.bioinf.jku.at/publications/older/2604.pdf)及 [Gers、Schmidhuber 与 Cummins,Learning to Forget,2000](https://doi.org/10.1162/089976600300015015)。

<span id="read-R21"></span>

### 保留的一次完整门控复算


下面完整展开旧独立二维门控算例使用的参数。取 $h_{t-1}=(0.2,-0.1)$、$e_t=(1,0)$,故 $z_t=(0.2,-0.1,1,0)$。为完整复算,令四个 $W$ 都等于

$$U=\begin{bmatrix}1&0&0.5&0\\0&1&0&0.5\end{bmatrix},\qquad Uz_t=(0.7,-0.1).$$

各偏置分别取 $b_f=(\ln9-0.7,-\ln4+0.1)$、$b_i=(-\ln9-0.7,\ln3+0.1)$、$b_o=(\ln4-0.7,0.1)$、$b_g=(\operatorname{atanh}(0.5)-0.7,-\operatorname{atanh}(0.2)+0.1)$。因此仿射输出及非线性结果为:

| 分支 | 本次仿射输出 | 门/候选向量 |
| --- | --- | --- |
| forget | $(\ln9,-\ln4)$ | $(0.9,0.2)$ |
| input | $(-\ln9,\ln3)$ | $(0.1,0.75)$ |
| output | $(\ln4,0)$ | $(0.8,0.5)$ |
| candidate | $(\operatorname{atanh}(0.5),-\operatorname{atanh}(0.2))$ | $(0.5,-0.2)$ |

参数是为了独立手算指定的,并未训练;改变输入或旧 hidden,门值仍会按上述函数改变。参考解释:V-RNN PDF p107–115,尤其 p112;这里展示通行的 forget-gate 形式,不把它等同于1997年原始论文的每个历史细节。

沿用上表由 $z_t$ 算出的门与候选,给定旧 cell $c_{t-1}=(1,-1)$。先保留旧信息:

$$f_t\odot c_{t-1}=(0.9,0.2)\odot(1,-1)=(0.9,-0.2).$$

再写入候选内容:

$$i_t\odot g_t=(0.1,0.75)\odot(0.5,-0.2)=(0.05,-0.15),$$
$$c_t=(0.9,-0.2)+(0.05,-0.15)=(0.95,-0.35).$$

最后计算本步 hidden:

$$h_t=(0.8,0.5)\odot\tanh(0.95,-0.35)=(0.591826,-0.168188).$$

输入门控制的是“写入多少”,不决定候选的正负。输出门较小也不等于把 cell 擦掉;它限制本步可见的 hidden,cell 仍沿独立通路传下去。

### 多步干预的定义与边界

旧多步门控扩展另固定一个坐标:c₀=1,每步 i=.01、g=0,因此写入项为0,c₂₀=f²⁰。f=.99时为0.8179069376,f=.8时为0.0115292150。所有门值为教学干预,不是模型学到的参数。先观察保留量怎样变化;本节末尾再将这条状态通路与求导路径对上。

### 把保留量与求导路径对上

沿cell直接通路、把门激活固定时,一步偏导贡献为 $\operatorname{diag}(f_t)$,多步为这些因子的乘积。上面的20步干预因此既能看保留量,也能看该路径的梯度。跨度改为100步时,$0.99^{100}\approx0.366$,而 $0.9^{100}\approx2.66\times10^{-5}$,更说明乘积对forget gate的敏感性。

实际门依赖旧hidden,完整总导数还含经过hidden和门网络的其他路径;直接cell路径不等于总导数。LSTM提供可学习的保留与改写结构,不保证总梯度恒为1或任意长记忆。是否用好它仍取决于任务、优化、容量与训练分布。V-RNN PDF p113强调直接通路,p115同时交代限制。

<span id="read-R22"></span>

回到前面两个四事件块的约定:可分别检查cell中是否保留第2条写入的事实,以及hidden/读出头是否把它用于第8条查询。两处干预对应不同故障;上面的门控复算提供了区分它们的起点。

<span id="recurrent-state-and-credit-s08"></span>

## GRU 符号先统一,才比较实现

本讲把z当**写入比例**:`h=(1-z)⊙h_old+z⊙candidate`;Cho2014把z当**保留比例**:`h=z_Cho⊙h_old+(1-z_Cho)⊙candidate`。两者换算为 `z=1-z_Cho`。例如旧值2、候选6,本讲z=.25得到3;原论文要用z_Cho=.75才得到同一数值,不能把.25原样搬过去。

两个门通常由当前输入与旧状态的仿射函数接sigmoid得到:`z=σ(W_z x+U_z h_old+b_z)`、`r=σ(W_r x+U_r h_old+b_r)`,逐特征取0到1的值。这里z采用上面的写入约定。

Cho候选为 `tanh(Wx+U(r⊙h_old))`。PyTorch2.9的GRU采用 `tanh(W_in x+b_in+r⊙(W_hn h_old+b_hn))`,reset在投影后。令h=(1,2)、r=(1,0)、U的两行为(1,1)/(1,-1):投影前reset给(1,1),投影后给(3,0),都是tanh前的值。非对角U使两者一般不同。reset只控制候选中的旧状态通路;即使r=0,最终保留支路仍可能留下旧状态。

门控、双向和堆叠解决不同设计问题。整句命名实体识别可用双向;连续传感流常要求因果;多层把局部模式逐级组合,代价是更多计算与优化难度。选择它们应先问输出何时需要、允许看见哪些输入,再问深度和隐藏宽度。

来源:同版读本第二章;lecture_7物理11–60、91–116连续推演;[Cho2014 v3 §2.3](https://arxiv.org/html/1406.1078v3)、[PyTorch2.9 GRU定义](https://docs.pytorch.org/docs/2.9/generated/torch.nn.GRU.html)。四事件块只规定依赖关系;数值门控与解析梯度是构造核验;LAB01 C的短训练不升级为能力评测。


原课程连续页组:CS224N RNN/LM物理p21–24、p53/56/58;CS231n原文件lecture_7.pdf为RNN与图像条件生成课,页脚April 21, 2025,元数据创建于2026。末页才预告attention;这里不把它登记成Seq2Seq→attention连续页组。


<span id="recurrent-state-and-credit-s09"></span>

## 相邻知识与复核资源

[把预测、训练与评价摊在同一张样本表上](https://codingai-lec05.pages.dev/course/knowledge/objectives-and-evaluation.html) · [2014:先拥有一个可工作的翻译器,再决定改哪里](https://codingai-lec05.pages.dev/course/knowledge/translation-choices-2014.html)

[全部主题](https://codingai-lec05.pages.dev/course/knowledge/index.html) · [关键结果JSON](https://codingai-lec05.pages.dev/course/knowledge/data/learning-paths.json) · [只读诊断源码](https://codingai-lec05.pages.dev/course/knowledge/code/learning_paths.py.read.html) · [Seq2Seq完整实现](https://codingai-lec05.pages.dev/course/knowledge/code/seq2seq.py.read.html) · [视觉机制实现](https://codingai-lec05.pages.dev/course/knowledge/code/mechanisms.py.read.html) · [TinyDecoder与cache实现](https://codingai-lec05.pages.dev/course/knowledge/code/legacy_numpy.py.read.html)