上一期,我们主要讲解了人工智能算法系列的卷积神经网络。这一期,我们将从RNN结构、RNN使用场景RNN的训练方法以及改进的RNN模型四个部分对循环神经网络(RNN)进行阐述。
本文约2400字,建议阅读时间8分钟
普通的深度神经网络智能单独地处理一个个的输入,前一个输入和后一个输入之间是完全没有关系的。然而,在某些场景之中这是不够的,比如当我们在理解一句话的意思时,孤立地理解这句话的每个词没有意义,因为一个句子中前一个单词对于当前单词的词性预测是有很大影响的,比如预测“苹果”时,如果前面的词是动词“吃”,那么“苹果”作为名词的概率就会远远大于动词,这样一来,我们就需要处理这些词连接起来的整个序列,而RNN算法就能够做到处理序列信息。
RNN结构
RNN和传统的深度神经网络一样,由输入层、隐藏层和输出层组成,示意图如下:
图一 RNN结构图

资料来源: CSDN
RNN包含输入单元,输入集标记为{x0,x1,…xt,xt+1,…},而输出单元的输出集则被标记为{y0,y1,…,yt,yt+1,…}。RNN的隐藏单元输出集标记为{s0,s1,…,st,st+1,…}。这些隐藏单元完成了最主要的工作。在图中,有一条单向流动的信息流是从输入单元到达隐藏单元的,与此同时另一条单向流动的信息流从隐藏单元到达输出单元。在某些情况下,RNN会打破后者的限制,引导信息从输出单元返回隐藏单元,这被称为“Back Projections”,并且隐藏层的输入还包括上一隐藏层的状态,即隐藏层内的节点可以自连也可以互连。上图将RNN进行展开成一个全神经网络。例如,对一个包含5个单词的语句,那么展开的网络便是一个五层的神经网络,每一层代表一个单词。对于该网络的计算过程如下:xt表示第t,t=1,2,3…步(step)的输入。比如,x1为第二个词的one-hot向量(根据上图,x0为第一个词);st为隐藏层的第t步的状态,它是网络的记忆单元。st根据当前输入层的输出与上一步隐藏层的状态进行计算。st=f(Uxt+Wst−1),其中f一般是非线性的激活函数,如ReLU,在计算s0时,即第一个单词的隐藏层状态,需要用到s−1,但是其并不存在,在现实中一般置为0向量;Ot是第t步的输出。我们可以认为隐藏层状态st是网络的记忆单元,st包含了前面所有步的隐藏层状态。而输出层的输出ot只与当前步的st有关。这便是RNN的主要结构。此外,在传统神经网络中,每一个网络层的参数是不共享的。而在RNN中,每输入一步,每一层各自都共享参数U,V,W。其反映着RNN中的每一步都在做相同的事,只是输入不同,因此大大地降低了网络中需要学习的参数。
RNN使用场景
RNN在实践中被证明对NLP是非常成功的。如词向量表达、语句合法性检查、词性标注等。下面对RNN的几种常用使用场景做介绍。
(1)机器翻译
机器翻译是将一种源语言语句变成意思相同的另一种源语言语句,如将英语语句变成同样意思的中文语句。机器翻译需要将源语言语句序列输入后,才进行输出,即输出第一个单词时,便需要从完整的输入序列中进行获取。
(2)语音识别
语音识别是指给一段声波的声音信号,预测该声波对应的某种指定源语言的语句以及该语句的概率值。
(3)图像描述生成
和CNN一样,RNN已经在对无标图像描述自动生成中得到应用。将CNN和RNN结合进行图像描述自动生成能够根据图像的特征生成描述,如下图所示:
图二 图像描述生成

资料来源:CSDN
RNN训练方法
对RNN的训练和对传统的深度神经网络训练一样。RNN同样使用BP误差反向传播算法,不过有一点区别。如果将RNN进行网络展开,那么参数W,U,V是共享的,而传统神经网络却不是的。并且在使用梯度下降算法中,每一步的输出不仅依赖当前步的网络,并且还依赖前面若干步网络的状态。比如,在t=4时,我们还需要向后传递三步,后面的三步都需要加上各种的梯度。该学习算法称为Backpropagation Through Time (BPTT)。在vanilla RNN的训练中,BPTT无法解决长时依赖问题(即当前的输出与前面很长的一段序列有关,一般超过十步就无能为力了),因为BPTT会带来梯度爆炸或者梯度消失问题。
改进的RNN模型
上文提到,在对RNN进行反向传播训练的过程中,会出现梯度爆炸和梯度消失的问题,而两种常用的改进算法,即LSTM和GRU,可以改进这类问题。
LSTM(长短期记忆)是一种特殊的RNN,主要是为了解决长序列训练过程中的梯度消失和梯度爆炸问题。简单来说,就是相比普通的RNN,LSTM能够在更长的序列中有更好的表现。
首先使用LSTM的当前输入xt和上一个状态传递下来的ht-1拼接训练得到四个状态,其中,zf,zi,zo是由拼接向量乘以权重矩阵之后,再通过一个sigmoid激活函数转换成0到1之间的数值来作为一种门控状态。而z则是将结果通过一个tanh激活函数转换成-1到1之间的值(这里的tanh是将其作为输入数据,而不是门控信号)。如下图所示:
图三 LSTM拼接训练状态


资料来源:知乎
LSTM内部主要有三个阶段:
1.忘记阶段:这个阶段主要是对上一个节点传进来的输入进行选择性忘记。具体来说是通过计算得到的zf(f表示forget)来作为忘记门控,来控制上一个状态ct-1哪些需要留哪些需要忘。
2.选择记忆阶段:这个阶段将输入有选择性地进行记忆。主要是会对输入xt进行选择记忆。哪些重要则着重记录下来,哪些不重要则少计一点。当前的输入内容由前面计算得到的z表示。而选择的门控信号则是由zi(i表示information)来控制。将上面两步的结果相加,即可得到传输给下一个状态的ct。也就是下图中的第一个公式。
3.输出阶段:这个阶段将决定哪些将会被当成当前状态的输出。主要是通过zo来进行控制的。并且还对上一段得到的c0进行了放缩(通过tanh激活函数进行变化)。
图四 LSTM内部结构

资料来源:知乎
由于LSTM引入了很多内容,导致参数变多,也使得训练难度加大了很多。因此很多时候我们往往会使用效果和LSTM相当,但是参数更少的GRU来构建大训练量的模型。
在GRU中,算法通过上一个输出状态ht-1和当前节点的输入xt来获取两个门控状态。其中r控制重置的门控(reset gate),z为控制更新的门控(update gate),如下图所示。
图五 r,z门控

资料来源:知乎
与LSTM分明的层次结构不同,GRU在得到门控信号之后,首先使用重置门控来得到“重置”之后的数据ht-1’,再将ht-1’与输入xt进行拼接,再通过一个tanh激活函数来将数据放缩到-1到1的范围内,即得到h’。这里的h’主要包含了当前输入的xt数据。同时有针对性地对h’添加到当前的隐藏状态,相当于记忆了当前时刻的状态,类似于LSTM地选择记忆阶段。
接着是GRU最关键的步骤,即更新记忆阶段。在这个阶段,算法同时进行了遗忘和记忆两个步骤。
图六 GRU内部结构

资料来源:知乎
更新表达式:

在这个阶段中,使用了同一个门控就可以同时进行遗忘和选择记忆(LSTM则要使用多个门控),这分别对应了表达式中的z和1-z。由于GRU比LSTM少了一个门控,因此考虑到计算能力和时间成本,GRU相较于LSTM来说更加高效。
往期回顾
扫描二维码
关注我们
智物区域产业发展研究院
研究区域产业发展
区域产业发展智库
你“在看”我吗?
code/s?__biz=MzI3OTM0NDMxMQ==&mid=2247483887&idx=1&sn=8dafce7cb35a976b43b3e148f426e197&chksm=eb486437dc3fed215f75465102d48e6fb965107fcb5512668534fdcc72751cd2e5198418f4c6#rd