Recurrent Neural Network(递归神经网络)

Long-Term Dependencies(长期依赖)

普通的RNN网络结构,每一步的状态state都依赖于前一步,那么从理论上来说,它应该是能够记住很多时间步之前见过的信息的,但事实上,想要学到这样的信息是十分困难的,最主要的原因在于梯度消失问题(vanishing gradient problem)导致学习的困难。
下面借助线性代数中的特征值与特征向量相关的知识来解释一下梯度消失问题。
我们对RNN做出如下假设:
1.没有偏置(bias)
2. 无激活函数(activation function)
3. 假设input x=h0
4. 关联各阶段的权重矩阵W,shape=NN,借助特征值lambda和特征向量v,我们有如下表达式
在这里插入图片描述
5.最后我们假设h0可以表示为矩阵W的N个特征向量的和
在这里插入图片描述
接下来,我们来看一下,这个神经网络的第t步的表达式,通过不断地迭代,我们可以得到如下的式子
在这里插入图片描述
根据我们对h0做出的简单假设,将h0替换为特征向量的线性和的形式,我们可以对W^t
h0做出如下替换
在这里插入图片描述
后续每一步的替换完全依赖于特征向量/特征值的初始表达式,每次从前面抽出一个W,放到后面特征向量v之前,再将Wv替换lambda*v,不断重复,就能得到上图最下面的这个式子。当t足够大时,我们可以观察到RNN的第t层的output主要有最大的特征值lambda_i决定(注意指数位置的t)。

下面我们来重点看一下梯度g。我们的目标是通过反向传播更新权重W。具体的表达式为
在这里插入图片描述
我们直接来看最右边的等式中的三个部分,其中第一部分为第一层的ouput对于W的偏导值,因为根据我们非常简单的假设,这个值=h0,就是我们的input,不需要多说什么。最后一个部分就是Loss function对于输出层的ht的梯度,这部分更多地取决于我们选用什么loss,这里也再探讨了。我们重点来看一下中间的部分,就是ht对h1的偏导值。根据chain rule,我们可以将它展开为如下形式
在这里插入图片描述
根据我们这个世界上最简单RNN的假设,我们有 ht对ht-1的偏导=W,依次类推,最终我们可以得到这个部分的值为
在这里插入图片描述
把它替换到我们的梯度表达式中得到
在这里插入图片描述
这时我们可以将中间这个式子中的前两部分再次替换为lambda^(t-1)*v的的线性和的形式。这时我们会发现,梯度的值也会主要由N个特征值中最大的那个来决定,因为我们有一个很大的t作为次幂。假设他为lambda_l,当lambda_l小于1时,那么我们的梯度经过非常大的t次幂作用后就会非常接近于0,也就是所谓的梯度消失,那么在这种情况下,我们的模型训练就会严重受阻,权重无法更新以及收敛,在这种情况下,RNN往往是无法训练出好的结果的,这也是为什么普通的RNN模型无法对于那些long-term dependency的问题进行建模的原因。当然也有可能lambda_l>1,那么经过长时间的积累,梯度会非常大,产生梯度爆炸,这对于训练过程中参数的收敛也是极为不利的。所以总结来说,对于那些long-term dependency的问题,普通RNN的应用十分受限。

LSTM(Long Short-term Memory)

相较于传统的RNN网络结构,LSTM在每个neural cell内部实现了更精细的构造。最核心的就是memory cell的存在,或者叫做state,被单独拿出来用来存储关于序列过去的信息。在序列向前推进的过程中,每一步,state都会通过一个叫forget gate的装置实现self-loop,具体来说,每一步,forget gate会输出一个介于0到1的值(比如通过sigmoid激活函数),如果输出为1,则表示在这一步中,前面保留的信息会被完整的留下来,而如果输出0,表示清空之前的memory,除此之外,每一步的input会进过一个叫input gate的装置来确定被新存储到state的内容,也就是说,如果forget gate保持始终open的情况,那么之前的所有信息都会被保留,同时如果每一步input gate 都输出一个接近于1的值,那么每一步的input的信息都会被完整add到state中,从而实现了长时记忆。
除了input gate 和 forget gate 之外,在LSTM cell中还有一个 output gate 用来控制每一步的output,总结来说,在每一步中,我们的input x_t不仅仅直接作为input进入input gate,而是通过四组不同的参数形成四组输入z,z_i, z_f, z_o, 分别传给 input ,input gate,forget gate 以及 output gate,也因此LSTM训练需要的参数量会是一般单一神经网络的4倍。下面这张图取自李宏毅老师的RNN课件,清晰地呈现了LSTM的结构。
在这里插入图片描述
我们再来具体看一下state的更新以及forget gate的更新。
在这里插入图片描述
首先第一部分就是self-loop,使用forget gate来确定对上一步state s_t-1的保留情况。第二部分则是用input gate 来控制input x_t以及上一步的输出h_t-1对state的更新影响。然后我们再来具体看一下forget gate的更新过程,如下图。
在这里插入图片描述
在每一步中,forget gate决定之前保留的信息在这一步的保留情况。具体来说,它受到前一步的output h_t-1以及本轮的input x_t的影响,模型通过训练来自主确定什么时候需要继续保留之前的信息,什么时候需要format之前的信息。

关于LSTM的variants,其中一个比较有名的叫做Gated Recurrent Unit(GRU),相较于LSTM,它的主要变化有两点,首先,它将 forget gate和 input gate合并在一起,称为update gate, 同时它将memory cell也就是state和hidden output合并为一起,因此相较于LSTM它的结构更简单,参数量更少,训练更快。而且从准确率上来说,GRU并不比LSTM差。除此之外,LSTM还有许多其他的结构变化形式,有人曾经对不同的variants做了比较,但是结果发现,大多取得类似的结果。

如果大家想对LSTM的内部结构以及它的一些variants有更深入的理解,可以阅读一下这篇文章,我觉得写得十分详细,在这里我就不再复述了。
Understanding LSTM Network
http://colah.github.io/posts/2015-08-Understanding-LSTMs/

Augmented RNN—Attention Mechanism

我们知道RNN可以用来做多项任务,其中一个非常著名的模型叫做Sequence to Sequence model。简单来说,我们使用两个RNN,其中一个将sentence转化为一个向量,称它为context。用来represent这个sentence,我们把这个RNN称为encoder。然后我们把context作为输入给到另外一个RNN,用来生成另外的sentence,这个RNN被称为decoder。一个非常经典的Seq2Seq的应用场景就是language translation。

我们再来思考一个细节,假设在一个translation的任务中,为了在生成目标语句的后续阶段不要忘记context的内容,我们会想要在生成目标语句的每一个词时,都将context重复作为input。但是这么做其实会有一些问题,比方说我们的翻译语句可能很长,因此context可能包含了大量的信息(整个初始语句),但是我们在翻译某个词时,最需要的可能是与这个词最相关的几个词,比如在原句中对应位置或者位置靠近的几个词,那么如果我们使用整个context作为input,冗余的信息可能会干扰到我们的翻译生成。除此之外,原始的Seq2Seq只使用encoder的hidden layer的最后一个位置的输出,显然这样导致信息的利用率不够高。

为了优化这些问题,attention mechanism(注意力机制)被提出了。它的基本点在于在生成句子的每一个部分时,都将注意力放在原句中最相关的部分。那么具体该怎么设计结构呢?

attention机制充分使用encoder中hidden layer的所有状态ht,t=1,2,3…len(sentence)。每一个ht都包含encoder的对应每一部分输入的信息。然后对于decoder,我们在得到每一部分的输出时,输入使用的不再是完整的context,而是在encoder中不同ht的加权和。下面这张图可以清晰地表述这一过程。
在这里插入图片描述
对于decoder中hidden layer的每一个state,我们使用不同的input c1,c2,c3。而具体生成这些不同输入的方式就是对encoder中的不同state的不同加权和。比如说,上述图中从中文‘早上好’到英文‘good morning’的过程中,生成 ‘good’ 这个词依赖的hidden layer state的生成的过程可能会需要w13的很大的权重,w11和w12的权重可能相对较小。那么我们是如何生成这些权重的呢?方法就是去计算decoder hidden layer的每一个状态zt与encoder中hidden layer中的所有状态ht的similarity,也就是匹配程度。怎么理解这个匹配程度的计算呢?比如在decoder中,状态z0与encoder中的h1,h2的相似程度很高,那么也就意味这它们在两种语言中的语义的相似程度很高,那么我在预测z1这个z0相邻位置的词时,使用一个主要通过h1,h2加权得到的向量作为input,得到的准确率也会相对更高一些。那么说了半天,还是没有给出计算相似度的具体公式?其实最直接的方法当然是直接计算两个vector的dot product,当然还有其他方法。其实,这里可以自由的设计,并没有一个固定的最优选择。当我们得到zt与h1,2,3,…的一系列匹配值时,其实我们还可以做一下softmax,使得它们的和为1,这样更符合权重的概念,但是这一步并不是必须的。

对于decoder的每一个state,我们不断重复上面的过程,得到不同的input,产生不同的output并最终形成句子。很多时候,我们会对不同状态时attention的情况感兴趣,通过绘制相应的网格图,可以看到在语句的每一个部分,关注的原句的部分在哪里。

参考:
李宏毅机器学习https://www.bilibili.com/video/BV1JE411g7XF?p=51
Attention and Augmented Recurrent Neural Networks https://distill.pub/2016/augmented-rnns/#attentional-interfaces
https://zhuanlan.zhihu.com/p/51383402

扫描二维码关注公众号,回复: 12389762 查看本文章

猜你喜欢

转载自blog.csdn.net/weixin_44607838/article/details/109695593