通常,数据的存在形式有语音、文本、图像、视频等。因为我的研究方向主要是图像识别,所以很少用有“记忆性”的深度网络。怀着对循环神经网络的兴趣,在看懂了有关它的理论后,我又看了Github上提供的tensorflow实现,觉得收获很大,故在这里把我的理解记录下来,也希望对大家能有所帮助。本文将主要介绍RNN相关的理论,并引出LSTM网络结构(关于对tensorflow实现细节的理解,有时间的话,在下一篇博文中做介绍)。
循环神经网络
RNN,也称作循环神经网络(还有一种深度网络,称作递归神经网络,读者要区别对待)。因为这种网络有“记忆性”,所以主要是应用在自然语言处理(NLP)和语音领域。与传统的Neural network不同,RNN能利用上”序列信息”。从理论上讲,它可以利用任意长序列的信息,但由于该网络结构存在“消失梯度”问题,所以在实际应用中,它只能回溯利用与它接近的time steps上的信息。
1. 网络结构
常见的神经网络结构有卷积网络、循环网络和递归网络,栈式自编码器和玻尔兹曼机也可以看做是特殊的卷积网络,区别是它们的损失函数定义成均方误差函数。递归网络类似于数据结构中的树形结构,且其每层之间会有共享参数。而最为常用的循环神经网络,它的每层的结构相同,且每层之间参数完全共享。RNN的缩略图和展开图如下,
尽管RNN的网络结构看上去与常见的前馈网络不同,但是它的展开图中信息流向也是确定的,没有环流,所以也属于forward network,故也可以使用反向传播(back propagation)算法来求解参数的梯度。另外,在RNN网络中,可以有单输入、多输入、单输出、多输出,视具体任务而定。
2. 损失函数
在输出层为二分类或者softmax多分类的深度网络中,代价函数通常选择交叉熵(cross entropy)损失函数,前面的博文中证明过,在分类问题中,交叉熵函数的本质就是似然损失函数。尽管RNN的网络结构与分类网络不同,但是损失函数也是有相似之处的。
假设我们采用RNN网络构建“语言模型”,“语言模型”其实就是看“一句话说出来是不是顺口”,可以应用在机器翻译、语音识别领域,从若干候选结果中挑一个更加靠谱的结果。通常每个sentence长度不一样,每一个word作为一个训练样例,一个sentence作为一个Minibatch,记sentence的长度为T。为了更好地理解语言模型中损失函数的定义形式,这里做一些推导,根据全概率公式,则一句话是“自然化的语句”的概率为
3. 梯度求解
在训练任何深度网络模型时,求解损失函数关于模型参数的梯度,应该算是最为核心的一步了。在RNN模型训练时,采用的是BPTT(back propagation through time)算法,这个算法其实实质上就是朴素的BP算法,也是采用的“链式法则”求解参数梯度,唯一的不同在于每一个time step上参数共享。从数学的角度来讲,BP算法就是一个单变量求导过程,而BPTT算法就是一个复合函数求导过程。接下来以损失函数展开式中的第3项为例,推导其关于网络参数U、W、V的梯度表达式(总损失的梯度则是各项相加的过程而已)。
为了简化符号表示,记
所以,
说明一下,为了更好地体现复合函数求导的思想,公式(2)中引入了变量
简化得下式,
继续简化得下式,
3.1
E3
关于参数V的偏导数
记t=3时刻的softmax神经元的输入为
3.2
E3
关于参数W的偏导数
关于参数W的偏导数,就要使用到上面关于复合函数的推导过程了,记
类似于标准的BP算法中的表示,定义
那么,公式(7)可以转化为下式,
显然,结合公式(8)中的递推公式,可以递推求解出公式(9)中的每一项,那么
3.3
E3
关于参数U的偏导数
关于参数U的偏导数求解过程,跟W的偏导数求解过程非常类似,在这里就不介绍了,感兴趣的读者可以结合3.2的思路尝试着自己推导一下。
4. 梯度消失问题
当网络层数增多时,在使用BP算法求解梯度时,自然而然地就会出现“vanishing gradient“问题(还有一种称作“exploding gradient”,但这种情况在训练模型过程中易于被发现,所以可以通过人为控制来解决),下面我们从数学的角度来证明RNN网络确实存在“vanishing gradient“问题,推导公式如下,
大家应该注意到了,上面的式子中有一个连乘式,对于其中的每一项,满足
我们再从直观的角度来理解一下消失梯度问题,对于RNN时刻T的输出,其必定是时刻t=1,…,T-1的输入综合作用的结果,也就是说更新模型参数时,要充分利用当前时刻以及之前所有时刻的输入信息。但是如果发生了”消失梯度”问题,就会意味着,距离当前时刻非常远的输入数据,不能为当前模型参数的更新做贡献,所以在RNN的编程实现中,才会有“truncated gradient”这一概念,“截断梯度”就是在更新参数时,只利用较近的时刻的序列信息,把那些“历史悠久的信息”忽略掉了。
解决“消失梯度问题”,我们可以更换激活函数,比如采用Relu(rectified linear units)激活函数,但是更好的办法是使用LSTM或者GRU架构的网络。
LSTM网络
为了解决原始RNN网络结构存在的“vanishing gradient”问题,前辈们设计了LSTM这种新的网络结构。但从本质上来讲,LSTM是一种特殊的循环神经网络,其和RNN的区别在于,对于特定时刻t,隐藏层输出
GRU(Gated Recurrent Unit)是2014年提出来的新的RNN架构,它是简化版的LSTM,在超参数(hyper-parameters)均调优的前提下,这两种RNN架构的性能相当,但是GRU架构的参数少,所以需要的训练样本更少,易于训练。LSTM和GRU架构的网络图如下,
关于LSTM网络结构相关的理论,请参见http://colah.github.io/posts/2015-08-Understanding-LSTMs/,相信也只有这样的大牛能把LSTM解析的如此浅显易懂。这里还需要补充说明一下,关于LSTM网络的参数求偏微分,如果我们手动求解的话,也是跟RNN类似的思路,但由于LSTM网络结构比较复杂,手动算的话,式子会变得非常复杂,我们便可以借助深度学习框架的自动微分功能了,现在的框架也都支持自动微分的,比如theano、tensorflow等。
参考资料:http://www.wildml.com/2015/10/recurrent-neural-networks-tutorial-part-3-backpropagation-through-time-and-vanishing-gradients/
“A tutorial on training recurrent neural networks”. H. Jaeger, 2002.