动手学深度学习——门控循环单元(GRU)
前面我们已经学习了:RNNRNN 从零开始实现RNN 简洁实现通过隐藏状态,把过去的信息传到当前时刻。这让它能够处理序列数据,比如:文本时间序列音频序列它很难有效处理长期依赖。也就是说,如果当前时刻需要依赖很久以前的信息,普通 RNN 往往学不好。这背后通常会伴随着:梯度消失梯度爆炸远距离信息难以保留GRU(Gated Recurrent Unit,门控循环单元)让模型学会“该记什么、该忘什么、该
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 向“更聪明的记忆系统”迈出的关键一步。
更多推荐
所有评论(0)