循环神经网络(RNN, Recurrent Neural Networks)介绍
这篇文章很多内容是参考:http://www.wildml.com/2015/09/recurrent-neural-networks-tutorial-part-1-introduction-to-rnns/,在这篇文章中,加入了一些新的内容与一些自己的理解。
??循环神经网络(Recurrent Neural Networks,RNNs)已经在众多自然语言处理(Natural Language Processing, NLP)中取得了巨大成功以及广泛应用。但是,目前网上与RNNs有关的学习资料很少,因此该系列便是介绍RNNs的原理以及如何实现。主要分成以下几个部分对RNNs进行介绍:
1. RNNs的基本介绍以及一些常见的RNNs(本文内容);
2. 详细介绍RNNs中一些经常使用的训练算法,如Back Propagation Through Time(BPTT)、Real-time Recurrent Learning(RTRL)、Extended Kalman Filter(EKF)等学习算法,以及梯度消失问题(vanishing gradient problem)
3. 详细介绍Long Short-Term Memory(LSTM,长短时记忆网络);
4. 详细介绍Clockwork RNNs(CW-RNNs,时钟频率驱动循环神经网络);
5. 基于Python和Theano对RNNs进行实现,包括一些常见的RNNs模型。
??不同于传统的FNNs(Feed-forward Neural Networks,前向反馈神经网络),RNNs引入了定向循环,能够处理那些输入之间前后关联的问题。定向循环结构如下图所示:
??该tutorial默认读者已经熟悉了基本的神经网络模型。如果不熟悉,可以点击:Implementing A Neural Network From Scratch进行学习。
词向量(Word Representation,Word embeding)[1]便是一种可行又有效的方法。何为词向量,即使用一个指定长度的实数向量v来表示一个词。有一种种最简单的表示方法,就是使用One-hot vector表示单词,即根据单词的数量|V|生成一个|V| * 1的向量,当某一位为一的时候其他位都为零,然后这个向量就代表一个单词。缺点也很明显:
- 由于向量长度是根据单词个数来的,如果有新词出现,这个向量还得增加,麻烦!(Impossible to keep up to date);
- 主观性太强(subjective)
- 这么多单词,还得人工打labor并且adapt,想想就恐
- 最不能忍受的一点便是很难计算单词之间的相似性。
现在有一种更加有效的词向量模式,该模式是通过神经网或者深度学习对词进行训练,输出一个指定维度的向量,该向量便是输入词的表达。如word2vec。
现在有一种更加有效的词向量模式,该模式是通过神经网或者深度学习对词进行训练,输出一个指定维度的向量,该向量便是输入词的表达。如word2vec。
需要注意的是:
LSTMs(Long Short-Term Memory,长短时记忆模型)模型,该模型通常比vanilla RNNs能够更好地对长短时依赖进行表达,该模型相对于一般的RNNs,只是在隐藏层做了手脚。对于LSTMs,后面会进行详细地介绍。下面对RNNs在NLP中的应用进行简单的介绍。
Recurrent neural network based language model
Image Source
??下面是关于RNNs中机器翻译研究的三篇文章:
- A Recursive Recurrent Neural Network for Statistical Machine Translation
- Sequence to Sequence Learning with Neural Networks
- Joint Language and Translation Modeling with Recurrent Neural Networks
Towards End-to-End Speech Recognition with Recurrent Neural Networks
图像描述自动生成中得到应用。将CNNs与RNNs结合进行图像描述自动生成。这是一个非常神奇的研究与应用。该组合模型能够根据图像的特征生成描述。如下图所示:

??图像描述生成中的深度视觉语义对比. Image Source
BPTT无法解决长时依赖问题(即当前的输出与前面很长的一段序列有关,一般超过十步就无能为力了),因为BPTT会带来所谓的梯度消失或梯度爆炸问题(the vanishing/exploding gradient problem)。当然,有很多方法去解决这个问题,如LSTMs便是专门应对这种问题的。
Simple RNNs(SRNs)[2]
图像描述自动生成中得到应用。将CNNs与RNNs结合进行图像描述自动生成。这是一个非常神奇的研究与应用。该组合模型能够根据图像的特征生成描述。如下图所示:

??图像描述生成中的深度视觉语义对比. Image Source
BPTT无法解决长时依赖问题(即当前的输出与前面很长的一段序列有关,一般超过十步就无能为力了),因为BPTT会带来所谓的梯度消失或梯度爆炸问题(the vanishing/exploding gradient problem)。当然,有很多方法去解决这个问题,如LSTMs便是专门应对这种问题的。
Simple RNNs(SRNs)[2]
Simple RNNs(SRNs)[2]
??SRNs是RNNs的一种特例,它是一个三层网络,并且在隐藏层增加了上下文单元,下图中的y便是隐藏层,u便是上下文单元。上下文单元节点与隐藏层中的节点的连接是固定(谁与谁连接)的,并且权值也是固定的(值是多少),其实是一个上下文节点与隐藏层节点一一对应,并且值是确定的。在每一步中,使用标准的前向反馈进行传播,然后使用学习算法进行学习。上下文每一个节点保存其连接的隐藏层节点的上一步的输出,即保存上文,并作用于当前步对应的隐藏层节点的状态,即隐藏层的输入由输入层的输出与上一步的自己的状态所决定的。因此SRNs能够解决标准的多层感知机(MLP)无法解决的对序列数据进行预测的任务。
??SRNs网络结构如下图所示:
Bidirectional RNNs[3]
??Bidirectional RNNs(双向网络)的改进之处便是,假设当前的输出(第t步的输出)不仅仅与前面的序列有关,并且还与后面的序列有关。例如:预测一个语句中缺失的词语那么就需要根据上下文来进行预测。Bidirectional RNNs是一个相对较简单的RNNs,是由两个RNNs上下叠加在一起组成的。输出由这两个RNNs的隐藏层的状态决定的。如下图所示:
Deep(Bidirectional)RNNs[4]
??Deep(Bidirectional)RNNs与Bidirectional RNNs相似,只是对于每一步的输入有多层网络。这样,该网络便有更强大的表达与学习能力,但是复杂性也提高了,同时需要更多的训练数据。Deep(Bidirectional)RNNs的结构如下图所示:
Echo State Networks[5]
??ESNs(回声状态网络)虽然也是一种RNNs,但是它与传统的RNNs相差很大。ESNs具有三个特点:
- 它的核心结构时一个随机生成、且保持不变的储备池(Reservoir),储备池是大规模的、随机生成的、稀疏连接(SD通常保持1%~5%,SD表示储备池中互相连接的神经元占总的神经元个数N的比例)的循环结构;
- 其储备池到输出层的权值矩阵是唯一需要调整的部分;
- 简单的线性回归就可完成网络的训练。
??从结构上讲,ESNs是一种特殊类型的循环神经网络,其基本思想是:使用大规模随机连接的循环网络取代经典神经网络中的中间层,从而简化网络的训练过程。因此ESNs的关键是中间的储备池。网络中的参数包括:W为储备池中节点的连接权值矩阵,Win为输入层到储备池之间的连接权值矩阵,表明储备池中的神经元之间是连接的,Wback为输出层到储备池之间的反馈连接权值矩阵,表明储备池会有输出层来的反馈,Wout为输入层、储备池、输出层到输出层的连接权值矩阵,表明输出层不仅与储备池连接,还与输入层和自己连接。Woutbias表示输出层的偏置项。
??对于ESNs,关键是储备池的四个参数,如储备池内部连接权谱半径SR(SR=λmax=max{|W的特征指|},只有SR <1时,ESNs才能具有回声状态属性)、储备池规模N(即储备池中神经元的个数)、储备池输入单元尺度IS(IS为储备池的输入信号连接到储备池内部神经元之前需要相乘的一个尺度因子)、储备池稀疏程度SD(即为储备池中互相连接的神经元个数占储备池神经元总个数的比例)。对于IS,如果需要处理的任务的非线性越强,那么输入单元尺度越大。该原则的本质就是通过输入单元尺度IS,将输入变换到神经元激活函数相应的范围(神经元激活函数的不同输入范围,其非线性程度不同)。
??ESNs的结构如下图所示:
Gated Recurrent Unit Recurrent Neural Networks[6]
??GRUs也是一般的RNNs的改良版本,主要是从以下两个方面进行改进。一是,序列中不同的位置处的单词(已单词举例)对当前的隐藏层的状态的影响不同,越前面的影响越小,即每个前面状态对当前的影响进行了距离加权,距离越远,权值越小。二是,在产生误差error时,误差可能是由某一个或者几个单词而引发的,所以应当仅仅对对应的单词weight进行更新。GRUs的结构如下图所示。GRUs首先根据当前输入单词向量word vector已经前一个隐藏层的状态hidden state计算出update gate和reset gate。再根据reset gate、当前word vector以及前一个hidden state计算新的记忆单元内容(new memory content)。当reset gate为1的时候,new memory content忽略之前的所有memory content,最终的memory是之前的hidden state与new memory content的结合。
LSTM Netwoorks[7]
??LSTMs与GRUs类似,目前非常流行。它与一般的RNNs结构本质上并没有什么不同,只是使用了不同的函数去去计算隐藏层的状态。在LSTMs中,i结构被称为cells,可以把cells看作是黑盒用以保存当前输入xt之前的保存的状态ht?1,这些cells更加一定的条件决定哪些cell抑制哪些cell兴奋。它们结合前面的状态、当前的记忆与当前的输入。已经证明,该网络结构在对长序列依赖问题中非常有效。LSTMs的网络结构如下图所示。对于LSTMs的学习,参见 this post has an excellent explanation
??LSTMs解决的问题也是GRU中所提到的问题,如下图所示:
??LSTMs与GRUs的区别如图所示[8]:
??从上图可以看出,它们之间非常相像,不同在于:
- new memory的计算方法都是根据之前的state及input进行计算,但是GRUs中有一个reset gate控制之前state的进入量,而在LSTMs里没有这个gate;
- 产生新的state的方式不同,LSTMs有两个不同的gate,分别是forget gate (f gate)和input gate(i gate),而GRUs只有一个update gate(z gate);
- LSTMs对新产生的state又一个output gate(o gate)可以调节大小,而GRUs直接输出无任何调节。
Clockwork RNNs(CW-RNNs)[9]
??CW-RNNs是较新的一种RNNs模型,其论文发表于2014年Beijing ICML。在原文[8]中作者表示其效果较SRN与LSTMs都好。
??CW-RNNs也是一个RNNs的改良版本,是一种使用时钟频率来驱动的RNNs。它将隐藏层分为几个块(组,Group/Module),每一组按照自己规定的时钟频率对输入进行处理。并且为了降低标准的RNNs的复杂性,CW-RNNs减少了参数的数目,提高了网络性能,加速了网络的训练。CW-RNNs通过不同的隐藏层模块工作在不同的时钟频率下来解决长时间依赖问题。将时钟时间进行离散化,然后在不同的时间点,不同的隐藏层组在工作。因此,所有的隐藏层组在每一步不会都同时工作,这样便会加快网络的训练。并且,时钟周期小的组的神经元的不会连接到时钟周期大的组的神经元,只会周期大的连接到周期小的(认为组与组之间的连接是有向的就好了,代表信息的传递是有向的),周期大的速度慢,周期小的速度快,那么便是速度慢的连速度快的,反之则不成立。现在还不明白不要紧,下面会进行讲解。
? ?CW-RNNs与SRNs网络结构类似,也包括输入层(Input)、隐藏层(Hidden)、输出层(Output),它们之间也有向前连接,输入层到隐藏层的连接,隐藏层到输出层的连接。但是与SRN不同的是,隐藏层中的神经元会被划分为若干个组,设为g,每一组中的神经元个数相同,设为k,并为每一个组分配一个时钟周期Ti∈{T1,T2,...,Tg},每一个组中的所有神经元都是全连接,但是组j到组i的循环连接则需要满足Tj大于Ti。如下图所示,将这些组按照时钟周期递增从左到右进行排序,即T1<T2<...<Tg,那么连接便是从右到左。例如:隐藏层共有256个节点,分为四组,周期分别是[1,2,4,8],那么每个隐藏层组256/4=64个节点,第一组隐藏层与隐藏层的连接矩阵为64*64的矩阵,第二层的矩阵则为64*128矩阵,第三组为64*(3*64)=64*192矩阵,第四组为64*(4*64)=64*256矩阵。这就解释了上一段的后面部分,速度慢的组连到速度快的组,反之则不成立。
??CW-RNNs的网络结构如下图所示:
??在传统的RNN中,按照下面的公式进行计算:
??其中,W为隐藏层神经元的自连接矩阵,Win为输入层到隐藏层的连接权值矩阵,Wout是隐藏层到输出层的连接权值矩阵 ,xt是第t步的输入,st?1为第t?1步隐藏层的输出,st为第t步隐藏层的输出,ot为第t步的输出,fs为隐藏层的激活函数,fo为输出层的激活函数。
??与传统的RNNs不同的是,在第t步时,只有那些满足(tmodTi)=0的隐藏层组才会执行。并且每一隐藏层组的周期{T1,T2,...,Tg}都可以是任意的。原文中是选择指数序列作为它们的周期,即Ti=2i?1i∈[1,...,g]。
??因此W与Win将被划分为g个块。如下:
其中W是一个上三角矩阵,每一个组行Wi被划分为列向量{W1i,...,Wii,0(i+1)i,...,0gi}T,Wji,j∈[1,...,g]表示第i个组到第j个组的连接权值矩阵。在每一步中,W与Win只有部分组行处于执行状态,其它的为0:
??为了使表达不混淆,将Win写成Win。并且执行的组所对应的o才会有输出。处于非执行状态下的隐藏层组仍保留着上一步的状态。下图是含五个隐藏层组在t=6时的计算图:
??在CW-RNNs中,慢速组(周期大的组)处理、保留、输出长依赖信息,而快速组则会进行更新。CW-RNNs的误差后向传播也和传统的RNNs类似,只是误差只在处于执行状态的隐藏层组进行传播,而非执行状态的隐藏层组也复制其连接的前面的隐藏层组的后向传播。即执行态的隐藏层组的误差后向传播的信息不仅来自与输出层,并且来自与其连接到的左边的隐藏层组的后向传播信息,而非执行态的后向传播信息只来自于其连接到的左边的隐藏层组的后向传播数据。
??下图是原文对三个不同RNNs模型的实验结果图:
??上图中,绿色实线是预测结果,蓝色散点是真实结果。每个模型都是对前半部分进行学习,然后预测后半部分。LSTMs模型类似滑动平均,但是CW-RNNs效果更好。其中三个模型的输入层、隐藏层、输出层的节点数都相同,并且只有一个隐藏层,权值都使用均值为0,标准差为0.1的高斯分布进行初始化,隐藏层的初始状态都为0,每一个模型都使用Nesterov-style
momentum SGD(Stochastic Gradient Descent,随机梯度下降算法)[10]进行学习与优化。
更多的RNNs模型。
??后面将陆续推出:
- 详细介绍RNNs中一些经常使用的训练算法,如Back Propagation Through Time(BPTT)、Real-time Recurrent Learning(RTRL)、Extended Kalman Filter(EKF)等学习算法,以及梯度消失问题(vanishing gradient problem)
- 详细介绍Long Short-Term Memory(LSTM,长短时记忆网络);
- 详细介绍Clockwork RNNs(CW-RNNs,时钟频率驱动循环神经网络);
- 基于Python和Theano对RNNs进行实现,包括一些常见的RNNs模型;
??本系列将实现一个基于循环神经网络的语言模型(recurrent neural network based language model)。该实现包含两个方面:一是能够得到任意语句在现实中成立的得分,其提供了判断语法与语义的正确性的度量方式。该模型是机器翻译中的典型应用。二是模型能够产生新的文本,这是一个非常棒的应用。比如,对莎士比亚的文章进行训练,能够产生一个新的类似莎士比亚的文本,目前,这个有趣的想法已经被Andrew Karpathy基于RNNs的字符级别的语言模型实现了。
由于实在很忙,后面都没进行更新,抱歉。