Recurrent neural network and LSTM
简单记录一下循环神经网络 (recurrent neural network, RNN), 另一种RNN,主要关注时间序列的预测、分类和识别等问题。这里卖个瓜,前面有讨论过残差神经网络,感兴趣地可以去围观,链接见文末。
本文首先讨论RNN的motivation及其特点;然后是为了解决长程依赖 (long-term dependencies) 而提出的long short term memory (LSTM) 结构; 最后是二者在tensorflow中的简单样例。参考文献很多,这里强烈案例下面两篇文章!
Recurrent neural network
循环神经网络的动机是刻画一个时间序列当前输入与此前信息的联系,从网络结构上,循环神经网络通过称为循环体的模块 (如下图) 实现对信息的记忆,即该层在时刻的输出状态会被记录,并作为时刻该模块输入的一部分,以级联的形式与构成此刻的输入 .
显然,循环体中的循环理论上是无穷的,但在实际应用中会限制循环的次数以避免梯度消失 (gradient vanishing) 的问题,用num_step
来定义,即循环体的基本模块被复制并展开为num_step
个。如
文献[4]所述,循环体结构是RNN的基础,在RNN中对于复制展开的循环体,其参数是共享的。这一点与卷积神经网络中的权值共享有类似之处。在这篇文章里给出了非常多的RNN的应用场景,我很喜欢里面关于手写体识别的问题,体现了权值共享的效果。

设时刻循环体的输入为,$t-1$时刻循环体的输出状态为,则RNN中时刻的输出为,
其中是权值矩阵,其shape为, 为偏置。这里采用的激活函数是tanh,将数据限制到之间。
那么,为什么用tanh,而不是有high reputation的ReLU? 知乎的这个讨论给出了很棒的解释,参考Hinton论文中的观点 ReLUs seem inappropriate for RNNs because they can have very large outputs so they might be expected to be far more likely to explode than units thathave bounded values. ReLU将输出的值限制在之间,而RNN中循环体之间的权值是共享的,经过公式(1)的多次作用,相当于对做了连乘,ReLU函数会导致梯度爆炸的问题。因此,采用tanh可以将每层的输出空控制在限定的范围内,既避免了梯度消失,也避免了梯度爆炸的问题。
LSTM
在时间序列的预测中存在长期依赖 (long-term dependencies) 的问题,即网络需要记住离时间很远的某个时刻的信息,固定的num_step
将不适用于这一情形,并且长时间间隔下的梯度消失问题将无法处理。因此,需要对RNN的循环体模块进行修改,即长短时记忆网络 (long short term memory, LSTM).
LSTM的基本模块如下图所示,参考Understanding LSTM的解释,The key to LSTMs is the cell state, the horizontal line running through the top of the diagram. The cell state is kind of like a conveyor belt. 即LSTM的核心是组成为cell state
,用于存储和记忆上文的信息,类似传送带的功能。
而cell state
的更新,通过三个逻辑门以及和共同完成。它们分别称为 (1) forget gate, (2) input gate, (3) output gate. 采用sigmoid函数将数值规范化到区间,并与待处理信号进行点乘,本质上实现软判决.

与RNN类似,首先将时刻LSTM cell的输出与时刻的输入进行级联,逐一通过三个门,
- 遗忘门 (Forget gate)
- 输入门 (Input gate)
- 输出门 (Output gate)
其中遗忘门的作用是抛弃cell state中不需要的信息,与作用; 输入门则是决定cell state中待更新的信息,与,即state candidates作用;输出门则从更新后的cell state
中决定输出的状态。结合以上三个门结构,便可以更新cell state
以及cell output
,
- cell state update
- cell output upadte
Examples
参考《TensorFlow实战》第7章的LSTM基于PTB数据集的语言预测样例,以及TensorFlow的Tutorial,设计了一个小实验,对比RNN和LSTM的performance,以及激活函数对于RNN的影响。(详细的notebooks见这里: RNN, LSTM)
这里给出tf.contrib.rnn
中提供的用于搭建RNN和LSTM cell的类的实例化方法,以及如何构建多个Recurrent层,
另外,在PTB的TF教程里,设置了可变的学习率以及梯度的clipping用于抑制梯度爆炸 (gradient explosion) 的问题,代码如下
下面来比较一下RNN和LSTM的效果。比较的指标是perplexity (复杂度),用于刻画该模型能够估计出某一句话的概率,其数值越小,模型表现越好。

容易看出,LSTM的表现是优于RNN的。除此之外,采用tanh函数的RNN要显著好于采用ReLU,在训练中也出现了RuntimeWarning: overflow encountered in exp的警告,说明出现了gradient explosion的问题。最后,我尝试增加了RNN的层数,但是效果并没有变好,也许是参数多了?也有可能是我偷懒了,没多训测试几次。。。
References
[1] Understanding LSTM
[2] The Unreasonable Effectiveness of Recurrent Neural Networks
[3] Tensorflow tutorial
[4] TensorFlow实战Google深度学习框架
[5] TensorFlow实战
[6] RNN中为什么要采用tanh而不是ReLu作为激活函数?
广告位
Residual network I — block and bottleneck
Residual network II — realize with tensorflow