引言
本着“凡我不能创造的,我就不能理解”的思想,本系列文章会基于纯Python以及NumPy从零创建自己的深度学习框架,该框架类似PyTorch能实现自动求导。
要深入理解深度学习,从零开始创建的经验非常重要,从自己可以理解的角度出发,尽量不使用外部完备的框架前提下,实现我们想要的模型。本系列文章的宗旨就是通过这样的过程,让大家切实掌握深度学习底层实现,而不是仅做一个调包侠。
GRU旨在解决RNN 中出现的梯度消失问题。GRU也可以被视为LSTM的变体,启发于LSTM,但更易于实现和计算,且在某些情况能产生同样出色的结果。
GRU
GRU(Gated recurrent unit,门控循环单元)把LSTM的遗忘门和输入门合并成为一个“更新门”,把单元状态和隐藏状态合并,还有其他变化。这样做使得 GRU比标准的LSTM模型更简单。
架构
为了解决RNN的梯度消失问题,GRU使用了更新门和重置门。它们可以控制保留很久之前信息,或删除与未来预测无关的信息。
更新门
我们说GRU把LSTM的遗忘门和输入门合并成为一个更新门,那么我们先来看这个更新门是如何计算的:
门的计算都是这种模式,通过输入和前一时刻隐藏状态
。
更新门控制可以保留多少历史信息(过去的隐藏状态)。
重置门
重置门的计算和更新门类似:
区别仅是权重参数不同。
重置门控制遗忘多少历史信息,或控制还想记住的旧状态的数量。
我们说更新门控制保留历史信息,而重置门控制遗忘历史信息,听起来有点绕。我们继续往下看它们是如何影响最终的输出就明白了。
候选隐藏状态
与LSTM类似,GRU也有一个候选隐藏状态:
看起来就是在RNN中计算隐藏状态时,通过重置门控制是否会遗忘过去的隐藏状态(历史信息)。
重置门和
相乘可以减少旧状态的影响。当重置门接近于
时,我们就得到了普通RNN中的隐藏状态。当重置门接近于
时,那么候选状态是以
作为输入的结果。这样,可以允许隐藏状态丢弃任何后面发现与未来预测无关的信息,从而得到一个更紧密的表示。所以说重置门控制遗忘多少历史信息。
隐藏状态
最后,可以计算当前时刻隐藏状态,此时需要使用更新门来决定从候选隐藏状态
和前一隐藏状态
保留多少信息:
更新门这类似于LSTM的记忆单元,可以让GRU记住过去历史信息,控制新状态中有多少个是旧状态的副本。
每当更新门接近于时,就倾向于保留旧状态,而忽略来自于
的信息,从而有效地跨越时间步。反之,当更新门接近于
时,隐藏状态就会接近候选隐藏状态
。这样可以处理RNN中的梯度消失问题,并更好地捕获时间步距离很长的序列依赖关系。举个例子,如果某个序列的所有时间步的更新门都接近于
,则无论序列的长度如何,在序列起始时间步的旧隐藏状态都可以很容易保留并传递到序列结束。
因为每个隐藏单元(维度)都是独立的重置门和更新门,所以每个隐藏单元将学习捕获到不同时间范围的依赖。这些学习捕获短期依赖的单元倾向于使重置门频繁地激活,但学习长期依赖的单元几乎总是激活更新门。
注意上图的流程画的和公式有点不同,zₜ乘的是候选隐藏状态,不过不影响我们理解。
总之,GRU具有下面两个特征:
- 重置门用于捕获序列中的短期依赖关系
- 更新门用于捕获序列中的长期依赖关系
References
- 从RNN到LSTM再到GRU
- DIVE INTO DEEP LEARNING
- (GRU论文)Learning Phrase Representations using RNN Encoder–Decoder for Statistical Machine Translation