循环神经网络

循环神经网络

这一章主要介绍了循环神经网络(Recurrent neural network, 简称RNN),主要用来处理序列数据,比如一些文字序列或时序数据。对于这类数据,基本的前馈神经网络会对每一个输入的特征都训练一个单独的参数,而不能很好的进行参数的共享,而RNN就可以通过对不同时间点的特征共享参数而更容易的进行训练,泛化效果也更好。上一章CNN也可以实现参数共享,RNN与其不同的地方在于其每一点的输出还依赖于之前的结果。

循环

recurrent也得名于 \(t\) 时刻的状态依赖于 \(t-1\) 时刻的状态。当然,我们可以把该式不断的展开直至可以用对于初始状态 \(s^{(1)}\) 的不断的函数叠加来表示,如图所示,我们可以将计算图展开如下

如果我们对于该系统由外部信号驱动,则可以表示为 \(s^{(t)}=f\left(s^{(t-1)}, x^{(t)} ; \theta\right)\) 。RNN就采取的类似的循环公式,只不过用hidden units来代表状态,即 \(h^{(t)}=f\left(h^{(t-1)}, x^{(t)} ; \theta\right)\) 。同样的,可以将其计算图展开如下,展开图可以有助于理解信息传播方向和梯度的反向传播方向:

我们可以将 \(h^{(t)}\) 看做是之前的输入向量序列 \(\left(x^{(t)}, x^{(t-1)}, \ldots, x^{(1)}\right)\) 的一种有损的表示。根据不同的需要,我们可以控制损失的精度,例如对于一些语言模型,可能只有附近的文字信息比较重要,我们就不需要存储所有 \(t\) 之前的序列信息。

RNN网络结构

了解了这些基本概念,我们就可以构建RNN了,最基本的结构如下图所示

即在每一个时间点都产生输出,并且hidden units之间有循环链接,图中 \(y\) 为该点的真实目标 值, \(L\) 为模型预测的输出值 \(O\) 与真实值 \(y\) 间的损失函数如交叉熵,总的损失为各 \(L^{(t)}\) 之和。由 于该结构hidden units之间有循环链接,计算时我们需要顺序计算,而不能进行并行计算,所以训练过程较为缓慢。而且该模型需要输入与输出序列长度相同。

Teacher forcing

假如我们损失一点模型普适性,去掉hidden units之间的循环链接,而是建立前一时间点真实目标值与当前hidden unit的链接,则当前点hidden unit并不依赖于前一点hidden unit计算结束,则我们可以有效地将训练过程并行化,当然 \(y^{(t-1)}\) 并不能完全代表 \(h^{(t-1)}\) 所包含的所有信息,所以 在提高训练效率的同时降低了一些模型的普适性,这一方法叫做teacher forcing,其计算图可作如下展开:

还有一种常见的结构是将一个向量而不是向量序列作为输入,输出一个序列,这经常用在image caption中,即给定一个图像,我们常常用CNN得到其特征向量,再将这个特征向量作为输入,得到描述该图片的输出文字序列。这种结构如下图所示:

上下文RNN

由于之前基本的RNN结构要求输入与输出同等长度,而实际应用如语音识别、机器翻译等往往输入输出的长度不同,为了解决这一问题我们可以把上述两种结构结合起来,即先用一个RNN将输入序列转化为一个向量,通常是其最终的隐藏态的一个函数,这一过程称作encoder或reader,然后再将这一定长的向量作为输入,利用上图所示结构产生序列输出,这一过程称作decoder或reader,结合起来就是经典的encoder-decoder或称作sequence-to-sequence结构。注意经过这两步,输出和输入序列不再需要满足长度相同的条件,如下图所示 \(n_x\)\(n_y\) 可取不同长度:

c是上下文向量,为Encoder网络的输出,包含了所有输入的信息。通常我们需要c有足够的维度,这样才有足够的信息去描述输入的信息。Decoder则是采用了向量生成序列的网络结构。

LSTM与GRU

一个需要注意的问题是,在RNN中,由于相同的权重矩阵被不断的在hidden state上叠加,梯度会随着循环次数的增加呈指数的衰减或爆炸,造成模型无法有效的学习long-term的相互作用。即我们每次循环可用 \(h^{(t)}=W h^{(t-1)}\) 表示,假设对权重矩阵 \(W\) 可做本征分解 \(W=Q \Lambda Q^T\) , 则 \(h^{(t)}=Q \Lambda^t Q h^{(0)}\) ,为本征值的\(t\)次方的形式,对于本征值小于 1 的方向会衰减至零而本征值 大于1的方向爆炸。为了解决这种长程作用的问题,一系列gated RNN模型被提出,其中比较常用 的是LSTM和GRU。

LSTM(Long short-term memory)基本单元结构如下图所示,在hidden state \(h_t\) 的基础上又添 加了一个新的cell state \(c_t\) ,旨在长程有效的传递信息。同时引入了四个作用不同的gate:

  1. \(f\)代表forget gate,经过sigmoid函数,其大小在 \((0,1]\) 之间,代表了我们会保留之前的cell state的多 少信息。

  2. \(i\)代表input gate,同样的经过sigmoid函数大小在 \((0,1]\) 之间,代表对于这个cell,有哪些值需要更新。

3)\(g\)经过tanh函数,其大小在 \((-1,1)\) 之间,代表了这些需要更新的值得具体的大小,与input gate做元素积则可求出cell state需要update的值。

4)\(o\)代表output gate,即需要将 哪些 \(c_t\) 的值输出到hidden state \(h_t\) 。通过这一结构,在一个单元中,我们可以合理的保存某些前 一个单元携带的长程信息,以及本单元的一些更新信息,而不是简单的权重矩阵的乘积,从而解决 了长程作用的问题。

GRU(gated recurrent unit)可以看做是将LSTM中的forget gate和input gate合并成了一个update gate,即下式中的 \(z_t\) ,同时将cell state也合并到hidden state中。由于该模型相较LSTM更为简化,计算量更小,且最终模型性能类似,所以最近越来越广泛的得到应用。

LSTM与GRU之所以可以获得成功,是由于其forget gate的效果,能够实时地调整过去记忆的获取方式,从而能够更容易从记忆中获得需要的信息量。详细的LSTM和GRU的推导不再给出,可在花书上找到。

基于记忆力的RNN网络

改进的RNN模型,如长短时记忆网络(LSTMs),使长序列训练克服了梯度消失等问题。然而,即使是更高级的模型也有其局限性,研究人员在处理长数据序列时也很难开发出高质量的模型。例如,在机器翻译中,RNN必须找到由几十个单词组成的长输入和输出句子之间的联系。现有的RNN体系结构似乎需要改变和适应,以便更好地处理这些任务。

Attention是结合在RNN中的一种机制,它可以在预测输出序列的某一部分时,将注意力集中在输入序列的某一部分,从而使学习更容易,质量更高。注意机制使其在许多任务中的性能得到提高,使其成为现代RNN网络的一个组成部分。

经典上下文RNN

首先介绍一下传统的RNN结构图,方便我们在之后比较attention RNN与traditional RNN的区别

RNN编码器有一个输入序列\(x_1\), \(x_2\), \(x_3\), \(x_4\)。我们用\(c_1\), \(c_2\), \(c_3\)表示编码器的状态。编码器输出单个输出向量c作为输入传递给解码器。和编码器一样,解码器也是一个单层的RNN,我们用\(s_1\), \(s_2\), \(s_3\)表示解码器的状态,用\(y_1\), \(y_2\), \(y_3\), \(y_4\)表示网络的输出。

这种结构的问题在于解码器需要将整个输入序列\(x_1\), \(x_2\), \(x_3\), \(x_4\)表示为单个向量\(c\),这会导致信息丢失。此外,解码器需要从这个单一向量中解码传递的信息,这本身就是一项复杂的任务。

这种编译码方法的一个潜在问题是,神经网络需要能够将源语句的所有必要信息压缩成一个固定长度的向量。这可能会使神经网络难以处理长句,尤其是那些比训练语料库中的句子长的的长句。

带注意力机制的RNN

注意力模型有一个单层的RNN编码器,同样有4个步骤。我们用\(x_1\), \(x_2\), \(x_3\), \(x_4\)表示编码器的输入向量,用\(h_1\), \(h_2\), \(h_3\), \(h_4\)表示输出向量。

注意力机制位于编码器和解码器之间,其输入是由编码器的输出向量\(h_1\), \(h_2\), \(h_3\), \(h_4\)和解码器的状态\(s_0\), \(s_1\), \(s_2\), \(s_3\)构成,注意力的输出向量序列被称为上下文向量用 \(c_1\), \(c_2\), \(c_3\), \(c_4\)表示。

上下文向量

上下文向量使解码器能够在预测输出时关注输入的某些部分。每个上下文向量是编码器的输出向量\(h_1\), \(h_2\), \(h_3\), \(h_4\) 的加权和,每个向量 \(hi\) 包含整个输入序列信息(因为它在计算时可以得到编码器的状态),这个向量强烈关注第 \(i\) 个输入序列向量的周围部分。向量\(h_1\), \(h_2\), \(h_3\), \(h_4\)\(\alpha_{ij}\) 进行加权,得到输入\(x_j\)对于输出 \(i\) 时刻的 \(y_i\) 的相关程度。

上下文向量 \(c_1\), \(c_2\), \(c_3\), \(c_4\)这样得到:

\[c_i = \sum_{j=1}^{4}\alpha_{ij}h_j \]

注意力权重是通过一个额外的全连接的浅网络来学习的,用fc表示,这就是注意力机制输入的\(s_0\), \(s_1\), \(s_2\), \(s_3\)部分发挥作用的地方。注意力权重的计算方法为:

\[\begin{align} & a_{ij} = \frac{\exp(e_{ij})}{\sum_{k=1}^{4}\exp(e_{ik})}\\ where \ \ \ \ \ \ & e_{ij} = fc(s_{i-1},h_j) \end{align} \]

使用注意力全连接网络和softmax函数学习注意力权值

在时间步\(i\),注意力机制使用\(h_1\), \(h_2\), \(h_3\), \(h_4\)\(s_{i-1}\) 作为输入,它使用fc神经网络和softmax函数计算权重\(\alpha_{i1}\)\(\alpha_{i2}\)\(\alpha_{i3}\)\(\alpha_{i4}\),从而计算上下文向量。相比于传统的上下文RNN,attention机制的RNN在原来的上下文位置引入了一个fc网络,对于decoder RNN的每次输入,由原本的固定上下文变量\(c\),变成了 \(\alpha_{ij}\)\(h_j\)的加权和,其中 \(\alpha_{ij}\)\(s_{i}\)\(h_{j}\) 作为输入,由fc和softmax层输出的结果。

可以看到在上面的图片中,向量的全连接网络使用 [\(s_{i-1}\)\(h_i\)] 作为输入在时间步 \(i\) 。网络有一个全连接层、输出层用\(e_{ij}\)表示,经过softmax函数计算权重的取值范围为[0,1]。

注意,我们对所有对 [\(s_{i-1}\)\(h_1\)], [\(s_{i-1}\)\(h_2\)], [\(s_{i-1}\)\(h_3\)], [\(s_{i-1}\)\(h_4\)]使用相同的全连接网络,这意味着存在一个学习注意力权重的单一网络。

注意力权重\(\alpha_{ij}\)反映的是\(h_j\)对前面的隐藏状态\(s_{i-1}\)在决定下一个状态\(s_i\)和生成\(y_i\)时候的重要性。大的\(\alpha_{ij}\)会导致RNN关注输入\(x_j\)(通过编码器的输出hj来表示),来对\(y_i\)的输出进行预测。

思考:个人认为在此softmax仅仅只是起到归一化的作用,而非是为了输出概率,虽然也可以将attention解释为概率分布,但是需要注意的是,之所以在离散分布的输出层使用softmax是由于我们采用了最大似然估计的损失函数作为优化目标,在这种情况下softmax的exp函数可以和log抵消,从而有效地进行梯度下降。然而在此我们并不是需要输出的分布和log进行抵消,因为这个操作已经在输出 \(y\) 的分布中实现了,所以在此处使用softmax层并不是必须的,同时在此使用softmax层反而可能会造成梯度消失的问题。因此我认为可以使用简单的线性归一化,而非softmax的指数归一化。

利用反向传播对fc网络与编码器、解码器进行训练,将RNN的预测误差项反向传播到解码器,然后通过fc注意力网络,再从解码器反向传播到编码器。注意,由于注意力的权重是使用一个额外的神经网络fc学习的,我们有一组额外的权重来允许这个学习发生,我们用\(W_a\)表示这个权重矩阵。

一个包含4个输入时间步长和4个输出时间步长的RNN,在训练过程中会对以下权重矩阵进行微调。注意注意矩阵的维数4×4,将每个输入连接到每个输出:

这种机制使解码器能够决定输入序列的哪些部分需要注意。通过让解码器具有注意力机制,我们将编码器从必须将输入序列中的所有信息编码为单个向量中解放出来。信息可以传播到\(h_1\), \(h_2\), \(h_3\), \(h_4\) 序列中,解码器可以选择性地检索这些序列。

这种方法与基本编码码器最重要的区别在于,它不试图将整个输入语句编码成一个固定长度的向量。相反,它将输入的句子编码成一个向量序列,并在解码时自适应地选择这些向量的子集。这使得神经翻译模型不必将源句的所有信息(无论其长度)压缩到一个固定长度的向量中。

posted @ 2025-07-31 17:08  sky_darkeen  阅读(14)  评论(0)    收藏  举报