第8讲 循环神经网络II
–长程依赖问题
–长短期记忆网络(LSTM)
–门控循环神经网络(GRU)
–深层循环神经网络
–实验④(循环神经网络实验)布置

RNN的长时依赖问题

首先回顾一下上篇文章推导出来的RNN的误差项随时间反向传播的公式。(误差项:误差EE对神经元j的输出netjnet_j的偏导)
《深度学习》:循环神经网络II
我们可以看到,误差项从t时刻传递到k时刻,其值的上界是βfβwbm{beta_fbeta_w}的指数函数。βfβwbm{beta_fbeta_w}分别是对角矩阵diag[f(netj)]diag[f^{'}(net_j)]和矩阵W模的上界。显然,除非βfβwbm{beta_fbeta_w}乘积的值位于1附近,否则,当t-k很大时(也就是误差传递很多个时刻时),整个式子的值就会变得极小(当βfβwbm{beta_fbeta_w}乘积小于1)或者极大(当βfβwbm{beta_fbeta_w}乘积大于1),前者就是梯度消失,后者就是梯度爆炸。虽然科学家们搞出了很多技巧(比如怎样初始化权重),让βfβwbm{beta_fbeta_w}的值尽可能贴近于1,终究还是难以抵挡指数函数的威力。
梯度消失或者梯度爆炸会导致梯度为0,没法继续训练更新参数。也就是RNN的长时依赖问题。/

长短时记忆网络(LSTM)

Hochreiter & Schmidhuber (1997)

Long Short Term Memory networks(以下简称LSTMs),一种特殊的RNN网络,该网络设计出来是为了解决长依赖问题。该网络由 Hochreiter & Schmidhuber (1997)引入,并有许多人对其进行了改进和普及。他们的工作被用来解决了各种各样的问题,直到目前还被广泛应用。
下面放一张李宏毅老师的LSTM图:

李宏毅老师,个人认为是机器学习、深度学习国内中文课程讲的最好的。想看视频的可以去b站或者直接百度李宏毅,真的是从根本上讲透彻!!!!

《深度学习》:循环神经网络II
相比RNN只有一个传递状态 hth^t ,LSTM有两个传输状态,一个 ctc^t(cell state),和一个hth^t(hidden state)。(Tips:RNN中的 hth^t 对于LSTM中的 ctc^t

其中对于传递下去的ctc^t改变得很慢,通常输出的 [公式] 是上一个状态传过来的ctc^t 加上一些数值。
hth^t 则在不同节点下往往会有很大的区别。

深入了解LSTM结构

《深度学习》:循环神经网络II
LSTM首先将本时刻的输入xtx_t和上时刻的隐状态ht1h_{t-1}拼接成一个向量。然后分别和三个不同的W矩阵点乘,再经过sigmoidsigmoid函数作用,得到三个范围在0-1的数ziz^i,zfz^f,zoz^o
有经验的同学可能就能发现这三个数值的作用了,一般用sigmoidsigmoid都是输出一个概率值,所以这三个数值就是一种“门控机制”。而z=tanh(W[xt,ht1])z=tanh(W [x_t,h_{t-1}])表示输入,tanh的作用是把数据压缩到【-1,1】。

具体原理

《深度学习》:循环神经网络II
odot是Hadamard Product,也就是操作矩阵中对应的元素相乘,因此要求两个相乘矩阵是同型的。 oplus 则代表进行矩阵加法。
LSTM内部主要有三个阶段:

  1. 忘记阶段。这个阶段主要是对上一个节点传进来的输入进行选择性忘记。简单来说就是会 “忘记不重要的,记住重要的”。具体来说是通过计算得到的zfbm{z^f}(f表示forget)来作为忘记门控,来控制上一个状态的ct1c^{t-1}哪些需要留哪些需要忘。

  2. 选择记忆阶段。这个阶段将这个阶段的输入有选择性地进行“记忆”。主要是会对输入xtbm{x_t} 进行选择记忆。哪些重要则着重记录下来,哪些不重要,则少记一些。当前的输入内容由前面计算得到的zbm{z} 表示。而选择的门控信号则是由 zibm{z^i}(i代表information)来进行控制。
    将上面两步得到的结果相加,即可得到传输给下一个状态的 ctbm{c^t}。也就是上图中的第一个公式。

  3. 输出阶段。这个阶段将决定哪些将会被当成当前状态的输出。主要是通过zobm{z^o}(o代表output)来进行控制的。并且还对上一阶段得到的ctbm{c^t}进行了放缩(通过一个tanh**函数进行变化)。
    与普通RNN类似,输出ytbm{y^t}往往最终t也是通过htbm{h^t} 变化得到。

GRU

GRU(Gate Recurrent Unit)是循环神经网络(Recurrent Neural Network, RNN)的一种。和LSTM(Long-Short Term Memory)一样,也是为了解决长期记忆和反向传播中的梯度等问题而提出来的。
《深度学习》:循环神经网络II
一句话,效果差不多但是计算简单。

GRU结构

GRU的输入输出结构与普通的RNN是一样的。
《深度学习》:循环神经网络II
下面是内部结构:
《深度学习》:循环神经网络II
同样的方法,加个sigmoidsigmoid函数生成两个“门控”,rr为控制重置的(reset),zz为控制更新的门控(update)。
得到门控信号之后,首先使用重置门控来得到“重置”之后的数据 ht1=ht1rbm{h^{t-1^{'}}=h^{t-1}odot r} ,再将 ht1bm{h^{t-1^{'}}} 与输入 xtbm{x_t} 进行拼接,再通过一个tanh**函数来将数据放缩到-1~1的范围内。《深度学习》:循环神经网络II
这里的hbm{h^{'}} 主要是包含了当前输入的xtbm{x_t} 数据。有针对性地对hbm{h^{'}} 添加到当前的隐藏状态,相当于”记忆了当前时刻的状态“。类似于LSTM的选择记忆阶段.
《深度学习》:循环神经网络II

更新记忆阶段

更新表达式: ht=(1z)ht1+zhh^t =(1-z)odot h^{t-1}+zodot h^{'}
再次强调一下,门控信号(这里的 z)的范围为0~1。门控信号越接近1,代表”记忆“下来的数据越多;而越接近0则代表”遗忘“的越多。
GRU很聪明的一点就在于,我们使用了同一个门控zbm{z} 就同时可以进行遗忘和选择记忆(LSTM则要使用多个门控)。

  • (1z)ht1(1-z)odot h^{t-1} :表示对原本隐藏状态的选择性“遗忘”。这里的1z1-z可以想象成遗忘门(forget gate),忘记 hth^t维度中一些不重要的信息。
  • zhzodot h^{'} : 表示对包含当前节点信息的 hh^{'} 进行选择性”记忆“。与上面类似,这里的zz 同理会忘记hh^{'}维度中的一些不重要的信息。或者,这里我们更应当看做是对hh^{'}维度中的某些信息进行选择。
    ht=(1z)ht1+zhh^t =(1-z)odot h^{t-1}+zodot h^{'}:结合上述,这一步的操作就是忘记传递下来的 ht1h^{t-1} 中的某些维度信息,并加入当前节点输入的某些维度信息。

LSTM和GRU的联系

GRU是在2014年提出来的,而LSTM是1997年。他们的提出都是为了解决相似的问题,那么GRU难免会参考LSTM的内部结构。
大家看到rr (reset gate)实际上与他的名字有点不符。我们仅仅使用它来获得了hh^{'}
那么这里的 hbm{h^{'}} 实际上可以看成对应于LSTM中的hidden state;上一个节点传下来的 ht1bm{h^{t-1}} 则对应于LSTM中的cell state。1-z对应的则是LSTM中的 zfbm{z^f} forget gate,那么 z我们似乎就可以看成是选择门 zibm{z^i} 了。

RNN的作业布置

手动实现RNN/LSTM/GRU的结构以及BPTT算法?
运用pytorch的nn.RNN/LSTM模块搭建现成的网络?

参考文献

https://zhuanlan.zhihu.com/p/32481747
https://zybuluo.com/hanbingtao/note/581764