循环神经网络RNN以及LSTM的推导和实现

1. 从神经网络谈起

了解神经网络的都知道,神经网络作为一种非线性模型,在监督学习领域取得了state-of-art的效果,其中反向传播算法的提出居功至伟,到如今仍然是主流的优化神经网络参数的算法. 递归神经网络、卷积神经网络以及深度神经网络作为人工神经网络的"变种",仍然延续了ANN的诸多特质,如权值连接,激励函数,以神经元为计算单元等,只不过因为应用场景的不同衍生了不同的特性,如:处理变长数据、权值共享等。

为了介绍RNN,先简单的介绍ANN. ANN的结构很容易理解,一般是三层结构(输入层-隐含层-输出层). 隐含层输出 o j o_j oj 和输出层输出 o k o_k ok如下。其中 n e t j net_j netj为隐含层第 j j j个神经元的输入, u u u为输入层和隐含层的连接权值矩阵, v v v为隐含层和输出层之间的连接权值矩阵.

$ \begin{align} o_j & = f(net_j) \
o_k & = f(net_k) \
net_j & =\sum_i(x_{i}u_{i,j})+b_j \
net_k & =\sum_j(o_{j}v_{j,k})+b_k \end{align} $$

定义损失函数为 E p = 1 2 ∑ k ( o k − d k ) 2 E_p=\frac{1}{2}\sum_k (o_k - d_k)^2 Ep=21k(okdk)2 ,其中 p p p为样本下标, o k o^k ok为第 k k k个输出层神经元的输出, d k d^k dk为样本在第 k k k个编码值。然后分别对参数 v j , k v_{j,k} vj,k u i , j u_{i,j} ui,j 进行求导,可得:

KaTeX parse error: No such environment: align at position 8: \begin{̲a̲l̲i̲g̲n̲}̲ \frac{\partial…

KaTeX parse error: No such environment: align at position 8: \begin{̲a̲l̲i̲g̲n̲}̲ \frac{\partial…

从对 ∂ E p ∂ u i , j \frac{\partial E_p} {\partial u_{i,j}} ui,jEp的推导可以得到反向传播的核心思路,令误差项 β k = ∂ E p ∂ n e t k \beta_k = \frac{\partial E_p} {\partial net_k} βk=netkEp, 则有: β k = o l ( 1 − o l ) ∑ l β l w l k \beta_k=o_l(1-o_l)\sum_l\beta_lw_{lk} βk=ol(1ol)lβlwlk

反向传播的实质是基于梯度下降的优化方法,只不过在优化的过程使用了一种更为优雅的权值更新方式。

2. 循环神经网络

传统的神经网络一般都是全连接结构,且非相邻两层之间是没有连接的。一般而言,定长输入的样本很容易通过神经网络来解决,但是类似于NLP中的序列标注这样的非定长输入,前向神经网络却无能为力。

于是有人提出了循环神经网络(Recurrent Neural Network),这是一种无法像前向神经网络一样有可以具象的网络结构的模型,一般认为是网络隐层节点之间有相互作用的连接,其实质可以认为是多个具有相同结构和参数的前向神经网络的stacking, 前向神经网络的数目和输入序列的长度一致,且序列中毗邻的元素对应的前向神经网络的隐层之间有互联结构,其图示( 图片来源 )如下.

上图只是一个比较抽象的结构,下面是一个以时间展开的更为具体的结构[W,V,U略有不同,后文推荐以展开图中的参数表示为主)(图片来源).

从图中可以看出,输出层神经元的输入输出和前向神经网络中没有什么差异,仅仅在于隐层除了要接收输入层的输入外,还需要接受来自于自身的输入(可以理解为t时刻的隐层需要接收来自于t-1时刻隐层的输入, 当然这仅限于单向RNN的情况,在双向RNN还需要接受来自t+1时刻的输入).

RNN的隐层是控制信息传递的重要单元,不同时刻隐层之间的连接权值决定了过去时刻对当前时刻的影响,所以会存在时间跨度过大而导致这种影响会削弱甚至消失的现象,称之为梯度消失,改进一般都是针对隐层做文章,LSTM(控制输入量,补充新的信息然后输出),GRU(更新信息然后输出)等都是这类的改进算法.

下图为某时刻隐层单元的结构示意图(图片来源).

虽说处理的是不定长输入数据,但是某个时刻的输入还是定长的。令t时刻:输入 x t ∈ R x d i m x_t \in R^{xdim} xtRxdim ,t隐层输出 h t ∈ R h d i m h_t\in R^{hdim} htRhdim, 输出层 y t ∈ R y d i m y_t \in R^{ydim} ytRydim, RNN和CNN有着同样的共享权值的属性,输入层到隐层的权值矩阵 V ∈ R x d i m × h d i m V\in R^{xdim\times hdim} VRxdim×hdim, 隐层到输出层的权值矩阵 W ∈ R h d i m × y d i m W \in R^{hdim\times ydim} WRhdim×ydim, 不同时刻隐层自连接权值矩阵 U ∈ R h d i m × h d i m U\in R^{hdim\times hdim} URhdim×hdim1. RNN有着类似于CNN的权值共享特点,所以不同时刻的U,V,W都是相同的,所有整个网络的学习目标就是优化这些参数以及偏置. RNN和普通神经网络一样,也有超过三层的结构,下文的推导仅以三层为例.

3. RNN推导

令隐含层的激励函数$f(x)$, 输出层的激励函数为$g(x)$. 则有:

KaTeX parse error: No such environment: align at position 8: \begin{̲a̲l̲i̲g̲n̲}̲ h^t & = f(net…

对于单个样本,定义我们的cost function E t = 1 2 ∣ ∣ d t − y t ∣ ∣ 2 E^t = \frac{1}{2}||d^t- y^t ||^2 Et=21dtyt2,其中 d t d^t dt为t时刻的真实输出, y t y^t yt是t时刻的预测输出。则对权值 W j , k W_{j,k} Wj,k V i , j V_{i,j} Vi,j U j , r U_{j,r} Uj,r的求导分别如下。其中 j j j表示隐层单元下标, k k k表示输出层下标, i i i表示输入层下标, r r r表示下一时刻隐含层下标. n e t h j t net^t_{hj} nethjt表示t时刻隐层第j个神经元的加权输入, n e t y k t net^t_{yk} netykt表示t时刻输出层第k个神经元的加权输入。

KaTeX parse error: No such environment: align at position 8: \begin{̲a̲l̲i̲g̲n̲}̲ \frac{\partial…

δ y , k t \delta_{y,k}^t δy,kt为t时刻输出层y第k个神经元的误差项,令 δ h , j t \delta_{h,j}^t δh,jt为t时刻隐含层h第j个神经元的误差项, 则有:

KaTeX parse error: No such environment: align at position 8: \begin{̲a̲l̲i̲g̲n̲}̲ \delta_{y,k}^t…

所以不难得到误差方向传递时的权值计算方式:

KaTeX parse error: No such environment: align at position 8: \begin{̲a̲l̲i̲g̲n̲}̲ \frac{\partial…

写成矩阵的形式即是(其中 ⋅ \cdot 表示矩阵对应位置的元素相乘):
KaTeX parse error: No such environment: align at position 8: \begin{̲a̲l̲i̲g̲n̲}̲ \delta_{y}^t &…

上述 公式其实在了解反向传播之后就能够很容易推导,对于 W j k W_{jk} Wjk U j r U_{jr} Ujr的推导套用反向传播公式即可,而对于 V i , j V_{i,j} Vi,j需要加上来自于下一时刻的误差,如以上式子中红色部分所示.

4. RNN实现

推导出了公式,用代码实现就很简单了,可以看到前向传递和反向传播过程中的都用到了矩阵的相关运算,封装好一个矩阵计算的类,然后重载相关的运算符,便可以十分方便的进行相关的计算了。矩阵类的实现见https://github.com/kymo/SUDL/blob/master/matrix/matrix.h ,然后直接按照上述的矩阵运算方式填写代码就可以了,详见:https://github.com/kymo/SUDL/blob/master/rnn/rnn.cpp.

5. LSTM推导

相比于普通的RNN而言,LSTM无非是多了几个门结构,求导的过程略微繁琐一点,但是只要清楚当前待求导变量到输出的路径,变可以依据链式求导法则得到对应的求导公式。LSTM是为了缓解RNN的梯度弥散问题而提出的一种变种模型,之所以能够缓解这个问题,是因为在原始的RNN中,梯度的传递是乘法的过程,如果梯度很小,那么从T时刻传递到后面的梯度只会越来越小,甚至消失,在优化空间中相当于一部分参数进行更新,而另外一部分参数几乎不变,那么问题的较优解也就很难收敛到。而LSTM通过推导会发现,梯度是以一种累加的方式进行反向传递的,从而一定程度上客服了累乘导致的梯度弥散的问题。下面要推导的LSTM 是不加peelhole的结构。要推导LSTM首先要了解LSTM的几个门结构:输入门、输出门以及遗忘门。从传统的神经网络的角度来看的话,三种门分别对应了三个并行的神经网络层,如下图所示(其中蓝色和黄色表示神经元层结构,有输入、输出和相应的激励函数;红色表示向量对应项相乘;淡绿色表示向量加)。

三种门的计算方式如下:
KaTeX parse error: No such environment: align at position 7: \begin{̲a̲l̲i̲g̲n̲}̲ netf^{t} & = x…

另外,LSTM中也引入一个Cell State的中间状态,该状态有选择的保存了过去的历史信息,不会像RNN一样存在越久远的记忆越模糊的问题。该Cell State的更新方式主要是依赖于过去时刻的Cell State( c t − 1 c^{t-1} ct1)以及当前时刻产生的新的信息( c ~ t \tilde{c}^t c~t),当前产生的新的信息的计算方式如下:
KaTeX parse error: No such environment: align at position 7: \begin{̲a̲l̲i̲g̲n̲}̲ netc^{t} & = x…

遗忘门用来控制过去时刻的Cell State有多少需要被保留,输入门用来控制增加多少新的信息到Cell State中,公式表述如下:
KaTeX parse error: No such environment: align at position 7: \begin{̲a̲l̲i̲g̲n̲}̲ c^t & = f^t \c…

h t h_t ht的更新则利用了 c t c^t ct,具体如下:
KaTeX parse error: No such environment: align at position 7: \begin{̲a̲l̲i̲g̲n̲}̲ h^t & = h(c^t)…

输出层的计算方式和一般的RNN无异,令输出层、输入门、输出门、遗忘门、新cell state的误差项分别为 δ y t \delta_y^t δyt, δ i t \delta_i^t δit, δ o t \delta_o^t δot δ f t \delta_f^t δft δ c t \delta_c^t δct, 则有:

KaTeX parse error: No such environment: align at position 8: \begin{̲a̲l̲i̲g̲n̲}̲ \delta_y^t & =…
另外我们也需要定义两个新的中间变量 ϵ c t \epsilon^t_c ϵct 以及 ϵ h t \epsilon^t_h ϵht ,其值为:

KaTeX parse error: No such environment: align at position 7: \begin{̲a̲l̲i̲g̲n̲}̲ \epsilon^t_h &…

so, 另外一波公式来袭~~
KaTeX parse error: No such environment: align at position 8: \begin{̲a̲l̲i̲g̲n̲}̲ \delta_y^t & =…

okay,现在对权值进行求导,首先看 w i x wix wix ,根据链式求导法则有:
KaTeX parse error: No such environment: align at position 7: \begin{̲a̲l̲i̲g̲n̲}̲ \frac{\partial…

剩下的参数不难推知:
KaTeX parse error: No such environment: align at position 7: \begin{̲a̲l̲i̲g̲n̲}̲ \frac{\partial…

总算推完了,代码实现就很简单了~详见 https://github.com/kymo/SUDL/blob/master/rnn/lstm.cpp
对于LSTM,GRU的推导也类似,了解清楚误差传递的来源和去向,就很容易得到对当前参数的推导链式规则了.

参考资料

http://www.cnblogs.com/YiXiaoZhou/p/6058890.html http://www.cs.toronto.edu/~graves/preprint.pdf
  • 9
    点赞
  • 50
    收藏
    觉得还不错? 一键收藏
  • 12
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 12
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值