这本书已经读了好几章,突然觉得有必要在阅读的过程中做一些笔记或记录一些问题什么的,故现在有了此篇文章。
14.循环递归RNN,序列建模套路深
问题:
(1)RNN中的“深度”与传统的深度神经网络里的“深度”有何不同?
答:RNN中的深度主要是指时间和空间(如网络中的隐含层个数)特性上的深度。
(2)RNN为什么会有梯度弥散或梯度爆炸的问题?
答:如果用到sigmoid激活函数(末尾推荐的两个回答是基于tanh激活函数),则它会将+∞~-∞之间的输入压缩到0~1之间,当input的值更新时,output会有很小的更新。又因为上一层的输出将作为后一层的输入,而输出经过sigmoid后更新速率会逐步衰减,直到输出层只会有微乎其微的更新。从数学的角度出发,可知sigmoid导数在0的位置取最大值1/4。当使用均值为0,方差为1的高斯分布及初始化参数w,有|w|<1. 随网络层数加深,w的变化幅度会呈1/4的指数衰减,使得最后学不到东西,造成梯度弥散。同样,当|w|>1,w变化幅度会指数递增,最后造成梯度爆炸。
【另外,推荐知乎高赞回答(RNN梯度消失与梯度爆炸的原因:https://zhuanlan.zhihu.com/p/28687529和https://zhuanlan.zhihu.com/p/28687529)】
(3)梯度弥散或爆炸问题在一定程度上阻碍了RNN的进一步发展,有什么策略可以在一定程度上抑制这个问题吗?
答:下图展示了RNN网络损失函数对权重和偏置的关系:
上图中存在一个非常陡峭的面,在更新参数的过程中,如果当前参数所处的位置刚好位于这个高高的“误差墙”上,由于这个面上的梯度非常大,那么采用梯度下降法更新后的参数可能就跑得很远,如图中蓝色的实线所示。因此,为了解决这个问题,gradient clipping算法为梯度的范数设置了一个阈值,当梯度的范数大于某个值的时候,将梯度设置为这个阈值,算法描述如下:
但是这个方法只能够解决梯度爆炸的问题,要解决梯度弥散的问题,可以从下面两点入手:
- 对于隐层态的权重矩阵Whh使用单位矩阵进行初始化而不是随机初始化;
- 使用RELU激活函数而不是Sigmoid激活函数,因为RELU函数的导数为0或者1,在反向传播的过程中不会衰减至0。
除此之外,还可以更改内部结构来解决梯度消失和梯度爆炸问题,那就是LSTM,请见下回分解!
(4)除了梯度弥散或爆炸问题,RNN还存在什么问题?如何解决?
答:
(5)你能将RNN预测正弦序列的实现范例用Eager执行模式进行改写吗?