1. 前言

前面我们已经学习了:

  • RNN

  • RNN 从零开始实现

  • RNN 简洁实现

到这里,我们已经知道 RNN 的核心思想:

通过隐藏状态,把过去的信息传到当前时刻。

这让它能够处理序列数据,比如:

  • 文本

  • 时间序列

  • 音频序列

但是,基础 RNN 虽然经典,却有一个非常著名的问题:

它很难有效处理长期依赖。

也就是说,如果当前时刻需要依赖很久以前的信息,普通 RNN 往往学不好。
这背后通常会伴随着:

  • 梯度消失

  • 梯度爆炸

  • 远距离信息难以保留

于是,人们提出了一种更强的循环结构:

GRU(Gated Recurrent Unit,门控循环单元)

GRU 的核心改进就在于:

让模型学会“该记什么、该忘什么、该更新多少”。

这也是它名字里“门控”两个字的由来。


2. 为什么基础 RNN 不够好

先回顾一下基础 RNN 的隐藏状态更新:

H_t = tanh(X_t W_xh + H_{t-1} W_hh + b_h)

这意味着:

  • 当前状态依赖当前输入

  • 也依赖上一时刻隐藏状态

  • 但这个“依赖多少”是统一混在一起更新的

问题就在这里。

2.1 它没有显式控制记忆保留

基础 RNN 并不会明确告诉你:

  • 哪些旧信息应该保留

  • 哪些旧信息应该丢掉

  • 当前输入应该写入多少新信息

所有东西都被一次 tanh 混到一起了。

2.2 长期依赖很难稳定传递

当序列变长时,很多有用信息会逐渐被冲淡,
最后模型很可能只记住最近的部分,而忘掉更久以前的关键内容。

所以我们希望模型具备一种能力:

自己决定信息该如何流动。

GRU 就是在解决这个问题。


3. 什么是 GRU

GRU 的全称是:

Gated Recurrent Unit

中文通常翻译为:

门控循环单元

这里最关键的词是:

门控(Gate)

所谓“门”,可以把它理解成一个开关控制器。
它不会直接存内容,而是决定:

  • 某些信息放行多少

  • 某些信息屏蔽多少

  • 当前应该保留多少旧状态

  • 当前应该写入多少新状态

所以 GRU 和基础 RNN 最本质的区别就在于:

RNN 是直接更新状态,GRU 是带门控地更新状态。


4. GRU 的核心思想是什么

GRU 的核心思想可以概括成一句话:

不是所有历史信息都应该一视同仁,而应该由模型自己学习如何选择性记忆。

为了做到这一点,GRU 引入了两个非常关键的门:

  • 重置门(reset gate)

  • 更新门(update gate)

这两个门共同控制信息流动。


5. 更新门是什么

更新门通常记作:

Z_t

它的作用可以简单理解为:

决定当前隐藏状态中,有多少应该沿用旧状态,有多少应该更新成新内容。

也就是说,它在控制:

  • 旧记忆保留多少

  • 新记忆写入多少

如果更新门值比较大,表示:

  • 更倾向于保留旧状态

如果更新门值比较小,表示:

  • 更倾向于采用新候选状态

所以更新门本质上是在做一种:

旧信息 vs 新信息 的权衡


6. 重置门是什么

重置门通常记作:

R_t

它的作用可以简单理解为:

决定在生成候选隐藏状态时,要不要参考旧状态,以及参考多少。

如果重置门很小,表示:

  • 过去隐藏状态的影响被弱化

  • 模型更偏向忽略过去,重新根据当前输入生成候选状态

如果重置门很大,表示:

  • 历史状态仍然重要

  • 生成候选状态时要更多参考过去信息

所以重置门更偏向控制:

“过去信息在当前候选状态计算里该参与多少”


7. GRU 的三个关键量

在每个时间步,GRU 最核心会算出三个东西:

7.1 更新门

Z_t

控制最终保留多少旧状态。

7.2 重置门

R_t

控制生成候选状态时使用多少旧信息。

7.3 候选隐藏状态

\tilde{H}_t

表示当前时刻新生成的一份“候选记忆”。

然后,真正的隐藏状态 H_t 会由:

  • 旧隐藏状态 H_{t-1}

  • 候选状态 \tilde{H}_t

按更新门加权融合得到。


8. GRU 的公式怎么理解

GRU 的经典公式通常写成:

更新门

Z_t = \sigma(X_t W_xz + H_{t-1} W_hz + b_z)

重置门

R_t = \sigma(X_t W_xr + H_{t-1} W_hr + b_r)

候选隐藏状态

\tilde{H}_t = tanh(X_t W_xh + (R_t \odot H_{t-1}) W_hh + b_h)

最终隐藏状态

H_t = Z_t \odot H_{t-1} + (1 - Z_t) \odot \tilde{H}_t

这里的 \odot 表示按元素乘法。


9. 为什么门要用 sigmoid

更新门和重置门通常都用:

\sigma

也就是 sigmoid 函数。

因为 sigmoid 的输出范围在:

(0, 1)

这非常适合表示“门开多大”。

例如:

  • 接近 0:几乎关闭

  • 接近 1:几乎完全打开

  • 中间值:部分通过

所以 sigmoid 很自然地适合作为门控系数。


10. 候选隐藏状态为什么还要用 tanh

候选隐藏状态:

\tilde{H}_t

通常还是用 tanh

原因和基础 RNN 类似:

  • 让隐藏表示保留非线性能力

  • 把数值压到相对稳定范围

  • 作为“新内容候选值”比较合适

所以你可以把 GRU 理解为:

  • sigmoid 负责决定“放多少”

  • tanh 负责生成“候选内容”


11. 最终隐藏状态公式怎么直观理解

这条公式非常关键:

H_t = Z_t \odot H_{t-1} + (1 - Z_t) \odot \tilde{H}_t

它可以直观理解为:

当前隐藏状态 = 旧状态的一部分 + 新候选状态的一部分

而这两部分的比例,由更新门控制。

如果 Z_t 接近 1

说明更倾向于保留旧状态:

H_t \approx H_{t-1}

如果 Z_t 接近 0

说明更倾向于采用新候选状态:

H_t \approx \tilde{H}_t

所以更新门本质上就是在控制:

记住过去,还是更新现在


12. 重置门为什么有用

重置门体现在候选状态计算里:

(R_t \odot H_{t-1})

这表示:

历史隐藏状态不是原封不动地参与,而是先经过一个门控筛选。

如果重置门很小,那么旧状态在这里被压得很弱,
说明模型认为:

当前候选状态生成时,不需要太依赖以前的信息。

这在某些场景特别有用。
例如序列中出现“话题切换”时,模型就可以更快地丢掉不相关旧信息。

所以重置门的作用很像:

决定当前时刻要不要“重置一下历史包袱”


13. GRU 相比 RNN 好在哪里

这是一节里最重要的问题之一。

13.1 更容易保留长期信息

更新门可以让旧状态直接保留下来,
避免每一步都被新输入猛烈改写。

13.2 更灵活地控制信息流

不是所有信息都无条件写入或丢弃,
而是由模型自己学习控制。

13.3 更缓解梯度消失问题

虽然 GRU 不是万能的,但它比基础 RNN 更容易处理较长依赖。

所以从效果上看,GRU 往往比原始 RNN 更稳定、更实用。


14. GRU 和 RNN 的直观区别

可以用一句很形象的话来概括:

基础 RNN

更像是:

把新旧信息一股脑混在一起更新

GRU

更像是:

先问一下“哪些要留、哪些要忘、哪些要重新算”,再更新

所以 GRU 的优势并不在于“更复杂”本身,
而在于:

它给了模型主动管理记忆的能力


15. GRU 和 LSTM 有什么关系

虽然这一节主要讲 GRU,但可以先给个定位。

GRU 和 LSTM 都属于:

门控循环神经网络

它们共同的目标都是:

  • 解决基础 RNN 长期依赖难的问题

  • 通过门控机制改善记忆能力

区别在于:

  • GRU 结构更简洁

  • LSTM 结构更复杂、门更多

所以你可以先记住:

GRU 是一种更轻量的门控循环单元


16. 为什么说 GRU 是“更简洁的门控循环网络”

因为和后面的 LSTM 相比,GRU:

  • 没有单独的记忆单元 C_t

  • 门的数量更少

  • 状态结构更简单

也就是说,GRU 用更少的门和更少的状态变量,
实现了类似“控制记忆”的效果。

所以在很多任务里,GRU 是一个很好用的折中选择:

  • 比基础 RNN 强

  • 比 LSTM 简洁


17. GRU 在语言模型里怎么理解

如果把 GRU 放回语言模型场景中,它其实在做这样一件事:

当前字符/词来到时,模型会自动判断:前面的上下文还重不重要?当前该保留多少旧信息?又该吸收多少新信息?

例如一句话里:

  • 某些长距离主语信息可能要一直保留

  • 某些局部修饰信息可能过几个词就没那么重要了

GRU 的门控机制,就是在帮助模型自动学习这种“记忆管理”。


18. 李沐这一节最想让你理解什么

这一节最核心的,不是让你马上把所有公式背下来,
而是让你建立一个很清楚的主线:

第一,基础 RNN 的痛点在长期依赖

这就是为什么需要改进。

第二,GRU 的关键是“门控”

不是盲目更新,而是有选择地更新。

第三,更新门和重置门各管一部分

  • 更新门:控制保留旧信息还是采用新信息

  • 重置门:控制旧信息在生成候选状态时参与多少

第四,GRU 是比 RNN 更强的循环单元

后面代码实现时,你会发现它只是把状态更新公式写得更精细了。


19. 本节总结

这一节我们学习了门控循环单元 GRU,核心内容可以总结为以下几点。

19.1 GRU 是为了解决基础 RNN 长期依赖问题而提出的

它通过门控机制更好地控制信息流。

19.2 GRU 有两个核心门

  • 更新门

  • 重置门

19.3 更新门决定保留多少旧状态、接纳多少新状态

它控制最终隐藏状态的更新比例。

19.4 重置门决定历史信息在候选状态计算中参与多少

它控制当前时刻要不要弱化过去影响。

19.5 GRU 比基础 RNN 更灵活,也更容易训练

这是它在很多序列任务中更常用的原因。


20. 学习感悟

GRU 这一节特别重要,因为它让“记忆”这件事第一次变得可控了。

基础 RNN 虽然也有隐藏状态,但那种记忆更像一种“自然流动”;
而 GRU 则进一步让模型学会:

什么时候该记,什么时候该忘,什么时候该更新。

这其实已经非常接近人类处理信息的直觉了。
我们也不是把所有过去信息一视同仁地一直背着,
而是会选择性保留重点、丢弃无关内容。

从这个角度看,GRU 是 RNN 向“更聪明的记忆系统”迈出的关键一步。

Logo

腾讯云面向开发者汇聚海量精品云计算使用和开发经验,营造开放的云计算技术生态圈。

更多推荐