循环神经网络--RNN GRU LSTM 对比分析
一.全连接层、CNN、RNN三种网络结构的分析
- 对于全连接网络:从理论上讲,在理论上全连接网络能够应对各种各样的问题。然而,在面对某些具有特殊需求或复杂度较高的问题时,则会显示出较低的运算效率。因此,在这些情况下我们通常会选择更加高效专用的网络架构。
- 在二维数据如图像的处理方面(Processing),卷积神经网络(CNN)无疑展现出显著的优势。
- 具备明显的时间依赖性(Time dependency)的数据序列(Sequence data),例如时间序列数据(Time series data),当采用循环神经网络(RNN)进行分析时,则能够展现出显著的优势。
1.CNN应用举例

现实生活中这样的数据和应用比比皆是:
说话时的语音处理,可以用序列模型进行语音识别
听的音乐,可以用序列模型进行音乐生成
我们的语言信息,可以用序列模型进行机器翻译、情感分析等等
还有感兴趣的金融市场波动,可以用序列模型进行预测
当然此外还有诸如DNA序列,视频动作识别等等
二.循环神经网络–RNN
1.首先来看看,为什么普通的全连接网络并不适用于序列数据处理。
- 第一,在采用全连接网络时,其输入输出长度被固定,而通常情况下,序列数据具有可变的输入与输出长度。
- 在学习序列关系时,RNN能够分享学到的关系特征,因此节省参数;相比之下,全连接网络无法实现这一点。
2.来看看RNN到底是什么样子
首先假设输入是一个长度为t的序列x(例如:这个序列x由t个单词组成)。
对于RNN单元而言,在时间步t的位置接收来自上一时间步的状态信息s_{t-1}以及当前时刻的输入数据x_t(每个时序单元接收当前时刻t的数据x_t)。
基于这两者的信息计算出当前时刻的状态向量s_t(即h_t),该状态向量会被传递给下一个时序单元使用,并根据状态向量s_t计算出输出\widehat{y}_t(若经过线性变换则为\widehat{o}_t= f(W_{sy}s_t + b_y);若未做线性变换则直接将状态向量作为输出)。(值得注意的是,在Simple RNN模型中不具备长期记忆功能)
状态更新方程如下:
s_{t}=f \left(W_{ss} s_{t-1}+W_{sx} x_{t} + b_s\right)
输出层计算式如下:
\widehat{y}_{t}=f\left(W_{s y} s_{t}+b_{y}\right)
其中,
- W_{ss}表示状态自回归权重矩阵;
- W_{sx}表示输入到状态的权重矩阵;
- b_s, b_y分别表示状态层和输出层的偏置项;
- f(\cdot)表示非线性激活函数。
循环网络之所以被称为循环网络,则是因为其本质特征在于该模型仅包含单个计算单元,在每次迭代中接收一个时间序列数据并完成信息提取与反馈机制

RNN通常有两种表达形式:第一种是以图1左侧为例,在左侧展示了一个单元加上一个循环符号的形式;第二种则是将整个计算过程展开展示。
3.RNN的不同的架构
为了应对具有不同输入输出组合的各种任务,RNN能够划分为不同的架构类别.
- 一对一:
其实就是普通的神经网络。

- 多对一:
在多个时间序列的数据中进行分析并预测结果。例如,在情感分析任务中完成一条评论的情感倾向判断(通过对评论中的每个字的信息进行综合分析后得出最终结论)。这种架构又被称为Acceptor(接受器),它能够接收输入数据序列并生成预测结果。

- 多对多:
多个序列输入映射到多个序列输出。其中一种常见的应用是Tagging(标记),例如给一个句子中的每个词分配词性标签;当输入是一个包含多个词的句子时,系统会将这些标签依次输出到对应的位置上。这种结构也被称为Transducer(变换器),它能够将一段连续输入转换为另一种形式的连续表示。

- 1:N模式:
通过单个输入序列生成多个输出序列。例如,在音乐合成中可实现声音序列生成;在自然语言处理中可训练模型从单个词开始逐步预测句子。这通常被视为一种特定类型的Transducer设计。

- 多对多的情形:
还有一种较为特殊的情况也是多对多的情形,并非Transducer模型而是被称为seq2seq编码器解码器模型的应用场景之一,在处理诸如机器翻译这类的任务时尤为常见。(在前期需要先输入一个输入序列,在后续则会生成多个输出序列)

4.语言模型于序列生成
由于语言固有的顺序性特征,在自然语言处理中RNN因此得以合理应用并获得了较为广泛的应用场景。然而,在这一领域中使用卷积神经网络(CNN)的情况则相对有限。
语言模型
让我们来探讨一下RNN是如何解决自然语言处理中的一个基础而重要的难题:语言模型 。
在之前的讨论中已经提及过,在机器翻译领域Language Model的主要功能是判断一段文字是否为人类所发出。
从科学的角度讲, 语言模型会计算出某句话出现的概率.例如, 使用通顺的人话如"我吃饭."其出现概率通常会高于使用不流畅或难以理解的组合如"吃,饭我"。
因此语言模型的核心任务即为计算单句话的概率。基于概率论的知识体系而言,在计算长度为t的句子的概率时P(\mathbf{w}_{1:t})时P(\mathbf{w}_{1:t})可以被分解为逐步计算前t−1个词\mathbf{w}_{1:t−1}的概率P(\mathbf{w}_{1:t−1})与第t个单词\mathbf{w}_t在已经出现的前t−1个词中的位置关系这一条件相乘的结果;进而具体地,在计算前t−1个词\mathbf{w}_{1:t−2}的具体出现顺序及其联合概率时,则可以继续将其分解成更基础的问题逐步解决。
而用RNN可以很好的模拟这个过程。

我们只需要利用RNN在一般性的语言数据中进行训练,并使它能够记住这些概率即可。
语言模型的用途非常广泛,在机器学习领域中能够协助机器翻译的任务非常常见。然而,在吴教授的研究中提到了一个非传统意义上的应用——序列生成。
序列生成
首先随机输入一个词汇,在 recurrent neural network(RNN)的作用下会预测出下一个词语。其输出是由 softmax 函数计算得出的概率分布列表,在每个位置上都代表了相应词语被选中的可能性大小。随后根据这些概率值将通过采样方法选出一个词语,并将其作为后续时间步的输入数据进行处理。重复上述步骤后就可以得到该语言模型所生成的一段有意义的文字内容了
> 输给模型 出战,不胜必斩!”庞
>
> 生成: 出战,不胜必斩!”庞德有张,而来。二人与言!”二绍急闻将骑去了了,不可护弟如开策一十,各兵当夺。,入荆州,皆口而奉,金密有奉罪...
>
>
>
>
>
>
>
就是看起来好像挺通,但是读完发现完全不知所云。
可以深入学习语言模型:浅谈NLP中条件语言模型(Conditioned Language Models)的生成和评估
5.NLP 的问题
问题探究: 梯度消失/梯度爆炸、过拟合/欠拟合
由于时序长度的延长会导致RNN模型深度的持续提升,在这种情况下不可避免地会遇到深度学习中著名的梯度爆炸与梯度消失两个关键问题。该文详细阐述了这两种现象的具体表现及其对模型训练效率的影响
对于出现梯度爆炸的情况而言,在每次更新之前需要对模型参数进行优化处理以应对可能出现的问题。具体来说,在每次更新之前需要监控梯度值的大小,并对过于庞大的数值进行裁剪(clip)。关于裁剪的具体方式以及效果还需要进一步的研究与验证。
该问题较为棘手,为此特意设计并实现了更为先进的RNN架构以解决该问题
二.循环神经网络–LSTM、GRU
在更强大的RNN架构中,最具代表性的两种门控单元分别是1997年由德国四位著名科学家之一Jürgen Schmidhuber提出的经典LSTM单元以及随后提出的Gated Recurrent Unit(GRU)。在前面讨论的RNN模型中,则较为基础且被统称为简单 recurrent 网络(Simple RNN),亦即埃尔曼(Rummel) RNN.
回到主题,在比较中 GRU 因其简明扼要的特点显得更为易于理解与掌握;因此吴教授最先对此进行了阐释说明。然而基于我的学习经验而言, 我认为相比于 Yoav Goldberg 所著的《Neural Network Methods for Natural Language Processing》一书中对相关知识的阐述过程而言, 前者在教学效果上略显逊色
就拿记忆管理问题来说吧。传统的RNN在每次迭代时会对整个记忆体进行清除和重写,这样一来就无法有效捕捉长期依赖关系(这里为何如此?因为每一步只基于前一状态与当前输入经激活函数生成新状态码)。而有些情况下也需要保持长时记忆以捕获长期关联。比如说像人类脑细胞中存在专门负责长期记忆的信息通道,在接收新信息的过程中能够对局部信息进行相应的更新维护)。就像人类大脑能够存储长久记忆并根据新信息更新局部信息一样。
因此也可以让RNN具备这样的结构,在每个时序阶段依据输入数据决定哪些信息被存储、哪些信息被遗忘,并结合新的输入数据进行更新。

如图所示,在该系统中s是从前一时刻传递过来的状态变量x代表当前时刻的输入信号g则是一个门控机制(Gate mechanism)。在门控机制中数值为1的位置表明这些区域用于保持长期记忆而在其余未被保留的位置则直接使用当前时刻的信息进行更新替代这也正是为何我们关注这两个区域在空间布局上的相似性
这可被视为门控循环神经网络(RNN)中的基础架构。然而,Gated recurrent units(GRU)与长短期记忆网络(LSTM)则对其中的门控机制进行了更为精细的优化设计。鉴于此方式直接实现了全部信息的擦除与更新机制显得过于简单粗略。有时候则希望能够部分保留记忆并相应地进行更新。
其中,
\tilde{c}_t 是当前时间步t处的状态候选值;
\Gamma_u 是更新门控单元;
c_t 则是经过更新后的状态值;
其他参数均为训练得到的权重矩阵或偏置向量;通过这种方式,
模型能够有效地捕捉并传递长期依赖关系,
从而实现了对序列数据的有效建模。
中间引入了一个门机制Γ(希腊字母Gamma),用于执行一个门机制(U代表Update更新),负责长期记忆的状态更新;为了更好地捕捉时间序列信息,在传统的LSTM架构基础上增加了额外的信息融合模块。这一机制通过引入一种经过加工的信息形式\tilde{c}_t来增强模型对时序数据的理解能力;传统的LSTM中新的状态通常是通过门机制由前一状态c_{t-1}和当前输入x_t共同决定的;然而,在这种改进后的模型中,在计算新状态c_t的过程中不仅考虑了前一时刻的状态信息c_{t-1}以及当前时刻的输入特征x_t的影响;同时我们还将其转换为一种经过加工的信息形式\tilde{c}_t;随后再结合这一预处理后的时序特征与原有状态下沿用下来的细胞状态c_{t-1}共同作用来生成最终的新细胞状态c_t
那么完整的GRU架构是怎样的呢?让我们深入探讨一下它的组成部分与工作原理。对于GRU模型而言,在面对输入信息x_t时不仅具备长期记忆能力而且引入了额外的处理机制以提升模型性能具体来说它仅包含两个门控机制r和z这两个控制变量共同决定了信息的状态更新过程。在计算过程中我们首先通过门控机制z来获取当前时间步的信息更新候选状态\tilde{s}_{t}随后再利用门控机制r来决定如何整合新的候选状态与上一个时间步的状态s_{t-1}最终得到新的状态s_t。这个过程不仅实现了对短期记忆的有效捕捉还通过引入复杂的非线性变换增强了模型的记忆深度与表达能力
相比于GRU而言,LSTM相对更为复杂,其具体的数学表达式如下所示
其中,c代表长期记忆单元,h代表短期记忆单元
具体而言,c能够根据每个时序输入的信息动态更新自身状态
如图所示,c会在轴线上不断向下传递信息

而h则是在每个时序中识别需要识别的短期记忆信息。这也正是为何LSTM得名的原因:Long Short Term Memory(长短期记忆)。
同样地,在我们之前所述,在GRU架构中如我们之前所述,通过操作c和h来实现更新的过程。而在LSTM模型中存在三个关键控制机制:输入门i,遗忘门f以及输出门o.这些控制单元的功能是利用激活函数来决定如何调整神经状态.按照名称划分,输入机制负责决定哪些新信息值得被接收并整合到当前状态,遗忘机制则负责判断哪些长期记忆应当被暂时遗忘,最终的输出机制则会筛选出当前长期记忆中最值得提取的部分作为短期记忆以供后续使用.
接下来从直观的角度理解GRU和LSTM如何能够避免梯度消失的问题,并如图所示。

我们可以直观地观察到,在LSTM网络结构中,长期记忆单元c在整个序列长度上实现了连续传递,在更新机制作用下才会对长期记忆单元进行数值调整。而由于门控机制采用的是sigmoid函数特性,在此基础之上能够实现对信息的有效保持(?)
关于LSTM与GRU谁更优的问题,在个人经验而言目前在许多问题上仍倾向于采用经典的LSTM模型。然而随着GRU结构更为简洁且运算量相对较少等优势的存在在许多问题上已有越来越多的人开始尝试应用它。(是否可以把 LSTM 和 GRU 这类能够抑制梯度消失现象的技术移植到其他同样面临梯度消失风险的模型中?)
最近LSTM还出了一个挺火的Nested LSTM(嵌套LSTM),有机会可以写一写。
2.增强技巧:双向与加深
在之前提到的一些RNN系列中, 不仅仅局限于单一方向以及单层结构, 还可以对其进行扩展。例如, 将一维变为二维的方式, 通过反向输入另一个RNN单元, 然后将其结果与正向处理后的输出相连接即可完成这一过程。基于其能够充分利用前后信息的优势, 双向RNN通常能展现出更为优异的表现。(进一步来实验实现)

还有就是增加RNN的纵向深度 ,多添加几层,增加复杂度。

参考:
Coursera DeepLearning.ai Sequence Model
神经网络方法在自然语言处理中的应用(或实现)由Yoav Goldberg著
基于LSTM的语言模型
神经网络训练中的梯度消失与梯度爆炸
作者坂本龙一拥有著作权。链接https://www.jianshu.com/p/a6fac09028e4来自简书
