LESSON 17 · 卷 自然语言处理

RNN 循环神经网络

固定窗口看不到更早的词——能不能给网络装上「记忆」?

第 1 站

固定窗口的死角

读这句话,填空:

「小猫没有过马路,因为__太害怕了。」

空里该填「它」——怕的是前面那只小猫。这对你毫不费力,可对上一课的固定窗口模型却是道坎: 「小猫」离空格隔了好几个词。如果模型只看最近 5 个词(「因为__太害怕了」), 它根本瞧不见「小猫」,只能干猜「因为什么太害怕了」,压根不知道主语是猫、是人还是狗。

这就是固定窗口的死角:窗口以外的所有信息,等于不存在。可真实文本里,代词(「它」「他们」「这」)和它指代的对象常常隔着几十个词, 段落之间前后呼应的线索甚至隔着几百个词——窗口再大也兜不住。

固定窗口的毛病是看不到远处。有没有办法让模型「记住」很久之前读过的内容,又不必把每个词都存下来?
第 2 站

给网络一个「记忆向量」

循环神经网络(RNN)的思路正是这样:读每个词时,除了当前这个词,网络还多收一个输入—— 来自上一步的「记忆」,记作 (书上叫「隐藏状态」,我们就叫它记忆向量)。

每读一个词,做两件事:

新记忆 = tanh( W · [当前词向量, 旧记忆] + b )
预测下一个词 = 用新记忆去算

更新公式拆开看其实很朴素:把当前词向量旧记忆拼在一起,过一个线性变换 , 再套一层 tanh,就得到新记忆。就这一步,从句首到句尾反复执行。

这里的 还是第 4、7 课那个 Wx+b;外面的 tanh 就是第 8 课的激活函数(形状像 Sigmoid,但输出在 −1~1 之间)。所以 RNN 没造新零件——它只是把「线性变换 + 激活」接成了一个: 上一步的输出,又喂回来当这一步的输入。

小猫没有马路因为h1h2h3h4h5h6记忆从左向右流动 →读到「小猫」预测「它」用 h6理论上「小猫」的信息一直传到最后
图 17-1RNN 展开图:每个方块是读一个词时做的同一套操作。记忆向量 h 从左到右传递,理论上「小猫」的信息会一直保留到预测「它」的时候。

这个设计最大的好处是不限制句子长度:无论句子多长,每步都只做同一件事——读一个词、更新记忆。 100 个词和 10 个词用的是同一套参数 ,记忆向量 h 始终在手边,随句子推进不断刷新。

第 3 站

手算一遍:记忆怎么一步步更新

公式归公式,我们把它缩小到能口算,亲眼看一遍记忆是怎么流动的。让记忆 就是一个数,专门记「这句话里有没有提到小猫」。更新规则简化成:

这里 0.6 是「上一步记忆能带过来多少」(记忆传递系数), 是当前这个词带来的新信号。 我们让只有「小猫」带来强信号 ,其余的词都和猫无关、。 从 开始,一个词一个词地算:

① 小猫:h = tanh(0.6×0 + 1.5) = tanh(1.5) ≈ 0.90 ← 记忆被「小猫」点亮
② 没有:h = tanh(0.6×0.90 + 0) = tanh(0.54) ≈ 0.50
③ 过 :h = tanh(0.6×0.50 + 0) = tanh(0.30) ≈ 0.29
④ 马路:h = tanh(0.6×0.29 + 0) = tanh(0.17) ≈ 0.17
⑤ 因为:h = tanh(0.6×0.17 + 0) = tanh(0.10) ≈ 0.10

看这串数:0.90 → 0.50 → 0.29 → 0.17 → 0.10。每读一个无关的词,「小猫」的信号都先乘 0.6、再被 tanh 压一下, 一步步矮下去。到第 5 个词「因为」,它只剩峰值的约 11%——好在 5 个词还撑得住, 预测「它」时记忆里多少还残着点猫味。下面这台机器,按「读下一个词」就走一步,自己看这个过程:

读到第 1 / 6 个词
小猫0.91没有马路因为记忆 h每读一个词,旧记忆先 ×0.6,再过 tanh —— 「小猫」的信号一步步变矮
读「小猫」:h ← tanh(0.6×0.00 + 1.50) = 0.91
第 1 步读到「小猫」,记忆冲到 0.91。之后每读一个无关的词,记忆都先乘 0.6 再压一下——到第 5 个词「因为」,「小猫」的信号只剩约 11%5 个词还勉强够用,可要是中间隔了 20 个词,0.6²⁰≈0.00004,信号早就归零——这就是 RNN 记不住远处的根本原因。
互动 17-A一维记忆的现场演算:每点「读下一个词」就执行一次 。蓝条的高度就是当前记忆 h,越往右越矮——「小猫」的信号正被一步步稀释。
第 4 站

局限:记忆随距离消退

上一站那串递减的数字,藏着 RNN 最残酷的毛病。记忆 h 每读一个词就被刷新一次, 而每次刷新都是「旧记忆 × 0.6 + 新词」的混合——也就是说,旧记忆每走一步都被稀释一点。 这就像打电话传话:第一个人说「小猫今天心情不好」,一个传一个, 传到第二十个人,「小猫」多半已经变成「谁?」

把上一站的 0.6 连乘下去,衰减快得吓人。隔 5 个词还剩 , 可隔 20 个词呢?

几乎归零。这就是为什么 RNN 记不住远处的词。

小猫h2h3h4h5h6h7h8h?越往右,「小猫」的信息越淡,直到消失(中间每读一个词都把旧记忆又稀释一次)
图 17-2每刷新一次记忆,旧记忆就被稀释。距离越远的词,残留越少——这叫「记忆淡出」,也是梯度消失的一种表现。
梯度也跟着淡了

从训练的角度看,这事更严重。要让「第 1 步读到的小猫」学会影响「第 20 步预测的它」, 得把梯度从第 20 步一路反向传回第 1 步,每经过一步就要乘一次权重的导数。 只要这个数稍小于 1,连乘 20 次后就几乎变成零——梯度消失,第 1 步的参数根本得不到有效更新。

这两个词你都见过:第 8 课讲 Sigmoid 时埋过「梯度消失」的伏笔,第 13 课讲反向传播时摊开过「链式法则」的连乘。 这一课它俩正面撞上了——RNN 把同一个权重沿时间连乘几十次, 数稍小于 1,远处梯度就被连乘到几乎不存在。这不是代码写错,是数学上的硬限制: 实践中 RNN 确实学不到间隔超过 5~10 个词的依赖。

「每步无差别混合所有信息」是病根。如果记忆能有选择地更新——重要的多留、无关的少写——会不会好很多?
第 5 站

总结

本课核心 · TAKEAWAY

RNN 给网络加了个「记忆向量」h,每读一个词就用 h ← tanh(W·[词, 旧记忆] + b) 刷新一次,理论上能记住任意长的上下文。可实践中,旧记忆每步被稀释, 距离远的词信息几乎消失——梯度也随距离连乘到近乎为零,网络根本学不到远距离依赖。

这一课你亲手推导了

  • 固定窗口的死角:窗口外的词等于不存在,处理不了长距离的代词指代。
  • RNN 的思路:一个记忆向量 h,每读一个词更新一次,把「线性变换+激活」接成环。
  • 手算一遍:h 从 0.90 一路衰减到 0.10——「小猫」信号 5 个词后只剩约 11%。
  • RNN 的局限:记忆随距离淡出(0.6²⁰≈0.00004);梯度随距离消失;学不到远依赖。
小测验

学习小测验

做完这一课,来检测一下核心知识点。选出你的答案后点击「提交」,即可看到正确选项与讲解。

Q1RNN(循环神经网络)相比固定窗口的前馈模型,关键创新是什么?
Q2原始 RNN 在处理长序列时常遇到的核心困难是什么?
NEXT · 第 18 课

LSTM:带阀门的记忆

给记忆加上「忘记阀」和「写入阀」——让网络自己决定记什么、忘什么,把重要信息守住几十步。

0 人点赞,0 人看过