长短期记忆网络(LSTM)和门控循环单元(GRU)算法详解

引言

传统循环神经网络在处理长序列时面临梯度消失或爆炸问题。梯度消失是指在训练过程中,误差反向传播时,梯度随着时间步数的增加而指数级衰减。梯度爆炸则正好相反,这会导致模型难以学习到当前时刻和距离较远的时刻之间的依赖关系。梯度消失问题的原因如下:

假设有一个简单的RNN模型,其隐藏状态的计算如下:

$$
\boldsymbol{h}_t=\tanh \left(\boldsymbol{W} * \boldsymbol{h}_{t-1}+\boldsymbol{U} * \boldsymbol{x}_t+b\right)
$$

其中, \(\boldsymbol{h}_t\) 是当前时间步 \(t\) 的隐藏状态, \(\boldsymbol{h}_{t-1}\) 是上一个时间步 \(t-1\) 的隐藏状态, \(\boldsymbol{x}_t\) 是当前时间步 \(t\) 的输入, \(\boldsymbol{W}\) 和 \(\boldsymbol{U}\) 分别是隐藏状态和输入的权重矩阵, \(b\) 是偏置项。

在训练过程中, 需要通过误差反向传播来更新权重矩阵 \(\boldsymbol{W}\) 和 \(\boldsymbol{U}\) 。为了计算 \(t\) 时刻关于 \(\boldsymbol{h}_{t-1}\) 的梯度, 我们需要计算以下偏导数:
$$
\partial \boldsymbol{h}_t / \partial \boldsymbol{h}_{t-1}=\partial\left(\tanh \left(\boldsymbol{W} * \boldsymbol{h}_{t-1}+\boldsymbol{U} * \boldsymbol{x}_t+b\right)\right) / \partial \boldsymbol{h}_{t-1}
$$

根据链式法则, 有:
$$
\partial \boldsymbol{h}_t / \partial \boldsymbol{h}_{t-1}=\left(1-\boldsymbol{h}_t^2\right) * \boldsymbol{W}
$$

其中 \(\left(1-\boldsymbol{h}_t^2\right)\) 是 tanh 激活函数的导数。请注意, 导数的值在- 1 和 1 之间, 因为 \(\tanh\) 激活函数的输出范围是 \((-1,1)\) 。当进行反向传播时, 需要计算 \(T\) 时刻的损失函数 \(L\) 关于 \(\boldsymbol{h}_{t-1}\) 的梯度:
$$
\partial L / \partial \boldsymbol{h}_{t-1}=\left(\partial L / \partial \boldsymbol{h}_T\right) *\left(\partial \boldsymbol{h}_T / \partial \boldsymbol{h}_{T-1}\right) * \ldots *\left(\partial \boldsymbol{h}_{t+1} / \partial \boldsymbol{h}_t\right) *\left(\partial \boldsymbol{h}_t / \partial \boldsymbol{h}_{t-1}\right)
$$

可以看到, 梯度是关于每一时间步的偏导数的连乘积。由于每个偏导数都包含 \(\tanh\) 激活函数的导数项 \(\left(1-\boldsymbol{h}_t^2\right)\), 当时间步数增加时, 这些小于 1 的值会被反复相乘, 导致梯度指数级衰减。这就是梯度消失问题的主要原因。反之, 如果大于 1 的值被反复相乘, 也可能出现梯度爆炸的情况。

梯度消失问题使得RNN在学习长距离依赖关系时变得非常困难,因为较早的时间步长的信息在反向传播过程中被丢失。为了解决这个问题,学者们提出了一些改进的RNN结构,长短期记忆网络和门控循环单元就是其中的代表。

长短期记忆网络(LSTM)

相对于传统的循环神经网络,长短期记忆网络具有更强的记忆和长期依赖性建模能力。它与GRU都采用类似的门机制。通过一系列门(输入门、遗忘门和输出门)来控制信息的流动,并使用单元状态来存储和传递信息。这些门允许网络选择性地从输入中获取信息、遗忘不重要的信息并决定什么信息传递到下一层。由于其出色的性能和实用性,LSTM已成为深度学习中最流行的神经网络架构之一。

在标准的RNN中,循环结构如图4-6所示。

图片[1]-长短期记忆网络(LSTM)和门控循环单元(GRU)算法详解-点头深度学习网站
图4-6 RNN

循环神经网络在每个时间步 \(t\) 上接收一个输入向量 \(\boldsymbol{x}_t\), 并更新其隐藏状态 \(\boldsymbol{h}_t \circ \mathrm{RNN}\) 的计算过程可以表示为:
$$
\boldsymbol{h}_t=f\left(\boldsymbol{W}_h *\left[\boldsymbol{h}_{t-1}, \boldsymbol{x}_t\right]+b_h\right)
$$

其中, \(\boldsymbol{W}_h\) 和 \(b_h\) 分别是隐藏层的权重矩阵和偏置项, \(f\) 是激活函数, 一般是 tanh。这里, \(\left[\boldsymbol{h}_{(t-1)}, \boldsymbol{x}_t\right]\) 表示将上一时刻的隐藏状态和当前时刻的输入向量拼接而成的向量。
LSTM 的结构与之类似, 但是每个循环结构中具有四层网络, 如图 4-7 所示。

图片[2]-长短期记忆网络(LSTM)和门控循环单元(GRU)算法详解-点头深度学习网站

4-7 LSTM Block

LSTM 在每个时间步 \(t\) 上接收一个输入向量 \(\boldsymbol{x}_t\), 更新其细胞状态 \(\boldsymbol{C}_t\) 和隐藏状态 \(\boldsymbol{h}_t\) 。其中,细胞状态(cell state)是 LSTM 的新概念, 它类似于传送带, 是 LSTM 的关键, 直接贯穿整个模型, \(\boldsymbol{C}_t\) 在传递中只有一些少量的线性交互, 使得信息在上面传递很容易, 这对远距离的信息更好的传递到当前计算时刻有很大帮助。也就是长短期记忆网络名字中对“长期”概念的一种实现。

在 LSTM 的计算过程中, 第一步决定我们会从上一时刻的隐藏状态中丢弃(忘记)什么信息。如图, 其中 \(\sigma\) 被称作遗忘门 (forget gate), 本质上是一个带有 Sigmoid 函数的神经网络层, 通过读取 \(\boldsymbol{h}_{t-1}\) 和 \(\boldsymbol{x}_t\), 输出一个在 0 到 1 之间的数值给到细胞状态 \(\boldsymbol{C}_{t-1}\) 。通过相乘的操作来决定保留多少 \(\boldsymbol{C}_{t-1}\) 中的信息, 1 表示保留全部信息, 0 表示遗忘全部信息。公式表示如下:
$$
f_t=\sigma\left(\boldsymbol{W}_f *\left[\boldsymbol{h}_{t-1}, \boldsymbol{x}_t\right]+b_f\right)
$$

图片[3]-长短期记忆网络(LSTM)和门控循环单元(GRU)算法详解-点头深度学习网站
图4-8 遗忘门

第二步决定会从当前时刻的输入信息中, 选择什么信息进行处理, 如图4-9。其中 \(\sigma\) 被称作输入门(input gate), 本质上也是一个带有 Sigmoid 函数的神经网络层, 通过读取 \(\boldsymbol{h}_{t-1}\) 和 \(\boldsymbol{x}_t\),输出一个在 0 到 1 之间的数值 \(\boldsymbol{i}_t\), 公式表示如下:
$$
\boldsymbol{i}_t=\sigma\left(\boldsymbol{W}_i \cdot\left[\boldsymbol{h}_{t-1}, \boldsymbol{x}_t\right]+b_i\right)
$$

图片[4]-长短期记忆网络(LSTM)和门控循环单元(GRU)算法详解-点头深度学习网站
图4-9 输入门

第三步, 使用 \(\tanh\) 激活函数创建一个新的候选细胞状态 \(\tilde{\boldsymbol{C}}_t\), 如图4-10所示。本质上是一个带有 \(\tanh\) 函数的神经网络层, 通过读取 \(\boldsymbol{h}_{t-1}\) 和 \(\boldsymbol{x}_t\), 输出 \(\tilde{\boldsymbol{C}}_t\), 这个 \(\tilde{\boldsymbol{C}}_t\) 可以一定程度上代表 \(\left[\boldsymbol{h}_{t-1}, \boldsymbol{x}_t\right]\), 即代表输入信息, 公式表示如下:
$$
\tilde{\boldsymbol{C}}_t=\tanh \left(\boldsymbol{W}_C \cdot\left[\boldsymbol{h}_{t-1}, \boldsymbol{x}_t\right]+b_C\right)
$$

图片[5]-长短期记忆网络(LSTM)和门控循环单元(GRU)算法详解-点头深度学习网站
图4-10 候选细胞状态

最后一步, 决定着当前时刻隐藏状态的输出结果, 如图4-11所示。其中 \(\sigma\) 被称作输出门 (forget gate), 本质上还是一个带有 Sigmoid 函数的神经网络层, 它的计算结果决定着当前时刻的输出结果有多少比例能进入到下一时刻。具体来说, 输出门的计算结果, 将与更新后的且经过激活函数 \(\tanh\) 映射后的细胞状态 \(\boldsymbol{C}_t\) 相乘, 作为当前时刻隐藏状态 \(\boldsymbol{h}_t\) 的输出结果。公式表示如下:
$$
\begin{gathered}
\boldsymbol{o}_t=\sigma\left(\boldsymbol{W}_o *\left[\boldsymbol{h}_{t-1}, \boldsymbol{x}_t\right]+b_o\right) \\
\boldsymbol{h}_t=\boldsymbol{o}_t \odot \tanh \left(\boldsymbol{C}_t\right)
\end{gathered}
$$

图片[6]-长短期记忆网络(LSTM)和门控循环单元(GRU)算法详解-点头深度学习网站
图4-11 输出门

至此,我们已经完成了一个时间步的LSTM计算过程。整个序列数据的处理过程就是将上述计算过程在各个时间步重复进行。

总结一下,LSTM(Long Short-Term Memory)网络可以优化梯度传播不稳定的问题,主要是因为它们的设计允许信息在多个时间步长上有效地流动,而不受梯度消失或爆炸的影响。这得益于LSTM的几个关键特性:

  1. 门控机制:LSTM单元包含遗忘门、输入门和输出门。这些门控制信息的流入、保留和流出,使得网络可以学习何时“记住”或“忘记”某些信息。这种选择性记忆有助于维持长期依赖,减少梯度消失的问题。
  2. 恒定误差传播:在LSTM的内部结构中,存在一种称为“细胞状态”的线性路径,其中的误差可以较为平滑地回流,几乎不受干扰。这意味着在训练过程中,梯度可以稳定地通过网络的多个时间步传播,减少了梯度爆炸或消失的风险。
  3. 自适应调节:由于门控结构,LSTM可以在训练过程中学习自适应地调整门的开关程度,从而有效处理不同时间尺度的信息。

因此,通过这些机制,LSTM能够较好地处理序列数据中的长期依赖关系,并在许多时间序列相关的任务中表现出色,如语言建模和时间序列预测。

门控循环单元(GRU)

门控循环单元(Gated Recurrent Unit,GRU)是一种改进的循环神经网络结构,用于解决传统RNN在处理长序列时面临的梯度消失和梯度爆炸问题。GRU通过引入门控机制来调整信息在序列中的传递程度,从而实现对长距离依赖关系的更好捕捉。

GRU的核心思想是引入两个门控单元,更新门(update gate)和重置门(reset gate)。这两个门控单元可以学习在每个时间步如何调整输入信息和上一个时间步的隐藏状态信息的重要程度,某种程度上可以看作有选择性的记忆当前时刻的输入和上一时刻的隐藏状态。从而使得网络能够更有效地捕捉长距离依赖关系。

具体来说,更新门负责确定有多少上一个时间步的隐藏状态信息应该被保留到当前时间步。更新门的计算公式如下:

$$
\boldsymbol{z}_t=\operatorname{sigmoid}\left(\boldsymbol{W}_z * \boldsymbol{x}_t+\boldsymbol{U}_z * \boldsymbol{h}_{t-1}+b_z\right)
$$

其中, \(\boldsymbol{x}_t\) 是当前时间步的输入, \(\boldsymbol{h}_{t-1}\) 是上一个时间步的隐藏状态, \(\boldsymbol{W}_z 、 \boldsymbol{U}_z\) 和 \(b_z\) 分别是更新门的权重矩阵和偏置。在GRU中,Sigmoid激活函数起着至关重要的作用,其将输出值限制在0和1之间,从而控制信息的保留与遗忘。GRU本质上保留了传统RNN的基本架构,但增加了通过Sigmoid激活函数控制的更新门和重置门。由于Sigmoid函数将输入映射到一个[0,1]的区间内,这个输出值便可以解释为信息的重要程度。具体来说,0代表不保留输入信息,而1则代表完全保留。通过这种方式,更新门学习到的参数可以帮助模型确定保留哪些信息,以及在何种程度上保留,以便更有效地进行序列信息的建模。

重置门负责确定在计算新的隐藏状态时,有多少上一个时间步的隐藏状态信息应该被保留。重置门的计算公式如下:

$$
\boldsymbol{r}_t=\operatorname{sigmoid}\left(\boldsymbol{W}_r * \boldsymbol{x}_t+\boldsymbol{U}_r * \boldsymbol{h}_{t-1}+b_r\right)
$$

重置门的组成和更新门是一样的, 它们各自维护更新自己的权重矩阵。其中 \(\boldsymbol{W}_r 、 \boldsymbol{U}_r\)和 \(b_r\) 分别是重置门的权重矩阵和偏置。输出 \(\boldsymbol{r}_t\) 的维度与隐藏状态 \(\boldsymbol{h}_{t-1}\) 的维度是一致的。候选隐藏状态也是 GRU 中的新概念, 它表示如果允许重置门调整上一个时间步的隐藏状态信息,当前时间步的隐藏状态会是什么样的,计算公式如下:
$$
\boldsymbol{h}_t^{\prime}=\tanh \left(\boldsymbol{W} * \boldsymbol{x}_t+\boldsymbol{U} *\left(\boldsymbol{r}_t \odot \boldsymbol{h}_{t-1}\right)+b\right)
$$

其中, \(\boldsymbol{W} 、 \boldsymbol{U}\) 和 \(b\) 分别是权重矩阵和偏置, \(\odot\) 表示逐元素相乘, 这是一个信息重要程度重分配的过程。通过重置门调整的隐藏状态信息与当前输入信息相结合,然后应用tanh激活函数得到候选隐藏状态。

计算新的隐藏状态:根据更新门的输出,确定在新的隐藏状态中保留多少旧的隐藏状态信息,以及候选隐藏状态的信息,计算公式如下:

$$
\boldsymbol{h}_t=\left(1-\boldsymbol{z}_t\right) \odot \boldsymbol{h}_{t-1}+\boldsymbol{z}_t \odot \boldsymbol{h}_t^{\prime}
$$

其中, \(\left(1-z_t\right)\) 和 \(z_t\) 分别表示保留多少上一个时间步隐藏状态的信息和当前时间步候选状态的信息。这些权重的和为 1, 因为它们都受 Sigmoid 激活函数的限制。通过将两部分加权求和, 得到当前时间步的新隐藏状态。

总之,门控循环单元通过引入更新门和重置门对信息在序列中的重要程度进行学习。这是很符合直觉的,因为在文本数据中,每个字词在一句话中的重要程度确实是不一样的。这种有选择性的记忆方式使得GRU能够更有效地捕捉文本间长距离依赖关系,并减轻梯度消失问题。

LSTM和GRU的区别与联系

LSTM和GRU都是RNN的变体,它们都试图解决传统RNN在处理长序列数据时遇到的梯度消失或梯度爆炸问题。LSTM和GRU通过引入门控机制来改进传统的RNN结构,使得它们能够捕捉长序列数据中的长期依赖关系。下面我们将详细解释它们的区别和联系。

最大的区别是结构差异,具体来说,LSTM的基本单元由一个细胞状态和三个门组成:输入门、遗忘门和输出门。而GRU的基本单元结构更为简洁,它只包含两个门:更新门和重置门。同时,GRU将LSTM中的细胞状态与隐藏状态合并为一个状态。

其次的差别在参数量上,由于GRU结构较简洁,其参数数量相对较少。这使得GRU在某些情况下训练速度较快,并且对内存需求较低。然而,这也可能意味着GRU在某些任务上的表现可能不如LSTM,特别是在需要捕捉更复杂长期依赖关系的任务上。

两者的联系也很明显,尽管LSTM和GRU在结构和计算过程上有所不同,但它们都试图通过门控机制来改进传统的RNN结构。这种门控机制允许网络有选择地更新状态信息,从而使得它们能够捕捉长序列数据中的长期依赖关系。这使得LSTM和GRU在很多序列处理任务中,如自然语言处理、语音识别和时间序列预测等领域具有较好的表现。

另一个联系是它们都可以能够缓解RNN的梯度问题。在传统的RNN中,每个时间步的隐藏状态 \(\boldsymbol{h}_t\) 都是由上一时间步的隐藏状态 \(\boldsymbol{h}_{t-1}\) 和当前时间步的输入 \(\boldsymbol{x}_t\) 计算得出:
$$
\boldsymbol{h}_t=f\left(\boldsymbol{W}_h \boldsymbol{h}_{t-1}+\boldsymbol{W}_x \boldsymbol{x}_t\right)
$$

由于每个时间步的计算都要乘以同一个权重矩阵 \(\boldsymbol{W}_h\), 这会导致梯度在反向传播过程中指数级衰减或爆炸。具体来说, 由于每个时间步的梯度都要乘以 \(\boldsymbol{W}_h\) 的转置, 而且 \(\boldsymbol{W}_h\) 是通过随机初始化得到的,因此每个时间步的梯度的大小和方向都是不同的,这导致梯度的方差随着时间步长的增加而指数级增长或减小,从而使得梯度在反向传播过程中衰减或爆炸。

为了解决这个问题,LSTM和GRU引入了门机制,用于选择性地控制信息的流动,从而降低梯度的大小。

以 LSTM 为例, 它引入了一个单元状态 \(\boldsymbol{C}_t\) 和三个门: 输入门 \(\left(\boldsymbol{i}_t\right)\) 、遗忘门 \(\left(\boldsymbol{f}_t\right)\)和输出门 \(\left(o_t\right)\) 。每个门都有一个对应的权重矩阵, 而且每个门的输出都是由 Sigmoid 函数变换得到的。这样, 对于每个时间步, 只有与门对应的权重矩阵需要更新, 而其他的权重矩阵都保持不变, 从而减少了梯度的大小变化。
具体来说, LSTM 的计算公式如下:

$$
\begin{gathered}
\boldsymbol{i}_t=\sigma\left(\boldsymbol{W}_i\left[\boldsymbol{h}_{t-1}, \boldsymbol{x}_t\right]\right) \\
\boldsymbol{f}_t=\sigma\left(\boldsymbol{W}_f\left[\boldsymbol{h}_{t-1}, \boldsymbol{x}_t\right]\right) \\
\boldsymbol{o}_t=\sigma\left(\boldsymbol{W}_o\left[\boldsymbol{h}_{t-1}, \boldsymbol{x}_t\right]\right) \\
\tilde{\boldsymbol{C}}_t=\tanh \left(\boldsymbol{W}_c\left[\boldsymbol{h}_{t-1}, \boldsymbol{x}_t\right]\right) \\
\boldsymbol{C}_t=\boldsymbol{f}_t \odot \boldsymbol{C}_{t-1}+\boldsymbol{i}_t \odot \tilde{\boldsymbol{C}}_t \\
\boldsymbol{h}_t=\boldsymbol{o}_t \odot \tanh \left(\boldsymbol{C}_t\right)
\end{gathered}
$$

其中, \(\left[\boldsymbol{h}_{t-1}, \boldsymbol{x}_t\right]\) 表示将上一时间步的隐藏状态和当前时间步的输入拼接在一起。 \(\boldsymbol{i}_t 、 \boldsymbol{f}_t\) 和 \(\boldsymbol{o}_t\)分别表示输入门、遗忘门和输出门的输出。 \(\tilde{\boldsymbol{C}}_t\) 表示候选单元状态。 \(\boldsymbol{C}_t\) 表示当前单元状态,可以通过遗忘门控制遗忘过去的信息,并通过输入门选择性地接收新信息。 \(\boldsymbol{h}_t\) 表示当前时间步的隐藏状态,是输出门和当前单元状态的乘积。由于输入门、遗忘门和输出门都是由Sigmoid函数变换得到的,它们的取值范围在0和1之间,因此可以有效地控制信息的流动和梯度的传递。因为在计算梯度时,它们可以充当一个缩放因子,帮助控制梯度的大小。具体来说,如果门函数的输出值接近于0或1,那么梯度就会相应地缩小或放大,从而更好地传递梯度。这个特点可以帮助缓解梯度消失和梯度爆炸问题,从而提高模型的性能。

类似的, GRU 也引入了门机制, 它包括一个重置门 \(\boldsymbol{r}_t\) 和一个更新门 \(\boldsymbol{z}_t\), 以及一个候选隐藏状态 \(\tilde{\boldsymbol{h}}_t\) 和当前隐藏状态 \(\boldsymbol{h}_t\) 。GRU 的计算公式如下:
$$
\begin{aligned}
& \boldsymbol{r}_t=\sigma\left(\boldsymbol{W}_r\left[\boldsymbol{h}_{t-1}, \boldsymbol{x}_t\right]\right) \\
& \boldsymbol{z}_t=\sigma\left(\boldsymbol{W}_z\left[\boldsymbol{h}_{t-1}, \boldsymbol{x}_t\right]\right) \\
& \tilde{\boldsymbol{h}}_t=\tanh \left(\boldsymbol{W}_h\left[\boldsymbol{r}_t \odot \boldsymbol{h}_{t-1}, \boldsymbol{x}_t\right]\right) \\
& \boldsymbol{h}_t=\left(1-\boldsymbol{z}_t\right) \odot \boldsymbol{h}_{t-1}+\boldsymbol{z}_t \odot \tilde{\boldsymbol{h}}_t
\end{aligned}
$$

其中, \(\left[\boldsymbol{h}_{t-1}, \boldsymbol{x}_t\right]\) 表示将上一时间步的隐藏状态和当前时间步的输入拼接在一起。 \(\boldsymbol{r}_t\) 和 \(\boldsymbol{z}_t\) 分别表示重置门和更新门的输出, 都是由 Sigmoid 函数变换得到的。 \(\tilde{\boldsymbol{h}}_t\) 表示候选隐藏状态, 是由 \(\tanh\) 函数变换得到的。 \(\boldsymbol{h}_t\) 表示当前时间步的隐藏状态, 可以通过更新门选择性地接收新信息,并通过重置门控制遗忘过去的信息。

总之, LSTM 和 GRU 通过引入门机制来控制信息的流动, 从而缓解了 RNN 的梯度问题, 这使得它们在处理长序列数据时更有效。

© 版权声明
THE END
喜欢就支持一下吧
点赞9 分享
评论 抢沙发

请登录后发表评论

    暂无评论内容