循 环 神 经 网 络(recurrent neural network,RNN) 源 自 于 1982 年 由Saratha Sathasivam 提出的霍普菲尔德网络。霍普菲尔德网络因为实现困难,在其提出的时候并且没有被合适地应用。该网络结构也于 1986 年后被全连接神经网络以及一些传统的机器学习算法所取代。然而,传统的机器学习算法非常依赖于人工提取的特征,使得基于传统机器学习的图像识别、语音识别以及自然语言处理等问题存在特征提取的瓶颈。而基于全连接神经网络的方法也存在参数太多、无法利用数据中时间序列信息等问题。随着更加有效的循环神经网络结构被不断提出,循环神经网络挖掘数据中的时序信息以及语义信息的深度表达能力被充分利用,并在语音识别、语言模型、机器翻译以及时序分析等方面实现了突破。

 循环神经网络的主要用途是处理和预测序列数据。在之前介绍的全连接神经网络或卷积神经网络模型中,网络结构都是从输入层到隐含层再到输出层,层与层之间是全连接或部分连接的,但每层之间的节点是无连接的。考虑这样一个问题,如果要预测句子的下一个单词是什么,一般需要用到当前单词以及图1 循环神经网络经典结构示意图前面的单词,因为句子中前后单词并不是独立的。比如,当前单词是“很”,前一个单词是“天空”,那么下一个单词很大概率是“蓝”。循环神经网络的来源就是为了刻画一个序列当前的输出与之前信息的关系。从网络结构上,循环神经网络会记忆之前的信息,并利用之前的信息影响后面结点的输出。也就是说,循环神经网络的隐藏层之间的结点是有连接的,隐藏层的输入不仅包括输入层的输出,还包括上一时刻隐藏层的输出。

                                                        TensorFlow实战系列14--循环神经网络简介

                                                                                 图1 循环神经网络经典结构示意图

          

 图 1 展示了一个典型的循环神经网络。对于循环神经网络,一个非常重要的概念就是时刻。循环神经网络会对于每一个时刻的输入结合当前模型的状态给出一个输出。从图 1 中可以看到,循环神经网络的主体结构 A的输入除了来自输入层 Xt,还有一个循环的边来提供当前时刻的状态。在每一个时刻,循环神经网络的模块
A 会读取 t 时刻的输入 Xt,并输出一个值 ht。同时 A 的状态会从当前步传递到下一步。因此,循环神经网络理论上可以被看作是同一神经网络结构被无限复制的结果。但出于优化的考虑,目前循环神经网络无法做到真正的无限循环,所以,现实中一般会将循环体展开,于是可以得到图 2 所展示的结构。

 在图 2 中可以更加清楚的看到循环神经网络在每一个时刻会有一个输入 Xt,然后根据循环神经网络当前的状态 At 提供一个输出 Ht。从而神经网络当前状态 At 是根据上一时刻的状态 At-1 和当前输入 Xt 共同决定的。从循环神经网络的结构特征可以很容易地得出它最擅长解决的问题是与时间序列相关的。循环神经网络也是处理这类问题时最自然的神经网络结构。对于一个序列数据,可以将这个序列上不同时刻的数据依次传入循环神经网络的输入层,而输出可以是对序列中下一个时刻的预测。循环神经网络要求每一个时刻都有一个输入,但是不一定每个时刻都需要有输出。在过去几年中,循环神经网络已经被广泛地应用在语音识别、语言模型、机器翻译以及时序分析等问题上,并取得了巨大的成功.

TensorFlow实战系列14--循环神经网络简介

       
图 2 循环神经网络按时间展开后的结构

 以机器翻译为例来介绍循环神经网络是如何解决实际问题的。循环神经网络中每一个时刻的输入为需要翻译的句子中的单词。如图 3 所示,需要翻译的句子为 ABCD,那么循环神经网络第一段每一个时刻的输入就分别是 A、B、C 和 D,然后用“”作为待翻译句子的结束符。在第一段中,循环神经网络没有输出。从结束符“”开始,循环神经网络进入翻译阶段。该阶段中每一个时刻的输入是上一个时刻的输出,而最终得到的输出就是句子
ABCD 翻译的结果。从图 3 中可以看到句子 ABCD 对应的翻译结果就是 XYZ,而 Q 是代表翻译结束的结束符。

                                        TensorFlow实战系列14--循环神经网络简介

           
3

 如之前所介绍,循环神经网络可以被看做是同一神经网络结构在时间序列上被复制多次的结果,这个被复制多次的结构被称之为循环体。如何设计循环体的网络结构是循环神经网络解决实际问题的关键。和卷积神经网络过滤器中参数是共享的类似,在循环神经网络中,循环体网络结构中的参数在不同时刻也是共享的。