RNN+RL

  • 深度学习

从一个 RNN+RL 记忆实验里,我纠正的那些认知

这是一篇给自己回顾用的学习博客。起因是一个"用 RNN 做强化学习记忆任务"的长周期实验(跑了很多天、很多轮)。过程中我对策略梯度、on-policy 采样、RNN/长程记忆、模型崩塌等一堆概念的理解发生了好几次颠覆。这里把背景、我学到的东西、以及实验结论尽量准确完整地记下来。


0. 背景:任务、模型、算法

任务(MiniGrid-Memory):一个 13×13 的网格世界。智能体开局在一条长走廊的随机位置;走廊最左端(x=1)放着一个线索物体(钥匙或球),最右端(x=11)是两个出口(上/下)。智能体必须:看到线索 → 穿过长走廊 → 走到与线索匹配的那个出口。因为走廊很长、线索和出口不可能同时出现在视野里,所以这是个典型的长时程记忆 + 稀疏奖励问题——必须真正"记住"线索。

奖励:走到正确出口得 R = 1 − 0.9·(步数/上限)(越快分越高),否则 0。

判断"真记忆"的关键指标:不能只看成功率。我用了一个"打乱线索"的对照——把开局线索随机替换、但不改正确出口:

  • 如果模型真用了记忆 → 打乱后成功率掉到 ~0.5(scrambled_success≈0.5);
  • 如果模型只是投机/固定走一边 → 打乱后成功率不变。 所以判据是:成功率高 且 scrambled≈0.5

模型与算法:RNN 类记忆(gru/lstm/dgate/residual/注意力/NTM 等) + REINFORCE / Actor-Critic(带 value baseline) + 自适应熵正则 + 梯度裁剪 + 按 batch 更新,训练时按策略分布采样、评估时贪心。

这个背景很重要,因为下面很多认知转变,都是被"这个具体任务里发生的现象"逼出来的。


1. 八条核心认知

下面每条都是我自己的总结(润色过、更流畅准确),后面用"补充"跟上更深一层的技术说明。

1.1 baseline 不影响模型分布,只降方差

baseline 不影响模型的输出分布,只影响方差。我以前一直没想通,是因为我总盯着单局轨迹看:这一局如果 reward 正好等于 baseline,梯度就成了 0,看起来 baseline 明显改变了训练。但真正的策略梯度,是对当前策略下所有可能轨迹求期望再取均值的——baseline 对当前这一局有影响,但它同样作用在别的轨迹上,按下葫芦浮起瓢、此消彼长,平均下来恰好抵消,所以只改方差、不改期望方向。

由此我意识到一件事:on-policy 训练在收集数据时,不能只盯着每条轨迹的得分,还得关心采样够不够多、分布正不正。因为梯度公式里除了 reward,轨迹出现的概率也是关键一项——这个概率其实就是"当前这批采样里这条轨迹出现的频率",我们是在拿它去近似真实分布;采样太少太偏,这个近似就和真实差很远,影响很大。我以前特别喜欢只采一条轨迹就更新,现在看来问题很大。

补充:数学上 baseline 项的期望 E[b·∇logπ] = b·E[∇logπ] = b·0 = 0(因为 Σπ·∇logπ = ∇1 = 0)。一个最小例子(两动作 A/B,π=0.5/0.5,R(A)=1,R(B)=0):无 baseline 时两样本梯度是 {+0.5, 0}(均值 0.25、方差大),有 baseline(0.5) 时是 {+0.25, +0.25}(均值仍 0.25、方差 0)。另外一个小订正:只采一条轨迹不是"把概率算错了",而是无偏但方差极大——结论一样,必须采够、用 batch。

1.2 策略过于确定后,关键信息会因"没梯度"而漂移消失、模型突然坍塌

模型长期训练时,如果策略变得过于确定,就会出问题:网络对关键信息只在乎"有没有",对"强弱"不敏感;而在真正需要用关键信息决策的地方,又长期得不到梯度(既没有正向、也没有负向)去强化它。于是关键信息对应的权重在噪声里慢慢漂移,最终漂没了,模型就突然坍塌失效。解决思路是别让关键信息在网络里消失:要么在 loss 里加一项关键信息的损失(cue-aux),要么在关键信息还在决策中时,让模型偶尔失败一下来周期性地强化它(比如加熵正则)。

补充:这条被实验完全证实(第 4 节)。“只在乎有无、不在乎强弱"很关键——因为动作是 argmax、是阈值化的读数:关键信息的强度可以渐进变弱而输出一直不变,直到跨过阈值突然翻转,所以表现为"突然"崩。除了 cue-aux 和熵正则,实验里"KL 锚到一个好参考策略"也能防。

1.3 RNN 就是共享权重的极深网络,门控/残差本质类似 ResNet

RNN 其实就是一个非常深、且各层共享权重的网络,所以 ResNet 那套残差短路也能用在 RNN 上。LSTM/GRU 的长程记忆本质和 ResNet 类似——都是把"旧状态"直接带到下一步、再和新信息汇合,只不过 LSTM/GRU 还要用门控去决定新旧信息各占多少比例。这也引出了 RNN 和普通深网的一个关键区别:RNN 每一步都注入新信息,但模型容量是固定的,所以它必须对旧信息做取舍来腾地方装新信息。这正是"残差用在 RNN 里,和用在普通深网里效果不一样"的根本原因。

补充:两点更准确的说明。① LSTM/GRU 的"比例"是乘法门控(遗忘门),比 ResNet 的纯加法更强——它是可选择地保留,而不只是把旧的加上去。② “残差能用在 RNN 上"要打个折扣:它确实能改善梯度传播,但在本实验这种长程记忆任务里,纯残差 RNN(resrnn)并没能保住记忆——原因恰恰是你说的"每步注入新信息、容量固定、必须取舍"带来的加性干扰(详见第 3 节)。所以这条的落点应是:残差救不了长程记忆。

1.4 熵正则 = 在 loss 里加一个熵项

熵正则就是在 loss 里加一个熵项,作用是让模型的输出概率别太偏,永远保留一点探索的余地。

补充:实现是 loss = 策略损失 − 熵系数·熵(所以是"奖励熵大”)。本实验还发现它是防坍塌的关键保护因素:保持探索,关键信息在决策处就能持续拿到梯度、不漂移消失;反过来把熵退火到 0,等于亲手制造坍塌。

1.5 时序记忆的三种方式:RNN 隐状态 / NTM / 注意力

RNN 隐状态、NTM、注意力都可以作为时序模型的记忆方式,区别在于:

  • RNN 隐状态:会随序列被一层层地处理、不断改写,是"边走边把信息揉进同一个固定向量”;
  • NTM:一块容量固定的外部记忆矩阵,好处是它是原始记忆——不会像隐状态那样被逐层揉掉;
  • 注意力:容量不固定,强行保留每一帧信息,好处是信息不丢失

(我记得实验里注意力好像没能稳定成功,当时没想明白为什么——现在搞清楚了:不是它存不下,而是纯 RL 把"用它的回路"练崩了。)

补充:一处订正——NTM 不只是"把每个隐状态被动加权累加",它有可学习的读/写头 + 按内容寻址(还带擦除),会主动决定写到哪、读哪,更像一台带可读写内存的小计算机。而注意力其实是训成功的(succ=1 且 scrambled≈0.5),它反而成了"保留≠会用"的最佳证据(第 4 节)。

1.6 训练是"相对导航",不是"绝对导航"

无论是强化学习还是普通神经网络,每一次训练都是在上一次训练的结果之上进行的——一步错,很可能步步错。所以哪怕训练数据完全符合真实分布(数据都是在真实环境里跑出来的,reward 一定能反映动作的好坏),能不能练出来仍然是不确定的。

我以前的想法是:数据都是对的、又能一直采、神经网络本来就会自动提取特征,那不管模型和训练过程怎样,只要一直训,总能收敛到最优。现在看这是错的,强化学习尤其如此,因为下一步是在上一步的策略上采样、再训练,不确定性被极大地放大了。

打个比方:我原来以为训练像大海里朝灯塔航行的船——每步歪歪扭扭,但总方向不会错,最终一定能到灯塔附近;而真实情况更像惯性导航——当前位置只是相对于上一步算出来的,一旦上一步偏了,这一步大概率也跟着偏。就像惯性导航本来指向正北,一阵风浪把船连同导航基准都带偏了一点,此后即使导航本身没坏,方向也永远错了,时间越久偏差越大;何况一路上还会反复遇到这种扰动,能不能到目的地就很随机了。一句话:我预期的是绝对导航,但训练其实是相对导航

也正因为是相对导航,降方差就格外重要——它减少每一步的随机抖动。降方差就像换一个更稳的惯性导航;或者换个类比:方差大(比如 batchsize 很小)时,每一步方向都很随机,像一个醉汉回家,很容易某一步走岔、之后越偏越远;而降方差就是让他每一步都大致朝着家的方向走,虽然未必精准,但总方向会比方差大时靠谱得多。

补充:这条抓住的是训练的路径依赖 / 非凸本质(RL 里数据分布还由当前策略决定,所以更严重)。它正好和 1.1 接上了:baseline 不改方向、只降方差,而"降方差"在相对导航里意义重大(压住累积漂移)。现实中,PPO 的 KL/信任域、梯度裁剪、稳定的 baseline,本质都是在主动管住这种漂移

1.7 A/B 90%/10% 例子——我的三次认知反转

设模型对两个动作输出 A=90%、B=10%,且两者奖励一样。

  • 认知①(错):A 采得多 → 拿的 reward 多 → A 概率进一步升高,慢慢涨到 100%。
  • 认知②(修正):梯度是 reward · ∇logπ(a),我之前只看了 reward、漏了后面那项。其实 A 采得多但每次的 ∇logπ 很小,B 采得少但一旦采到梯度就很大,两者恰好平衡;所以理论上不管训多久,A 都稳定保持 90%、B 保持 10%(奖励相同 → 没有对比 → 分布不变)。
  • 认知③(再修正):但由于采样有偏、加上第 6 条说的路径依赖(每次训练都在上一次基础上),最终概率其实是不确定的、会随机漂移

概括起来,我对这个知识点的认识经历了三次反转:“采样多就会强化该动作” → “正常采样训练不改变分布” → “训练会让分布往不确定性漂移”。这三步基本就是我这次学习的主线。

补充:更精确一点——∇logπ(a) 对高概率动作小、对低概率动作大(所以 A 采得多但每次推得少、B 采得少但一次推得多,期望上平衡)。认知③(实际会往不确定性漂)正是 1.2 与第 4 节"用进废退坍塌"的微观来源。

1.8 Actor-Critic:critic 只是个"更聪明的 baseline",它降方差、但不替你改方向

顺着第 1.1 条我又想通了 Actor-Critic:AC 里的 critic,本质就是在训练一个 baseline 网络。既然第 1.1 条说 baseline 不影响模型的输出分布、只降方差,那训练这个 critic 到底在优化什么?答案是——还是降方差。critic 学得越准,adv = 回报 − V(s) 这个基准就越贴合,梯度估计的方差就越小;但它对策略梯度的方向、对最终收敛到的策略分布,期望上是没有影响的。

这一条纠正了我一个曾经很执着的想法:我以前想,能不能训练一个 actor + 一个 critic,而这个 critic 不一定是神经网络、也可以是一条我随时能改的规则,这样我不就能随时"拨动"模型、让它往我想要的方向发展了吗?现在看,如果这个"critic"是当 baseline 用的((回报 − baseline)·logπ),那根本做不到——因为 baseline 被设计成不影响方向,我怎么调它,模型的最优解都不变。

想真正掰动方向,那一项就必须对动作有梯度:得写成 ext_adv = func(动作, 状态…) 而不是只跟状态有关。而这一步的本质,其实就是在偷偷修改环境给每个动作的奖励(reward shaping)——它确实能把模型往我定义的方向推,但代价是:我解的已经不是原来那个任务了,而是"原奖励 + 我这项"的新任务,规则若有偏,模型就忠实地跟着跑偏。

顺带把 bootstrapping 也理清了:它不是在 loss 里"多加一项",而是替换掉回报 G_t 的未来尾巴——把"真实采样到底的未来回报"换成 critic 的估值 V(s')(如 G_t ≈ r_t + γV(s_{t+1}))。这是拿方差换偏差,会实打实地改变梯度方向,和"减 baseline"完全是两码事。

补充:三者一句话区分——

  • baseline − V(s_t):同一状态下所有动作减同一个数 → 跨动作求和抵消 → 只降方差、不给任何"往哪走"的指引。训练 critic = 把这个基准学准 = 进一步降方差。
  • bootstrapping r + γV(s_{t+1}):替换回报尾巴 → 改方向(方差↓、偏差↑,critic 不准会引入系统偏差)。
  • reward shaping + func(a,s):动作相关的加项 → 改最优策略(在解新任务)。唯一的例外是势函数塑形 γΦ(s') − Φ(s):因为沿轨迹望远镜式两两抵消,累加只剩起点/终点两项,所以最优策略不变,却能把稀疏的终点大奖拆成一路的"面包屑"、给出密集的方向指引来加速收敛。它和 baseline 都不改最优,区别在于 baseline 完全不指路、势函数则每步都指路

2. 实验主要结论(简版)

  • 固定长走廊(S13)从零几乎不可学:稀疏奖励下"点火(探索)"+ 长程梯度消失双重障碍。
  • 能学成的路径:行为克隆(BC)暖启动 + 合适架构(注意力) + 合适学习率;或加 cue-aux 辅助信号。学成的标志:成功率高 scrambled≈0.5。
  • 学成后会"用进废退"地崩(第 1.2、第 4 节)——这是本实验最重要、也最反直觉的发现。
  • 防崩/救回的有效手段(实验验证):①自适应熵正则(维持探索)②KL 锚到一个"好参考策略"(信任域式,防漂移,还能把已崩模型拉回)③cue-aux 常驻辅助信号 ④自我模仿(SIL)。治标手段:低学习率(拖慢漂移)。无效/有害:裸 ε-greedy(有偏梯度,反而加速崩塌)。

3. 为什么残差在 RNN 里救不了长程记忆(深挖)

我一度以为"既然 ResNet 能靠残差堆几百层还不丢梯度,那给 RNN 加残差(resrnn: h_t = h_{t-1} + f)也该能保住长程记忆"。实验和推导都说不行,原因有三层:

  1. 同一个权重反复相乘:RNN 沿时间的梯度是 ∏_t (I + D_t·W_hh)W_hh 每步是同一个矩阵 → 近似于矩阵的 T 次幂 → 谱半径被抬到 T 次方 → 指数爆炸或消失。ResNet 每层是不同且独立的矩阵,不会对同一套特征值反复求幂。
  2. 没有归一化压小残差支路:ResNet 的残差支路有 BatchNorm + 初始化技巧,让它一开始接近恒等(I 项主导);resrnn 的 W_hh 没被压小,扰动项不是小量。
  3. 最深的一点——每步注入新输入的加性干扰:ResNet 是一股表示朝单一输出逐层精炼,中间不注入新的无关信息;RNN 每步都往同一个 h加进一帧新观测(走廊里全是墙)。第 5 步写进去的钥匙,会被第 6~60 步的加性噪声淹没。恒等短路能保"梯度传回早期",但保不住"某个具体信息不被后续输入干扰"

延伸:扩容(更大隐藏层)也治不了。问题不是"仓库不够大",而是"没有门禁"——写入是无差别的,钥匙那个角落迟早被路过的信息覆盖。真正的解是选择性保留(门控)可寻址/不压缩的记忆(NTM/注意力)


4. “保留 ≠ 会用”,以及崩塌的根因(本实验的核心)

4.1 保留不等于会用

注意力能把每一帧无损保留,钥匙信息在决策点一定取得到;但纯 RL 仍然不收敛/会崩。这说明**“把信息保留到最后"只是必要条件,不是充分条件**。真正的墙是**“学会用它”——这是一个信用分配 + 稀疏奖励下探索**的问题:

  • 岔路口"用钥匙 vs 瞎猜"的两种策略,在每一局的奖励里得分一样(赢了都是那个步数分),奖励分不清你是靠钥匙赢的还是蒙对的;只有长期成功率能区分,而单局梯度看不到"率”。
  • 一个"无视钥匙、固定走一边"的策略就有 50% 成功率,这是一个又平又宽的平台:往正确解挪一小步不会立刻涨分(要同时做到"对准钥匙"+“映射对出口"才涨),所以平台上几乎没有梯度指向正确解。

4.2 崩塌的因果链(实验确证,可复现、可双向验证)

用"从同一个收敛模型 warm-start、每次只改一个因素"的因果消融,得到:

崩塌 ⟺ 策略熵(探索)趋于 0,且权重仍在更新。

  • 关熵 + 正常 lr → 稳定复现崩塌(多种子一致,~20 万局);
  • 冻结(lr=0)不崩;关熵但极小 lr 不崩 → 说明是权重漂移在作祟,lr 决定快慢;
  • 熵充足(≥0.5)永不崩熵是保护因素(这推翻了我一开始"熵太强才会把模型带乱"的错误猜想)。

机制:策略确定化后,维持"用钥匙"回路的梯度 ∝ (a−p)(探索量)趋于 0 → 回路无人维持 → 在噪声(critic 梯度、有限批方差、步数惩罚等,Adam 还会把微小梯度放大到 ~lr 步长)下无回正力地随机游走 → 越过决策边界后骤然崩塌 → 落入"确定性固定走一个出口"的深度饱和吸收态

可逆性:从已崩模型重新注入探索(把熵开回来) → 能恢复。关掉探索就崩、开回探索就好——这个双向可控,是"探索(熵)就是因果变量"的最强证据。

4.3 和监督学习的根本区别

  • 监督学习梯度 ∝ (预测 − 标签):标签永远在场,输出一漂偏立刻被纠正 → 自我稳定,不会得这病
  • RL 策略梯度 ∝ (R − b)·(a − p):多了 (a−p) 探索因子;策略一确定化、不再采到"错动作”,就拿不到纠正信号。探索在 RL 里,扮演了监督学习中"标签"免费提供的纠错信号。

4.4 一个反直觉的细节:为什么崩塌"突然"发生

真正连续、平滑的信号是 weight_drift(权重漂移量,单调上升);而成功率、“线索可解码性"都是阈值化/饱和的读数——底层的钥匙"强度"其实在渐进减弱,但 argmax 动作和分类准确率在跨过阈值前看起来没变、跨过后骤变。所以"渐进漂移 → 突然崩塌"并不矛盾。


5. 我犯过 / 纠结过的知识性错误清单(备忘)

把散落在各处的踩坑点集中列一下,方便以后自查:

策略梯度 / 探索

  • 以为 baseline 会改变策略(只看单轨迹)——其实只降方差(1.1)。
  • 以为 ε-greedy 探索的偏差"影响很小、可接受”——实测它有偏(μ≠π 却按 π 算梯度、需 π/μ 校正)且在长轨迹里主动有害(制造的失败被一锅端摊到好动作上)。
  • 以为"采样多的动作会被强化到 100%"——忽略了 ∇logπ 那一项(1.7)。
  • 以为能拿一个 critic / 规则当 baseline 去"随时拨动"模型方向——baseline 不改方向(1.8),要改方向得让那项对动作有梯度(=reward shaping,在解新任务)。
  • 把 bootstrapping 误当成"loss 里多加一项"——它其实是用 V(s') 替换回报的未来尾巴(1.8)。

RNN / 记忆架构

  • 以为残差在 RNN 里也能像 ResNet 那样保长程记忆(第 3 节)。
  • 以为"隐藏层越大记忆越好"——瓶颈是干扰/访问控制,不是容量。
  • 把 NTM 误记成"被动加权累加"——其实是可学习读写头 + 按内容寻址。
  • 误记"注意力没训成功"——其实成功了,只是纯 RL 会崩。

崩塌机制

  • 以为"零件齐了(会导航 + 能保留钥匙 + 50%蒙对)就会自动组合收敛"——不会,断在"保留→使用"。
  • 以为"把信息保留到最后就够了"——保留≠会用(第 4.1)。
  • 以为"失败会自我修复、把错误动作压下去"——在 50% 平台上赢输行为一样、梯度相消,回正力需要"关键信息已在状态里"。
  • 在玩具里把 ∂输出/∂x_k(=k,k=0 时输入失效)和 ∂loss/∂k(权重仍可训)搞混,误以为"梯度永久死掉、不可逆"。
  • 以为崩塌"只是时间问题、都会自愈"——深饱和坍缩不会自愈,需外部去饱和。
  • 以为"熵正则太强会把模型带崩"——恰恰相反,熵是保护因素。

方法论

  • 以为"数据对 + 一直训 → 必然收敛"——训练是路径依赖的相对导航(1.6)。
  • 短观察窗就下"已成功"的结论——崩塌前有很长的"表面正常期",判稳必须跨过危险区并监控 scrambled / cue_visit / weight_drift
  • 单个 seed 去比较超参(如不同熵系数)——n=1 时终点由路径依赖主导,不可比。
  • (工程反面教训)把"熵目标退火到 0"当技巧——它会亲手制造崩塌。

6. 一句话总览

我这一路,是从"只看单局奖励、以为数据对就能练出来、以为把信息存下来就会用“的监督学习直觉,迁移到理解 on-policy 的分布与方差本质、训练的路径依赖不确定性,以及"保留≠使用、探索维持记忆、饱和即崩且需外力去饱和” 这一整套强化学习 + 时序记忆世界观的过程。

核心的三句话记忆点:

  1. 策略梯度是对分布求期望——baseline 只降方差不改方向;采样要够多够全。
  2. RNN 是共享权重的极深网 + 每步注入新输入——固定容量必须取舍,残差救不了,需门控/可寻址记忆;但**“能保留"不等于"会用”**。
  3. RL 训练是相对导航、路径依赖——策略过度确定 → 探索归零 → 维持关键信息的梯度归零 → 权重漂移 → 突然崩塌;**保持探索(熵)/常驻信号(cue-aux)/信任域(KL 锚)**是解药。