循环神经网络(RNN)_python

前言:

前馈神经网络的输入和输出的维数都是固定的,不能任意改变。当处理序列数据时,前馈神经网络就无能力为了。因为序列数据是变长的。为了使得前馈神经网络能处理变长的序列数据,一种方法是使用延时神经网络(Time-Delay Neural Networks,TDNN)[Waibel et al., 1989]。

循环神经网络(recurrent neural network, RNN),也叫递归神经网络。这里为了区别另外一种递归神经网络(Recursiva neural network),我们称之为循环神经网络。在前馈神经网络模型中,连接存在层与层之间,每层的节点之间是无连接的。

循环神经网络通过使用带自反馈的神经元,能够处理任意市场的序列。循环神经网络比前馈神经网络更加符合生物神经网络的结构。循环神经网络已经管饭的应用于语音识别,语音模型以及自然语言生成等任务上。

加深给定一个输入序列x(1:m) = (x1,x2,...,xm),循环神经网络通过下面的公式更行带反馈的隐层的激活值h(t):

循环神经网络(RNN)_python_02

从数学上讲,上面公式可以看成一个动态系统。动态系统是指系统的状态按照一定的规律随时间变化的系统。因此,活性值h(t) 在很多文献上也称为状态。但这里的状态是数学上的概念,区别与我们在前馈网络中定义的神经元的状态。理论上循环神经网络可以近似任意的动态系统。如下图1给出了循环神经网络的示例。

循环神经网络(RNN)_python_03

图1  循环神经网络


循环神经网络的参数训练可以通过随时间进行反向传播(Backpropagation ThroughTime,BPTT)算法[Werbos, 1990]。但循环神经网络的一个最大问题是训练时梯度需要随着时间进行反向传播。当输入序列比较长时,会存在梯度爆炸和消失问题Bengio et al.[1994], Hochreiter and Schmidhuber [1997], Hochreiter et al. [2001]。长短时记忆神经网络(long short term memory neural network, LSTM)--[Hochreiter and Schmidhuber, 1997]s是训练神经网络的一种扩展的方法。


简单循环神经网络

我们先来看一个非常简单的循环神经网络,叫简单循环网络(Simple Recurrent Net-work,SRN)[Elman, 1990]。

假设时刻t 时,输入为xt,隐层状态(隐层神经元活性)为ht。ht 不仅和当前时刻的输入相关,也和上一个时刻的隐层状态相关。

一般我们使用如下函数:

循环神经网络(RNN)_python_04

这里,f 是非线性函数,通常为logistic 函数或tanh 函数。,图2为按时间展开的循环神经网络。

循环神经网络(RNN)_python_05

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


梯度训练

循环神经网络(RNN)_python_06

图3 按时间展开的循环神经网络使用BP训练

循环神经网络的参数训练可以通过随时间进行反向传播(Backpropagation ThroughTime,BPTT)算法[Werbos, 1990]。图7.3给出了随时间进行反向传播算法的示例。假设循环神经网络在每个时刻t 都有一个监督信息,损失为Jt。则整个序列的损失为循环神经网络(RNN)_python_07


损失失J 关于U 的梯度为:

循环神经网络(RNN)_python_08


其中,h(t) 是关于U 和h(t−1) 的函数,而h(t−1) 又是关于U 和h(t−2) 的函数。因此,我们可以用链式法则得到:

循环神经网络(RNN)_python_09

其中,

循环神经网络(RNN)_python_10

因此,

循环神经网络(RNN)_python_11

我们定义循环神经网络(RNN)_python_12,则在上面公式中的括号里面为

r(t−k)。如果r > 1,当r---->OO时,r(t−k) -----> OO,会造成系统不稳定,也就是所谓的梯度爆炸问题;相反,如果r< 1,当t−k------>OO时,r(t−k) ----> 0,会出现和深度前馈神经网络类似的梯度消失问题。

在训练循环神经网络时,更经常出现的是梯度消失问题。因为我们一般情况下使用的非线性激活函数为logistic 函数或tanh 函数,其导数值都小于1。而权重矩阵循环神经网络(RNN)_python_13也不会太大。我们定义循环神经网络(RNN)_python_14,择有:

循环神经网络(RNN)_python_15

经过t − k 次传播之后,

循环神经网络(RNN)_python_16

如果时间间隔t − k 过大,循环神经网络(RNN)_python_17会趋于0.

因此,虽然简单循环网络从理论上可以建立长时间间隔的状态之间的依赖关系(Long-Term Dependencies),但是由于梯度爆炸或消失问题,实际上只能学习到短周期的依赖关系。这就是所谓的长期依赖问题。


改进的方案

为了避免梯度爆炸或者梯度小事的问题,关键是使得循环神经网络(RNN)_python_18。一种方式就是选取合适的参数,同时使用非饱和的激活函数。但这样的方式需要很多人工经验,同时也限制了模型的广泛使用。

还有一种改进的模型,比如让U=1,同时使用循环神经网络(RNN)_python_19

循环神经网络(RNN)_python_20

g 是非线性激活函数。

但这样的形式,丢失了神经元在反馈边上的非线性激活的性质。因此,一个更加有效的改进是引入一个新的状态c(t) 专门来进行线性的反馈传递,同时在ct 的信息非线性传递给h(t)。

循环神经网络(RNN)_python_21

但是,这样依然存在一定的问题。因为c(t) 和c(t−1) 是线性关系,同时不断累积x(t) 的信息,会使得c(t) 变得越来越大。为了解决这个问题,Hochreiter and Schmidhuber [1997] 提出一个非常好的解决方案,就是引入门机制(Gating Mechanism)来控制信息的累积速度,并可以选择遗忘之前累积的信息。这就是下面要介绍的长短时记忆神经网络。

关于LSTM的稍加详细的内容将在下一篇文章给出~~~~~~


循环神经网络(RNN)_python_22
欢迎分享

转载请标明

(机器学习算法与Python学习)