来源:Coursera吴恩达深度学习课程
基本的RNN算法还有一个很大的问题,就是梯度消失(vanishing gradients)的问题。
如上图,这是个语言模型的例子。有两个句子:“The cat, which already ate ……, was full.”和“The cats, which ate ……, were full.”它们都有长期的依赖(have very long-term dependencies),前面的单词对句子后面的单词有影响。但是基本的RNN模型(上图编号1所示的网络模型),不擅长捕获这种长期依赖效应。
原因如下:回忆之前的知识,一个很深很深的网络(上图编号2所示),100层,甚至更深,对这个网络从左到右做前向传播然后再反向传播。从输出y帽得到的梯度很难传播回去,很难影响靠前层的权重,很难影响前面层(红色标记)的计算。
对于RNN而言,首先从左向右前向传播,然后反向传播,同样存在梯度消失问题,后面层的输出误差很难影响到前面层的计算,实际上神经网络很难意识到它要记住的是单数还是复数单词,然后在序列后面生成依赖单复数形式的was或者were。所以基本的RNN模型会有很多局部影响,这是基本的RNN算法的一个缺点(weakness),不擅长处理长期依赖的问题。
尽管我们一直在讨论梯度消失问题,但是,之前在讲很深的神经网络时也提到了梯度爆炸。在反向传播时,随着层数的增多,梯度不仅可能指数型的下降,也可能指数型的上升。事实上梯度消失在训练RNN时是首要的问题(bigger problem),尽管梯度爆炸也是会出现,但是梯度爆炸很明显,因为指数级大的梯度会让你的参数变得极其大,以至于你的网络参数崩溃。你会看到很多NaN,或者不是数字的情况,这意味着网络计算出现了数值溢出(numerical overflow)。如果你发现了梯度爆炸的问题,一个解决方法就是用梯度修剪(gradient clipping)。梯度修剪的意思就是观察你的梯度向量,如果它大于某个阈值(threshold),缩放梯度向量,保证它不会太大,这就是通过一些最大值(maximum value)来修剪的方法。因此,如果你遇到了梯度爆炸,如果导数值很大,出现了NaN或者不是数字的情况,就用梯度修剪,这是相对比较鲁棒的,这是梯度爆炸的解决方法。
总结一下(summarize),我们了解到训练很深的神经网络时,随着层数的增加,导数有可能指数型的下降或者指数型的增加,我们可能会遇到梯度消失或者梯度爆炸的问题。加入一个RNN处理1,000个时间序列的数据集或者10,000个时间序列的数据集,这就是一个1,000层或者10,000层的神经网络,这样的网络就会遇到上述类型的问题。梯度爆炸基本上用梯度修剪就可以应对,但梯度消失比较棘手。我们接下来会介绍GRU(门控循环单元网络),这个网络可以有效地解决梯度消失的问题,并且能够使你的神经网络捕获更长的长期依赖。
说明:记录学习笔记,如果错误欢迎指正!转载请联系我。