现实中很多数据具有时间、空间等方面的序列特征,数据序列的前后部分具有逻辑上的关系,神经网络的研究者针对这类数据设计了RNN(循环神经网络)模型。对于经常使用手机和上网的我们来说,RNN其实无时无刻不存在我们身边,因为RNN已经被用于语音识别,机器翻译,股票预测,智能问答等领域,甚至图像识别的某些方面也会用到RNN,例如图像文本检测识别,以及视频检测。第一次打电话订餐与一位智能机器人对话时还有一点兴奋和紧张,不过默认接通机器人有时很不方便,想接通人工服务也是很有意思,因为目前机器人的应答还不是很智能,只要有一次知道了接通人工服务的“暗号”,下一次只要说这句话就可以触发真人接通服务了,?~
接下来通俗理解主要来自如何深度理解RNN?——看图就好!,这一部分基本上没有公式,用形象化的表示展现了RNN涉及的几个问题,序列结构,网络形式,梯度消失,对后面公式形式推导的理解有很大的帮助。
RNN 是一种层内神经元之间形成有向环连接的神经网络模型,擅长对序列数据进行建模处理。序列数据有很多种形式,音频是一种自然的序列,如下图,可以将音频频谱图分成块并将其馈入RNN.文本也是一种形式的序列,英语根据语法将单词组合成有意义的句子,说明不同的单词序列得到的信息是不同的
RNN有顺序存储的概念,就像我们的大脑能够自然而然记住已经练习过的序列,RNN也是如此。我们需要知道RNN是如何学习顺序存储的。首先一个传统的神经网络如下左图,也称为前馈神经网络,它包含输入层,隐藏层和输出层。如果在神经网络中添加一个传递先前信息的循环,以便以前的信息能够影响以后的信息,就会变成如下中图。
这基本上就是一个递归神经网络了,RNN让循环机制充当高速公路以允许信息从一个步骤流到下一个步骤。hidden state是先前输入的表示,也会对输出有影响。
假设我们想要构建一个聊天机器人,该聊天机器人可以根据用户输入的文本对意图进行分类。
为了解决这个问题。首先,我们将使用RNN对文本序列进行编码。然后,我们将RNN输出馈送到前馈神经网络中,该网络将对用户输入意图进行分类。
假设用户输入:what time is it?首先,我们将句子分解为单个单词。RNN按顺序工作,所以我们一次只能输入一个字。
第一步是将“What”输入RNN,RNN编码“what”并产生输出
对于下一步,我们提供单词“time”和上一步中的隐藏状态。RNN现在有关于“what”和“time”这两个词的信息。
由于最终输出是从序列的部分创建的,因此我们应该能够获取最终输出并将其传递给前馈层以对意图进行分类。
对于那些喜欢在这里查看代码的人来说,使用python展示了控制流程应该是最好的方式。
首先,初始化网络层和初始隐藏状态。隐藏状态的形状和维度将取决于你的递归神经网络的形状和维度。然后循环输入,将单词和隐藏状态传递给RNN。RNN返回输出和修改的隐藏状态,接着就继续循环。最后,将输出传递给前馈层,然后返回预测。整个过程就是这样!进行递归神经网络的正向传递的控制流程是for循环。
我们看到隐藏状态到最后颜色分布很奇怪,这是为了说明RNN短时记忆的问题。
短期记忆问题是由臭名昭着的梯度消失问题引起的,这在其他神经网络架构中也很普遍。由于RNN处理很多步骤,因此难以保留先前步骤中的信息。正如你所看到的,在最后的时间步骤中,“what”和“time”这个词的信息几乎不存在。短期记忆和梯度消失是由于反向传播的性质引起的,反向传播是用于训练和优化神经网络的算法。为了理解这是为什么,让我们来看看反向传播对深度前馈神经网络的影响。
训练神经网络有三个主要步骤,如下左图所示。首先,它进行前向传递并进行预测。然后,它使用损失函数将预测与基础事实进行比较。损失函数输出一个错误值,该错误值是对网络执行得有多糟糕的估计。最后,它使用该误差值计算网络中每个节点的梯度,进行反向传播,调整网络参数。
梯度是用于调整网络内部权重的值,以便能更新整个网络。梯度越大,调整越大,反之亦然,这也就是问题所在。在进行反向传播时,图层中的每个节点都会根据渐变效果计算它在其前面的图层中的渐变。因此,如果在它之前对层的调整很小,那么对当前层的调整将更小。
这会导致渐变在向后传播时呈指数级收缩。由于梯度极小,内部权重几乎没有调整,因此较早的层无法进行任何学习。这就是消失的梯度问题。
循环神经网络中这种梯度消失是什么样的呢?可以将循环神经网络中的每个时间步骤视为一个层。为了训练一个递归神经网络,你使用了一种称为通过时间反向传播的方法。这样梯度值在每个时间步长传播时将呈指数级收缩。
同样,梯度值将用于在神经网络权重中进行调整,从而允许其学习。小的渐变意味着小的调整。这将导致最前面的层没有优化。由于梯度消失,RNN不会跨时间步骤学习远程依赖性。这意味着在尝试预测用户的意图时,有可能不考虑“what”和“time”这两个词。然后网络就可能作出的猜测是“is it?”。这很模糊,即使是人类也很难辨认这到底是什么意思。因此,无法在较早的时间步骤上学习会导致网络具有短期记忆。
RNN模型不属于前馈神经网络,主要特点是隐藏层的输出不仅连接到下一层,而且还连接到自身,这种连接到自身的特点构成了数据的循环。通常RNN模型的输入和输出都具有“时序性”。为了表达RNN模型的“循环”特性,可以将其按照输入序列的长度展开。展开后,RNN可以看作由一系列核心模块(RNN单元)形成的二维阵列,在该阵列中,前一时刻与后一时刻的RNN单元相互连接,上一层与下一层的RNN单元相互连接。在RNN单元内部,我们可以设计出各种复杂的计算流程,从而构造出不同的模型,满足不同场景需求。
假设一个普通的全连接网络如图1.1左图所示,输入为 N N N个节点,即 x = ( x 1 , x 2 , ⋯   , x N ) {{x}}=({{x}_{1}},{{x}_{2}},\cdots ,{{x}_{N}}) x=(x1,x2,⋯,xN),隐藏层有 M M M个节点,即 h = ( h 1 , h 2 , ⋯   , h M ) {{h}}=({{h}_{1}},{{h}_{2}},\cdots ,{{h}_{M}}) h=(h1,h2,⋯,hM),输出层有 k k k个节点,那么经过一个隐藏层 h h h之后,得到 h = f ( U x ) h = f(Ux) h=f(Ux),然后经过下一层到达输出层 o o o,即 o = f ( V s ) o = f(Vs) o=f(Vs)。这是一个完整的全连接网络,将节点隐藏就会变成图1.1右图黄色框框中的样子,RNN网络模型多了一个循环隐藏层,用于学习之前序列对输出的影响。
简单RNN有三层:输入层、循环隐藏层和输出层,如图1.1右图所示。图1.1右图左侧是RNN模型的抽象表示,将时间维度进行了压缩,其中 x x x是输入,将输入单元与隐藏层中的隐藏单元全连接,该连接由权重矩阵 U U U控制,根据输入单元与权重矩阵 U U U得到隐含层的值; W W W则是上个时刻隐含层的值作为这个时刻输入对应的权重; V V V是隐含层到输出层的权重, o o o是输出。
将时间维度展开以后,更能方便理解,这时输入 x x x、隐层值 s s s和输出 o o o都有了下标 t t t, x x x是一系列沿时间 t t t的向量 ​​ { ​​ ⋯ x t − 1 , x t , x t + 1 , ⋯ ​​ } ​​ \text{ }\!\!\{\!\!\text{ }\cdots {{\text{x}}_{t-1}}\text{,}{{\text{x}}_{t}}\text{,}{{\text{x}}_{t+1}}\text{,}\cdots \text{ }\!\!\}\!\!\text{ } { ⋯xt−1,xt,xt+1,⋯ } ,其中 x t = ( x 1 , x 2 , ⋯   , x N ) {{x}_{t}}=({{x}_{1}},{{x}_{2}},\cdots ,{{x}_{N}}) xt=(x1,x2,⋯,xN) ,隐藏层有 M M M个隐藏单元 h t = ( h 1 , h 2 , ⋯   , h M ) {{h}_{t}}=({{h}_{1}},{{h}_{2}},\cdots ,{{h}_{M}}) ht=(h1,h2,⋯,hM),这个 t t t表示时刻, t − 1 t-1 t−1是上一时刻, t + 1 t+1 t+1则是下一时刻。不同时刻输入对应不同的输出,而且上一时刻的隐含层会影响当前时刻的输出。它们通过网络定义的循环结构沿时间彼此连接。使用较小非零元素的隐藏单元初始化能够提升网络的整体性能和稳定性。
从公式上来说,原来 h = f ( U x ) h = f(Ux) h=f(Ux),但是现在如果要求当前时刻的输出 h t h_t ht,还要加上上一时刻 h t − 1 h_{t-1} ht−1输出的影响 W h t − 1 Wh_{t-1} Wht−1,再加上当前时刻偏置 b t b_t bt【偏置在神经网络中的作用】,状态空间的记忆单元就可以被隐藏层定义为:
h t = f ( s t ) ( 1 − 1 ) h_t = f(s_t)\quad\quad (1-1) ht=f(st)(1−1) s t = U x t + W h t − 1 + b t ( 1 − 2 ) {{s}_{t}}=U{{x}_{t}}+W{{h}_{t-1}}\text{+}{{b}_{t}}\quad\quad (1-2) st=Uxt+Wht−1+bt(1−2) 其中 f f f是激活函数, h t {{h}_{t}} ht是隐含层的输入, W W W为隐藏单元的权重矩阵, b t {{b}_{t}} bt为隐藏单元的偏置向量。
设输出层的输入为 y t {{y}_{t}} yt,则很容易可以得到输出:
y t = V h t + b o ( 1 − 3 ) {{y}_{t}}=V{h}_{t}\text{+}{{b}_{o}}\quad\quad (1-3) yt=Vht+bo(1−3) o t = f ( y t ) ( 1 − 4 ) {{o}_{t}}=f({{y}_{t}})\quad\quad (1-4) ot=f(yt)(1−4) 其中 f f f是激活函数, b o {{b}_{o}} bo是输出层的偏置向量, y t o y_{t}^{o} yto是网络的输出。由于“输入-目标对”是沿时间的序列,因此上述步骤随着时间 t = ( 1 , 2 , ⋯   , T ) t=(1,2,\cdots ,T) t=(1,2,⋯,T)重复。公式(1-1)和(1-3)显示了RNN由特定非线性状态公式构成,该公式沿时间迭代。在每个时间步中,隐藏状态根据输入向量预测输出。RNN的隐藏状态是一组值的集合(除去任何外部因素的影响),该集合总结了与该网络在之前很多时间步上的状态相关的必要信息。这个集合可定义该网络的未来行为,作出准确的输出预测。虽然RNN在每个单元中仅仅使用一个简单的非线性激活函数。但是,如果此类简单结构沿时间步经过良好训练,则它能够建模丰富的动态关系,可以学习到前面很久的序列信息: h t = f ( s t ) = f ( U x t + W f ( U x t − 1 + W h t − 2 + b t − 1 ) + b t ) ⋯ ( 1 − 5 ) h_{t}=f\left(s_{t}\right)=f\left(U x_{t}+W f\left(U x_{t-1}+Wh_{t-2}+b_{t-1}\right)+b_t\right)\cdots \quad\quad (1-5) ht=f(st)=f(Uxt+Wf(Uxt−1+Wht−2+bt−1)+bt)⋯(1−5)
上述机器人翻译的例子中,是对“What time is it?”进行翻译,首先,我们将句子分解为单个单词。RNN按顺序工作,所以我们一次只能输入一个字。第一步是将“What”对应的原始特征向量 x 1 x_1 x1(可能是词向量)输入RNN,RNN编码“what”并产生输出,其中隐藏状态为 h 1 = f ( U x 1 + b h 1 ) h_1 = f(Ux_1+bh_1) h1=f(Ux1+bh1),输出为 o 1 = f ( V h 1 + b o 1 ) o_1 = f(Vh_1+bo_1) o1=f(Vh1+bo1).
对于下一步,我们提供单词“time”对应的原始特征向量 x 2 x_2 x2和上一步中的隐藏状态 h 1 h_1 h1。RNN现在有关于“what”和“time”这两个词的信息,隐藏层状态为 h 2 = f ( U x 2 + W h 1 + b h 2 ) h_2 = f(Ux_2+Wh_1+bh_2) h2=f(Ux2+Wh1+bh2),输出层状态为 o 2 = f ( V h 2 + b o 2 ) o_2 = f(Vh_2+bo_2) o2=f(Vh2+bo2)。
我们重复这个过程,直到最后一步。通过最后一步看到RNN编码了前面步骤中所有单词的信息。
非线性函数比线性函数强大,因为它们可以绘制非线性边界。RNN中一个或多个连续隐藏层中的非线性是学习“输入-目标关系”的关键。
Sigmoid函数是常用的激活函数,它将真值归一化到[0,1]区间。该激活函数主要用于输出层;Tanh激活函数实际上是缩放的Sigmoid函数;ReLU是另一个常用激活函数,向正输入值开放。
激活函数的选择主要取决于具体问题和数据本身。
sigmoid函数仅适合输出区间为[0,1]的网络,且存在两个缺点,第一,sigmoid函数会使神经元快速饱和,导致梯度消失问题;第二,sigmoid的输出不以零为中心会导致不稳定的权重梯度更新。tanh也存在上述缺点。
与Sigmoid函数和tanh函数相比,ReLU激活有两个优点:第一,ReLU函数导致更加稀疏的梯度,并大幅加快随机梯度下降(SGD)的收敛速度;第二,因其可通过将激活值二值化为零,所以ReLU函数的计算成本低廉;但是,ReLU无法抵抗大型梯度流(gradient flow),随着权重矩阵增大,神经元可能在训练过程中保持未激活状态。
损失函数的挑选因具体问题而异,一般比较流行的损失函数包括预测实数值的欧几里德距离和 Hamming距离,和用于分类问题的交叉熵损失函数。
设某时刻的损失函数 E t = 1 2 ( y d − y t o ) 2 E_{t}=\frac{1}{2}\left(y_{d}-y_{t}^{o}\right)^{2} Et=21(yd−yto)2,通过对比输出 y t o y_{t}^{o} yto和目标 y d y_{d} yd之间的差距而评估了神经网络的性能,则最终损失函数为对每一个时间步上的损失进行求和: E = ∑ t = 1 T E t ( 1 − 6 ) E=\sum_{t=1}^{T} E_{t}\quad\quad (1-6) E=t=1∑TEt(1−6)
RNN使用BPTT方法训练,BPTT实质上就是朴素的BP算法,采的“链式法则”求解参数梯度,唯一的不同在于每一个time和step上参数共享。从数学的角度来讲,BP算法是一个单变量求导过程,而BPTT算法是一个复合函数求导过程。BPTT通过三个主要步骤进行求解:
通过上述公式可以看到在对权重矩阵W求导的时候,因为要追溯到之前时刻的状态,所以会产生连乘操作,当W的值很小时,连乘可能会导致梯度消失,当W很大时,连乘会造成梯度爆炸。
解决方法:
LSTM即Long Short Memory Network,长短时记忆网络,是RNN网络的一种变体,可以说它克服了RNN无法很好处理远距离依赖问题。
LSTM通过累加的形式改变了使用链式求导法则会导致梯度变为连乘的问题,从而增加网络记忆长度。但是其重复网络模块的结构则复杂很多,它实现了三个门计算,即遗忘门、输入门和输出门。实际上简单来说可以看作LSTM增加了一个状态 c c c来保持长期的状态,成为单元状态。
这时就有一个关键问题,如何控制长期状态 c c c,实现的方法就是刚刚提到的LSTM实现了三个门做控制开关,第一个是遗忘门控开关,控制继续保持长期状态 c c c,因此遗忘门负责决定保留多少上一时刻的单元状态到当前时刻的单元状态。第二个门是输入门开关,负责控制把当前时刻的状态输入到长期状态 c c c,因此输入门负责决定保留多少当前时刻的输入到当前时刻的单元状态。第三个门是输出门,负责控制是否把长期状态 c c c作为当前LSTM的输出,所以输出门负责决定当前时刻的单元状态有多少输出。
那么门是什么呢,我认为就与神经元的激活函数道理是一样的,看后面公式我们可以知道,gate就是一个全连接层, g ( x ) = σ ( W x + b ) g(x) = \sigma(Wx+b) g(x)=σ(Wx+b),输入是一个向量,输出经过sigmoid处理后是0-1之间的实数向量,1 表示全部保留,0表示全部忘记。
每个LSTM包含了三个输入,即上一时刻的单元状态 c t − 1 c_{t-1} ct−1、上一时刻LSTM的输出 h t − 1 h_{t-1} ht−1和当前时刻输入 x t x_t xt。
遗忘门:
用来计算上一时刻输出 h t − 1 h_{t-1} ht−1和这一时刻输入 x t x_t xt中哪些信息需要忘记。于是有 f t = σ ( W f ⋅ [ h t − 1 , x t ] + b f ) = σ ( W f h h t − 1 + W f x x t + b f ) = σ ( n e t f , t ) ( 1 − 13 ) f_{t}=\sigma\left(W_{f} \cdot\left[h_{t-1}, x_{t}\right]+b_{f}\right) = \sigma(W_{f h} \mathbf{h}_{t-1}+W_{f x} \mathbf{x}_{t}+\mathbf{b}_{f})=\sigma(\mathbf{n e t}_{f, t})\quad\quad(1-13) ft=σ(Wf⋅[ht−1,xt]+bf)=σ(Wfhht−1+Wfxxt+bf)=σ(netf,t)(1−13) 其中,中括号表示两个向量相连合并, W f W_f Wf表示遗忘门的权重矩阵, σ \sigma σ为sigmoid函数, b f b_f bf为遗忘门的偏置项。设输入层的维度为 d x d_x dx,隐藏层维度为 d h d_h dh,上一时刻的单元状态 c t − 1 c_{t-1} ct−1维度为 d c d_c dc,则 W f W_f Wf维度为 d e × ( d h + d x ) d_{e} \times\left(d_{h}+d_{x}\right) de×(dh+dx), n e t f , t \mathbf{n e t}_{f, t} netf,t表示遗忘门的输入。
输入门:
用来计算哪些信息保存都状态单元中,看图1.5的划分可以看到,输入门分成两部分,第一部分可以看作当前输入有多少保存到单元状态之中,表示为:
i t = σ ( W i ⋅ [ h t − 1 , x t ] + b i ) = σ ( W i h h t − 1 + W i x x t + b i ) = σ ( n e t i , t ) ( 1 − 14 ) {{i}_{t}}=\sigma ({{W}_{i}}\cdot [{{h}_{t-1}},{{x}_{t}}]+{{b}_{i}})= \sigma(W_{i h} \mathbf{h}_{t-1}+W_{i x} \mathbf{x}_{t}+\mathbf{b}_{i})=\sigma(\mathbf{n e t}_{i, t})\quad\quad(1-14) it=σ(Wi⋅[ht−1,xt]+bi)=σ(Wihht−1+Wixxt+bi)=σ(neti,t)(1−14)
另一部分可以看作当前输入产生多少新信息添加到单元状态之中,表示为:
c ‾ t = tanh ( W c ‾ ⋅ [ h t − 1 , x t ] + b c ‾ ) = σ ( W c ‾ h h t − 1 + W c ‾ x x t + b c ‾ ) = σ ( n e t c ‾ , t ) ( 1 − 15 ) \overline{c}_{t}=\tanh \left(W_{\overline{c}} \cdot\left[h_{t-1}, x_{t}\right]+b_{\overline{c}}\right)= \sigma(W_{\overline{c} h} \mathbf{h}_{t-1}+W_{\overline{c} x} \mathbf{x}_{t}+\mathbf{b}_{\overline{c}})=\sigma(\mathbf{n e t}_{\overline{c}, t})\quad\quad(1-15) ct=tanh(Wc⋅[ht−1,xt]+bc)=σ(Wchht−1+Wcxxt+bc)=σ(netc,t)(1−15)
结合这两部分来创建一个新记忆。当前时刻的单元状态由遗忘门输出和上一时刻状态的积加上输入门两部分的积,即 c t = f t ∗ c t − 1 + i t ∗ c ‾ t ( 1 − 16 ) c_{t}=f_{t}^{*} c_{t-1}+i_{t} * \overline{c}_{t}\quad\quad(1-16) ct=ft∗ct−1+it∗ct(1−16)输出门:
通过sigmoid函数计算需要输出哪些信息,再乘以当前单元状态通过tanh函数的值,得到输出。
o t = σ ( W o ⋅ [ h t − 1 , x t ] + b o ) = σ ( W o h h t − 1 + W o x x t + b o ) = σ ( n e t o , t ) ( 1 − 17 ) o_{t}=\sigma\left(W_{o} \cdot\left[h_{t-1}, x_{t}\right]+b_{o}\right)= \sigma(W_{o h} \mathbf{h}_{t-1}+W_{o x} \mathbf{x}_{t}+\mathbf{b}_{o})=\sigma(\mathbf{n e t}_{o, t})\quad\quad(1-17) ot=σ(Wo⋅[ht−1,xt]+bo)=σ(Wohht−1+Woxxt+bo)=σ(neto,t)(1−17) h t = o t ∗ tanh ( c t ) ( 1 − 18 ) h_{t}=o_{t}{*} \tanh \left(c_{t}\right)\quad\quad(1-18) ht=ot∗tanh(ct)(1−18)
最后,输出层的输入 y t i = W y i h t y_{t}^{i}={{W}_{yi}}{{h}_{t}} yti=Wyiht ,输出为 y t o = σ ( y t i ) y_{t}^{o}=\sigma (y_{t}^{i}) yto=σ(yti)。
设某时刻的损失函数为 E t = 1 2 ( y d − y t 0 ) 2 E_{t}=\frac{1}{2}\left(y_{d}-y_{t}^{0}\right)^{2} Et=21(yd−yt0)2,则某样本的损失为:
E = ∑ t = 1 T E t ( 1 − 20 ) E=\sum_{t=1}^{T} E_{t}\quad\quad(1-20) E=t=1∑TEt(1−20)
LSTM使用BPTT算法进行训练,与普通RNN训练方法相同。
从LSTM的前向传播可以看到,需要学习很多权重参数,同时也可以看到LSTM的输出 h t h_t ht有四个输入分量加权影响,即三个门相关的 f t , i t , c ˉ t , o t {{f}_{t}},{{i}_{t}},{{\bar{c}}_{t}},{{o}_{t}} ft,it,cˉt,ot ,而且其中权重 W W W都是拼接的,所以在学习时需要分割出来,即:
W f = W f x + W f h W i = W i x + W i h W c ‾ = W c ‾ x + W c ‾ h W o = W o x + W o h ( 1 − 19 ) \begin{aligned} W_{f} &=W_{f x}+W_{f h} \\ W_{i} &=W_{i x}+W_{i h} \\ W_{\overline{c}} &=W_{\overline{c} x}+W_{\overline{c} h} \\ W_{o} &=W_{o x}+W_{o h} \end{aligned} \quad\quad(1-19) WfWiWcWo=Wfx+Wfh=Wix+Wih=Wcx+Wch=Wox+Woh(1−19)
这时可以明确要学习的参数有,分割出来的八个权重矩阵以及 f t , i t , c ˉ t , o t {{f}_{t}},{{i}_{t}},{{\bar{c}}_{t}},{{o}_{t}} ft,it,cˉt,ot对应的偏置向量 b f , b i , b c ‾ , b o b_f,b_i,b_{\overline {c}},b_o bf,bi,bc,bo,以及最后输出层的权重矩阵 W y i W_{yi} Wyi,所以要根据输出得到与他们相关的误差项。
将误差沿时间反向传递
设当前时刻 t t t的误差项 δ t = ∂ E ∂ h t \delta_{t}=\frac{\partial E}{\partial h_{t}} δt=∂ht∂E,那么误差沿时间反向传递就需要计算 t − 1 t-1 t−1时刻的误差项 δ t − 1 \delta_{t-1} δt−1,则
δ t − 1 = ∂ E ∂ h t − 1 = ∂ E ∂ h t ∂ h t ∂ h t − 1 = δ t ∂ h t ∂ h t − 1 ( 1 − 20 ) \delta_{t-1}=\frac{\partial E}{\partial h_{t-1}}=\frac{\partial E}{\partial h_{t}} \frac{\partial h_{t}}{\partial h_{t-1}}=\delta_{t} \frac{\partial h_{t}}{\partial h_{t-1}}\quad\quad(1-20) δt−1=∂ht−1∂E=∂ht∂E∂ht−1∂ht=δt∂ht−1∂ht(1−20)
∂ h t ∂ h t − 1 \frac{\partial h_{t}}{\partial h_{t-1}} ∂ht−1∂ht是一个Jacobian矩阵。如果隐藏层h的维度是N的话,那么它就是一个 N × N N\times N N×N矩阵。LSTM的数输出 h t h_t ht可以看成是一个复合函数, f [ f t ( h t − 1 ) , i t ( h t − 1 ) , c ‾ t ( h t − 1 ) , o t ( h − 1 ) ] f\left[f_{t}\left(h_{t-1}\right), i_{t}\left(h_{t-1}\right), \overline{c}_{t}\left(h_{t-1}\right), o_{t}\left(h_{-1}\right)\right] f[ft(ht−1),it(ht−1),ct(ht−1),ot(h−1)],因为 f t , i t , c ˉ t , o t {{f}_{t}},{{i}_{t}},{{\bar{c}}_{t}},{{o}_{t}} ft,it,cˉt,ot都是 h t − 1 h_{t-1} ht−1的函数, 由全导数公式有
δ t ∂ h t ∂ h t − 1 = δ t ∂ h t ∂ c t ∂ c t ∂ f t ∂ f t ∂ n e t f t ∂ n e t f t ∂ h t − 1 + δ t ∂ h t ∂ c t ∂ c t ∂ i t ∂ i t ∂ n e t i t ∂ n e t i t ∂ h t − 1 + δ t ∂ h t ∂ c t ∂ c t ∂ c ‾ t ∂ c ‾ t ∂ n e t c ‾ t ∂ n e t c ‾ t ∂ h t − 1 + δ t ∂ h t ∂ o t ∂ o t ∂ n e t o t ∂ n e t o t ∂ h t − 1 ( 1 − 21 ) \delta_{t} \frac{\partial h_{t}}{\partial h_{t-1}}=\delta_{t} \frac{\partial h_{t}}{\partial c_{t}} \frac{\partial c_{t}}{\partial f_{t}} \frac{\partial f_{t}}{\partial n e t_{f t}} \frac{\partial n e t_{f t}}{\partial h_{t-1}}+\delta_{t} \frac{\partial h_{t}}{\partial c_{t}} \frac{\partial c_{t}}{\partial i_{t}} \frac{\partial i_{t}}{\partial n e t_{i t}} \frac{\partial n e t_{it}}{\partial h_{t-1}}\\ \quad\quad\quad\quad\quad\quad\quad\quad +\delta_{t} \frac{\partial h_{t}}{\partial c_{t}} \frac{\partial c_{t}}{\partial \overline{c}_{t}} \frac{\partial \overline{c}_{t}}{\partial n e t_{ \overline{c} t}} \frac{\partial n e t_{ \overline{c}t}}{\partial h_{t-1}}+\delta_{t} \frac{\partial h_{t}}{\partial o_{t}} \frac{\partial o_{t}}{\partial n e t_{o t}} \frac{\partial n e t_{ot}}{\partial h_{t-1}}\quad\quad(1-21) δt∂ht−1∂ht=δt∂ct∂ht∂ft∂ct∂netft∂ft∂ht−1∂netft+δt∂ct∂ht∂it∂ct∂netit∂it∂ht−1∂netit+δt∂ct∂ht∂ct∂ct∂netct∂ct∂ht−1∂netct+δt∂ot∂ht∂netot∂ot∂ht−1∂netot(1−21)
将上述所有偏导都求出来【注:函数: f ( z ) = t a n h ( z ) f(z) = tanh(z) f(z)=tanh(z) 导数: f ( z ) ′ = 1 − ( f ( z ) ) 2 f(z)' = 1 − (f(z))^2 f(z)′=1−(f(z))2】:
∂ h t ∂ o t = t a n h ( c t ) ∂ h t ∂ c t = o t ∗ ( 1 − tanh ( c t ) 2 ) ∂ c t ∂ f t = c t − 1 ∂ f t ∂ n e t f , t = f t ∗ ( 1 − f t ) ∂ n e t f , t ∂ h t − 1 = W f h ∂ c t ∂ i t = c ‾ t ∂ i t ∂ n e t i , t = i t ∗ ( 1 − i t ) ∂ n e t i , t ∂ h t − 1 = W i h ∂ c t ∂ c ‾ t = i t ∂ c ‾ t ∂ n e t c ‾ , t = ( 1 − c ‾ t 2 ) ∂ n e t c ‾ , t ∂ h t − 1 = W c ‾ h ∂ o t ∂ n e t o t = o t ∗ ( 1 − o t ) ∂ n e t o , t ∂ h t − 1 = W o h ( 1 − 22 ) \begin{array}{l} {\frac{\partial \mathbf{h}_{\mathrm{t}}}{\partial \mathbf{o}_{t}} = tanh(c_t)\quad\quad \frac{\partial h_{t}}{\partial c_{t}}=o_{t} *\left(1-\tanh \left(c_{t}\right)^{2}\right)} \\ { \frac{\partial c_{t}}{\partial f_{t}}=c_{t-1} \quad\quad \frac{\partial f_{t}}{\partial n e t_{f, t}}=f_{t}{*}\left(1-f_{t}\right) \quad\quad \frac{\partial n e t_{f, t}}{\partial h_{t-1}}=W_{f h} }\\ { \frac{\partial c_{t}}{\partial i_{t}}=\overline{c}_{t} \quad\quad \frac{\partial i_{t}}{\partial n e t_{i, t}}=i_{t}{*}\left(1-i_{t}\right) \quad\quad \frac{\partial n e t_{i, t}}{\partial h_{t-1}}=W_{i h}}\\ { \frac{\partial c_{t}}{\partial \overline{c}_{t}}=i_{t} \quad\quad \frac{\partial \overline{c}_{t}}{\partial n e t_{\overline{c}, t}}=(1-\overline{c}_t^2) \quad\quad \frac{\partial n e t_{\overline{c}, t}}{\partial h_{t-1}}=W_{\overline{c} h}}\\ { \frac{\partial o_{t}}{\partial net_{o t}}=o_{t}{*}\left(1-o_{t}\right) \quad\quad \frac{\partial n e t_{o, t}}{\partial h_{t-1}}=W_{o h}}\end{array} \quad\quad(1-22) ∂ot∂ht=tanh(ct)∂ct∂ht=ot∗(1−tanh(ct)2)∂ft∂ct=ct−1∂netf,t∂ft=ft∗(1−ft)∂ht−1∂netf,t=Wfh∂it∂ct=ct∂neti,t∂it=it∗(1−it)∂ht−1∂neti,t=Wih∂ct∂ct=it∂netc,t∂ct=(1−ct2)∂ht−1∂netc,t=Wch∂netot∂ot=ot∗(1−ot)∂ht−1∂neto,t=Woh(1−22)
再设:
δ f , t = ∂ E ∂ n e t f , t , δ i , t = ∂ E ∂ n e t i , t , δ c ‾ , t = ∂ E ∂ n e t c ‾ , t , δ o , t = ∂ E ∂ n e t o , t \delta_{f, t}=\frac{\partial E}{\partial n e t_{f, t}} ,\quad \delta_{i, t}=\frac{\partial E}{\partial n e t_{i, t}} ,\quad \delta_{\overline{c}, t}=\frac{\partial E}{\partial n e t_{\overline{c}, t}} ,\quad \delta_{o, t}=\frac{\partial E}{\partial n e t_{o, t}} δf,t=∂netf,t∂E,δi,t=∂neti,t∂E,δc,t=∂netc,t∂E,δo,t=∂neto,t∂E
根据求出来的所有偏导可以知道 δ o , t = δ t × tanh ( c t ) × o t × ( 1 − o t ) δ f , t = δ t × o t × ( 1 − tanh ( c t ) 2 ) × c t − 1 × f t × ( 1 − f t ) δ i , t = δ t × o t × ( 1 − tanh ( c t ) 2 ) × c ‾ t × i t × ( 1 − i t ) δ c ‾ , t = δ t × o t × ( 1 − tanh ( c t ) 2 ) × i t × ( 1 − c ‾ t 2 ) ( 1 − 23 ) \begin{array}{l} {\delta_{o, t}=\delta_{t} \times \tanh \left(\mathbf{c}_{t}\right) \times \mathbf{o}_{t} \times\left(1-\mathbf{o}_{t}\right)} \\ {\delta_{f, t}=\delta_{t} \times \mathbf{o}_{t} \times \left(1-\tanh \left(\mathbf{c}_{t}\right)^{2}\right) \times \mathbf{c}_{t-1} \times \mathbf{f}_{t} \times \left(1-\mathbf{f}_{t}\right)} \\{ \delta_{i, t}=\delta_{t} \times \mathbf{o}_{t} \times \left(1-\tanh \left(\mathbf{c}_{t}\right)^{2}\right) \times \overline{c}_t \times \mathbf{i}_{t} \times \left(1-\mathbf{i}_{t}\right)} \\{ \delta_{\overline{c}, t}=\delta_{t} \times \mathbf{o}_{t} \times \left(1-\tanh \left(\mathbf{c}_{t}\right)^{2}\right) \times \mathbf{i}_{t} \times\left(1-\overline{c}_t^{2}\right)}\end{array} \quad\quad(1-23) δo,t=δt×tanh(ct)×ot×(1−ot)δf,t=δt×ot×(1−tanh(ct)2)×ct−1×ft×(1−ft)δi,t=δt×ot×(1−tanh(ct)2)×ct×it×(1−it)δc,t=δt×ot×(1−tanh(ct)2)×it×(1−ct2)(1−23)
将式(1-22)(1-23)带入(1-21)得到:
δ t − 1 = δ t ∂ h t ∂ h t − 1 = δ o , t ∂ n e t o , t ∂ h t − 1 + δ f , t ∂ n e t f , t ∂ h t − 1 + δ i , t ∂ n e t i , t ∂ h t − 1 + δ c ‾ , t ∂ n e t c ‾ , t ∂ h t − 1 = δ f , t W f h + δ i , t W i h + δ c ‾ , t W c ‾ h + δ o , t W o h ( 1 − 24 ) \delta_{t-1}=\delta_{t} \frac{\partial h_{t}}{\partial h_{t-1}}\quad\quad\quad\quad\quad\quad\quad\quad\quad\quad\quad\quad\quad\quad\quad\quad\quad\quad\quad\quad\\= \delta_{o, t}\frac{\partial \mathbf{n} e t_{o, t}}{\partial \mathbf{h}_{\mathrm{t}-1}}+\delta_{f, t}\frac{\partial \mathbf{n} e t_{f, t}}{\partial \mathbf{h}_{\mathrm{t}-1}}+\delta_{i, t}\frac{\partial \mathbf{n} e t_{i, t}}{\partial \mathbf{h}_{\mathrm{t}-1}}+\delta_{\overline{c}, t}\frac{\partial \mathbf{n} e t_{\overline{c}, t}}{\partial \mathbf{h}_{\mathrm{t}-1}}\\ =\delta_{f, t} W_{f h}+\delta_{i, t} W_{i h}+\delta_{\overline{c}, t} W_{\overline{c} h}+\delta_{o, t} W_{o h}\quad\quad(1-24) δt−1=δt∂ht−1∂ht=δo,t∂ht−1∂neto,t+δf,t∂ht−1∂netf,t+δi,t∂ht−1∂neti,t+δc,t∂ht−1∂netc,t=δf,tWfh+δi,tWih+δc,tWch+δo,tWoh(1−24)
式(1-23)(1-24)就是将误差沿时间反向传播一个时刻的公式。有了它,我们可以写出将误差项向前传递到任意 k k k时刻的公式:
δ k = ∏ j = k t − 1 δ o , j W o h + δ f , j W f h + δ i , j W i h + δ c ‾ , j W c ‾ h ( 1 − 25 ) \delta_{k}=\prod_{j=k}^{t-1} \delta_{o, j}W_{o h}+\delta_{f, j}W_{f h}+\delta_{i, j} W_{i h}+\delta_{\overline{c}, j}W_{\overline{c} h}\quad\quad(1-25) δk=j=k∏t−1δo,jWoh+δf,jWfh+δi,jWih+δc,jWch(1−25)
将误差项传递到上一层
我们假设当前为第 l l l层,定义 l − 1 l-1 l−1层的误差项是误差函数对 l − 1 l-1 l−1层加权输入的导数,即:
δ t l − 1 = ∂ E net t l − 1 ( 1 − 26 ) \delta_{t}^{l-1} = \frac{\partial E}{\operatorname{net}_{t}^{l-1}}\quad\quad(1-26) δtl−1=nettl−1∂E(1−26)
本次LSTM的输入 x t x_t xt由下面的公式计算:
x t l = f l − 1 ( n e t t l − 1 ) ( 1 − 27 ) \mathbf{x}_{t}^{l}=f^{l-1}\left(\mathbf{n e t}_{t}^{l-1}\right)\quad\quad(1-27) xtl=fl−1(nettl−1)(1−27)
其中 f l − 1 f^{l-1} fl−1为第 l − 1 l-1 l−1层的激活函数。因为 n e t f , t l , net_{f, t}^{l}, netf,tl, net i , t l , _{i, t}^{l}, i,tl, net c ~ , t l , _{\tilde{c}, t}^{l}, c~,tl, net o , t l _{o, t}^{l} o,tl都是 x t x_t xt的函数, x t x_t xt又是 n e t t l − 1 net_t^{l-1} nettl−1的函数,因此,要求出E对 n e t t l − 1 net_t^{l-1} nettl−1的导数,就需要使用全导数公式:
∂ E ∂ n e t t l − 1 = ∂ E ∂ n e t f , t 1 ∂ n e t f , t 1 ∂ x t l ∂ x t l ∂ n e t t 1 − 1 + ∂ E ∂ n e t i , t 1 ∂ n e t i , t 1 ∂ x t l ∂ x t l ∂ n e t t 1 − 1 + ∂ E ∂ n e t c ‾ , t 1 ∂ n e t c ‾ , t 1 ∂ x t l ∂ x t l ∂ n e t t 1 − 1 + ∂ E ∂ n e t o , t 1 ∂ n e t o , t 1 ∂ x t l ∂ x t l ∂ n e t t 1 − 1 = δ f , t W f h × f ′ ( n e t t l − 1 ) + δ i , t W i h × f ′ ( n e t t l − 1 ) + δ c ‾ , t W c ‾ h × f ′ ( n e t t l − 1 ) + δ o , t W o h × f ′ ( n e t t l − 1 ) = ( δ f , t W f h + δ i , t W i h + δ c ‾ , t W c ‾ h + δ o , t W o h ) × f ′ ( n e t t l − 1 ) ( 1 − 28 ) \frac{\partial E}{\partial \mathbf{n e t}_{t}^{l-1}}= \frac{\partial E}{\partial \mathbf{n e t}_{\mathrm{f}, \mathrm{t}}^{1}} \frac{\partial \mathbf{n e t}_{\mathrm{f}, \mathrm{t}}^{1}}{\partial \mathbf{x}_{t}^{l}} \frac{\partial \mathbf{x}_{t}^{l}}{\partial \mathbf{n e t}_{t}^{1-1}}+ \frac{\partial E}{\partial \mathbf{n e t}_{\mathrm{i}, \mathrm{t}}^{1}} \frac{\partial \mathbf{n e t}_{\mathrm{i}, \mathrm{t}}^{1}}{\partial \mathbf{x}_{t}^{l}} \frac{\partial \mathbf{x}_{t}^{l}}{\partial \mathbf{n e t}_{\mathrm{t}}^{1-1}}\\\quad\quad\quad\quad\quad\quad+ \frac{\partial E}{\partial \mathbf{n e t}_{\mathrm{\overline{c}}, \mathrm{t}}^{1}} \frac{\partial \mathbf{n e t}_{\mathrm{\overline{c}}, \mathrm{t}}^{1}}{\partial \mathbf{x}_{t}^{l}} \frac{\partial \mathbf{x}_{t}^{l}}{\partial \mathbf{n e t}_{\mathrm{t}}^{1-1}} +\frac{\partial E}{\partial \mathbf{n e t}_{\mathrm{o}, \mathrm{t}}^{1}} \frac{\partial \mathbf{n e t}_{\mathrm{o}, \mathrm{t}}^{1}}{\partial \mathbf{x}_{t}^{l}} \frac{\partial \mathbf{x}_{t}^{l}}{\partial \mathbf{n e t}_{\mathrm{t}}^{1-1}}\\ =\delta_{f, t} W_{f h}\times f^{\prime}\left(\mathbf{n} e t_{t}^{l-1}\right)+\delta_{i, t} W_{i h}\times f^{\prime}\left(\mathbf{n} e t_{t}^{l-1}\right)\\ \quad\quad\quad\quad+\delta_{\overline{c}, t} W_{\overline{c} h}\times f^{\prime}\left(\mathbf{n} e t_{t}^{l-1}\right)+\delta_{o, t} W_{o h}\times f^{\prime}\left(\mathbf{n} e t_{t}^{l-1}\right)\\ \quad\quad\quad\quad= (\delta_{f, t} W_{f h}+\delta_{i, t} W_{i h}+\delta_{\overline{c}, t} W_{\overline{c} h}+\delta_{o, t} W_{o h})\times f^{\prime}\left(\mathbf{n} e t_{t}^{l-1}\right)\quad\quad(1-28) ∂nettl−1∂E=∂netf,t1∂E∂xtl∂netf,t1∂nett1−1∂xtl+∂neti,t1∂E∂xtl∂neti,t1∂nett1−1∂xtl+∂netc,t1∂E∂xtl∂netc,t1∂nett1−1∂xtl+∂neto,t1∂E∂xtl∂neto,t1∂nett1−1∂xtl=δf,tWfh×f′(nettl−1)+δi,tWih×f′(nettl−1)+δc,tWch×f′(nettl−1)+δo,tWoh×f′(nettl−1)=(δf,tWfh+δi,tWih+δc,tWch+δo,tWoh)×f′(nettl−1)(1−28)
要求所有参数和偏置的误差项,我们首先根据式(1-13,14,15,17)对某时刻 t t t的所有权重求偏导,很容易求出 t t t时刻的 W f h W i h W c ‾ h W o h W_{fh} W_{ih} W_{\overline{c}h} W_{oh} WfhWihWchWoh的偏导数,即误差项:
∂ E ∂ W f h , t = ∂ E ∂ n e t f , t ∂ n e t f , t ∂ W f h , t = δ f , t h t − 1 ∂ E ∂ W i h , t = ∂ E ∂ n e t i , t ∂ n e t i t ∂ W i h t = δ i , t h t − 1 ∂ E ∂ W c ‾ h , t = ∂ E ∂ n e t c ‾ , t ∂ n e t c ‾ , t ∂ W c ‾ h , t = δ c ‾ , t h t − 1 ∂ E ∂ W o h , t = ∂ E ∂ n e t o , t ∂ n e t o , t ∂ W o h , t = δ o , t h t − 1 ( 1 − 29 ) \begin{array}{l} {\frac{\partial E}{\partial W_{f h, t}}=\frac{\partial E}{\partial n e t_{f, t}} \frac{\partial n e t_{f, t}}{\partial W_{f h, t}}=\delta_{f, t} h_{t-1}} \\{\frac{\partial E}{\partial W_{i h, t}}=\frac{\partial E}{\partial n e t_{i, t}} \frac{\partial n e t_{i t}}{\partial W_{i h t}}=\delta_{i, t} h_{t-1}} \\{\frac{\partial E}{\partial W_{\overline{c} h, t}}=\frac{\partial E}{\partial n e t_{\overline{c}, t}} \frac{\partial n e t_{\overline{c}, t}}{\partial W_{\overline{c} h, t}}=\delta_{\overline{c}, t} h_{t-1}} \\ {\frac{\partial E}{\partial W_{o h, t}}=\frac{\partial E}{\partial n e t_{o, t}} \frac{\partial n e t_{o, t}}{\partial W_{o h, t}}=\delta_{o, t} h_{t-1}}\end{array} \quad\quad(1-29) ∂Wfh,t∂E=∂netf,t∂E∂Wfh,t∂netf,t=δf,tht−1∂Wih,t∂E=∂neti,t∂E∂Wiht∂netit=δi,tht−1∂Wch,t∂E=∂netc,t∂E∂Wch,t∂netc,t=δc,tht−1∂Woh,t∂E=∂neto,t∂E∂Woh,t∂neto,t=δo,tht−1(1−29) 对于整个样本,它的误差是所有时刻的误差之和,最终得到:
∂ E ∂ W f h = ∑ j = 1 t δ f , j h j − 1 ∂ E ∂ W i h = ∑ j = 1 t δ i , j h j − 1 ∂ E ∂ W c h ‾ = ∑ j = 1 t δ τ ‾ , j h j − 1 ∂ E ∂ W o h = ∑ j = 1 t δ o , j h j − 1 ( 1 − 30 ) \begin{array}{l}{ \frac{\partial E}{\partial W_{f h}}=\sum_{j=1}^{t} \delta_{f, j} h_{j-1}} \\ {\frac{\partial E}{\partial W_{i h}}=\sum_{j=1}^{t} \delta_{i, j} h_{j-1} }\\ {\frac{\partial E}{\partial W_{\overline{c h}}}=\sum_{j=1}^{t} \delta_{\overline{\tau}, j} h_{j-1}}\\ {\frac{\partial E}{\partial W_{o h}}=\sum_{j=1}^{t} \delta_{o, j} h_{j-1} }\end{array}\quad\quad(1-30) ∂Wfh∂E=∑j=1tδf,jhj−1∂Wih∂E=∑j=1tδi,jhj−1∂Wch∂E=∑j=1tδτ,jhj−1∂Woh∂E=∑j=1tδo,jhj−1(1−30)
对于偏置项 b f , b i , b c , b o \mathbf{b}_{f}, \mathbf{b}_{i}, \mathbf{b}_{c}, \mathbf{b}_{o} bf,bi,bc,bo的梯度,也是将各个时刻的梯度加在一起。下面是各个时刻的偏置项梯度:
∂ E ∂ b f , t = ∂ E ∂ n e t f , t ∂ n e t f , t ∂ b f , t = δ f , t ∂ E ∂ b i , t = ∂ E ∂ n e t i , t ∂ n e t i , t ∂ b i , t = δ i , t ∂ E ∂ b c ‾ , t = ∂ E ∂ n e t c ‾ , t ∂ n e t c ‾ , t ∂ b c ‾ , t = δ c ‾ , t ∂ E ∂ b o , t = ∂ E ∂ n e t o , t ∂ n e t o , t ∂ b o , t = δ o , t ( 1 − 31 ) \begin{array}{l}{ \frac{\partial E}{\partial b_{f, t}}=\frac{\partial E}{\partial n e t_{f, t}} \frac{\partial n e t_{f, t}}{\partial b_{f, t}}=\delta_{f, t}}\\ {\frac{\partial E}{\partial b_{i, t}}=\frac{\partial E}{\partial n e t_{i, t}} \frac{\partial n e t_{i, t}}{\partial b_{i, t}}=\delta_{i, t}}\\ {\frac{\partial E}{\partial b_{\overline{c}, t}}=\frac{\partial E}{\partial n e t_{\overline{c}, t}} \frac{\partial n e t_{\overline{c}, t}}{\partial b_{\overline{c}, t}}=\delta_{\overline{c}, t}}\\ {\frac{\partial E}{\partial b_{o, t}}=\frac{\partial E}{\partial n e t_{o, t}} \frac{\partial n e t_{o, t}}{\partial b_{o, t}}=\delta_{o, t} }\end{array}\quad\quad(1-31) ∂bf,t∂E=∂netf,t∂E∂bf,t∂netf,t=δf,t∂bi,t∂E=∂neti,t∂E∂bi,t∂neti,t=δi,t∂bc,t∂E=∂netc,t∂E∂bc,t∂netc,t=δc,t∂bo,t∂E=∂neto,t∂E∂bo,t∂neto,t=δo,t(1−31)
偏差累加和为:
∂ E ∂ b f = ∑ j = 1 t δ f , j ∂ E ∂ b i = ∑ j = 1 t δ i , j ∂ E ∂ b c ‾ = ∑ j = 1 t δ c ‾ , j ∂ E ∂ b o = ∑ j = 1 t δ o , j ( 1 − 32 ) \begin{array}{l}{ \frac{\partial E}{\partial b_{f}}=\sum_{j=1}^{t} \delta_{f, j}} \\ {\frac{\partial E}{\partial b_{i}}=\sum_{j=1}^{t} \delta_{i, j}} \\ {\frac{\partial E}{\partial b_{\overline{c}}}=\sum_{j=1}^{t} \delta_{\overline{c}, j}} \\ {\frac{\partial E}{\partial b_{o}}=\sum_{j=1}^{t} \delta_{o, j} }\end{array}\quad\quad(1-32) ∂bf∂E=∑j=1tδf,j∂bi∂E=∑j=1tδi,j∂bc∂E=∑j=1tδc,j∂bo∂E=∑j=1tδo,j(1−32)
对于 W f x . W i x . W c x . W o x W_{f x} . W_{i x} . W_{c x .} W_{o x} Wfx.Wix.Wcx.Wox的权重梯度,与时间没有关系,只需要根据相应的误差项直接计算即可:
∂ E ∂ W f x = ∂ E ∂ n e t f , t ∂ n e t f , t ∂ W f x = δ f , t x t ∂ E ∂ W i x = ∂ E ∂ n e t i , t ∂ n e t i , t ∂ W i x = δ i , t x t ∂ E ∂ W c ‾ x = ∂ E ∂ n e t c ‾ t ∂ n e t c ‾ , t ∂ W c ‾ x = δ c ‾ , t x t ∂ E ∂ W o x = ∂ E ∂ n e t o t ∂ n e t o , t ∂ W o x = δ o t x t ( 1 − 33 ) \begin{array}{l} {\frac{\partial E}{\partial W_{\mathscr{fx}}}=\frac{\partial E}{\partial n e t_{f, t}} \frac{\partial n e t_{f, t}}{\partial W_{fx}}=\delta_{f, t} x_{t}}\\ {\frac{\partial E}{\partial W_{i x}}=\frac{\partial E}{\partial n e t_{i, t}} \frac{\partial n e t_{i, t}}{\partial W_{i x}}=\delta_{i, t} x_{t}}\\ {\frac{\partial E}{\partial W_{\overline{c} x}}=\frac{\partial E}{\partial n e t_{\overline{c} t}} \frac{\partial n e t_{\overline{c} , t}}{\partial W_{\overline{c} x}}=\delta_{\overline{c}, t} x_{t}}\\ {\frac{\partial E}{\partial W_{o x}}=\frac{\partial E}{\partial n e t_{o t}} \frac{\partial n e t_{o, t}}{\partial W_{o x}}=\delta_{o t} x_{t}}\end{array}\quad\quad(1-33) ∂Wfx∂E=∂netf,t∂E∂Wfx∂netf,t=δf,txt∂Wix∂E=∂neti,t∂E∂Wix∂neti,t=δi,txt∂Wcx∂E=∂netct∂E∂Wcx∂netc,t=δc,txt∂Wox∂E=∂netot∂E∂Wox∂neto,t=δotxt(1−33)
W y i W_{yi} Wyi的误差项直接求导即可。
∂ E ∂ W y i = σ ′ ( W y i h t ) h t ( 1 − 34 ) \frac{\partial E}{\partial W_{yi}} = \sigma'(W_{yi}h_t)h_t\quad\quad(1-34) ∂Wyi∂E=σ′(Wyiht)ht(1−34)
GRU即Gated Recurrent Unit ,是LSTM的一个变体。GRU保持了LSTM的效果同时又使结构更加简单,使用的参数更少,应用十分广泛。
GRU模型如下,它只有两个门了,分别为更新门和重置门,即图中的 z t z_t zt和 r t r_t rt 。更新门用于控制前一时刻的状态信息保留到当前状态中的程度,更新门的值越大说明前一时刻的状态信息保留得越多。重置门用于控制忽略前一时刻的状态信息的程度,重置门的值越小说明忽略得越多。
根据图1.6可以得到GRU的传播过程为:
r t = σ ( W r ⋅ [ h t − 1 , x t ] + b r ) z t = σ ( W z ⋅ [ h t − 1 , x t ] + b z ) h ‾ t = tanh ( W h ‾ ⋅ [ r t h t − 1 , x t ] + b h ‾ ) h t = z t ∗ h t − 1 + ( 1 − z t ) ∗ h ‾ t y t = σ ( W o ⋅ h t ) \begin{aligned} r_{t} &=\sigma\left(W_{r} \cdot\left[h_{t-1}, x_{t}\right]+b_r\right) \\ z_{t} &=\sigma\left(W_{z} \cdot\left[h_{t-1}, x_{t}\right]+b_z\right) \\ \overline{h}_{t} &=\tanh \left(W_{ \overline{h}} \cdot\left[r_{t} h_{t-1}, x_{t}\right]+b_{\overline{h}}\right) \\ h_{t} &=z_{t}* h_{t-1}+(1-z_{t}){*} \overline{h}_{t} \\ y_{t} &=\sigma\left(W_{o} \cdot h_{t}\right) \end{aligned} rtzththtyt=σ(Wr⋅[ht−1,xt]+br)=σ(Wz⋅[ht−1,xt]+bz)=tanh(Wh⋅[rtht−1,xt]+bh)=zt∗ht−1+(1−zt)∗ht=σ(Wo⋅ht)
其中[ ]表示两个向量的连接,*表示两个矩阵元素相乘。GRU的训练同LSTM类似,但是比LSTM的权重矩阵参数更容易,GRU需要学习的参数只有 W r , W z , W h ‾ , W o W_{r}, W_{z}, W_{\overline{h}}, W_{o} Wr,Wz,Wh,Wo,其中前三个参数LSTM中权重矩阵是一样的,都是拼接矩阵,在求解的时候也需要分割开来。
概括来说,LSTM和CRU都是通过各种门函数来将重要特征保留下来,这样就保证了在long-term传播的时候也不会丢失。此外GRU相对于LSTM少了一个门函数,因此在参数的数量上也是要少于LSTM的,所以整体上GRU的训练速度要快于LSTM的。不过对于两个网络的好坏还是得看具体的应用场景。
Bidirectional RNN(双向RNN)假设当前t的输出不仅仅和之前的序列有关,并且还与之后的序列有关,例如:预测一个语句中缺失的词语那么需要根据上下文进 行预测;Bidirectional RNN是一个相对简单的RNNs,由两个RNNs上下叠加在 一起组成。输出由这两个RNNs的隐藏层的状态决定。
如下图:
代码如下:
# 开始网络构建
# 1. 输入的数据格式转换
# X格式:[batch_size, time_steps, input_size]
X = tf.reshape(_X, shape=[-1, timestep_size, input_size])
# 单层LSTM RNN
# 2. 定义Cell
lstm_cell_fw = tf.nn.rnn_cell.LSTMCell(num_units=hidden_size, reuse=tf.get_variable_scope().reuse)
gru_cell_bw = tf.nn.rnn_cell.GRUCell(num_units=hidden_size, reuse=tf.get_variable_scope().reuse)
# 3. 单层的RNN网络应用
init_state_fw = lstm_cell_fw.zero_state(batch_size, dtype=tf.float32)
init_state_bw = gru_cell_bw.zero_state(batch_size, dtype=tf.float32)
# 3. 动态构建双向的RNN网络
"""
bidirectional_dynamic_rnn(
cell_fw: 前向的rnn cell
, cell_bw:反向的rnn cell
, inputs:输入的序列
, sequence_length=None
, initial_state_fw=None:前向rnn_cell的初始状态
, initial_state_bw=None:反向rnn_cell的初始状态
, dtype=None
, parallel_iterations=None
, swap_memory=False, time_major=False, scope=None)
API返回值:(outputs, output_states) => outputs存储网络的输出信息,output_states存储网络的细胞状态信息
outputs: 是一个二元组, (output_fw, output_bw)构成,output_fw对应前向的rnn_cell的执行结果,结构为:[batch_size, time_steps, output_size];output_bw对应反向的rnn_cell的执行结果,结果和output_bw一样
output_states:是一个二元组,(output_state_fw, output_state_bw) 构成,output_state_fw和output_state_bw是dynamic_rnn API输出的状态值信息
"""
outputs, states = tf.nn.bidirectional_dynamic_rnn(
cell_fw=lstm_cell_fw, cell_bw=gru_cell_bw, inputs=X,
initial_state_fw=init_state_fw, initial_state_bw=init_state_bw)
output_fw = outputs[0][:, -1, :]
output_bw = outputs[1][:, -1, :]
output = tf.concat([output_fw, output_bw], 1)
深度RNN
Deep Bidirectional RNN(深度双向RNN)类似Bidirectional RNN,区别在于每 个每一步的输入有多层网络,这样的话该网络便具有更加强大的表达能力和学习 能力,但是复杂性也提高了,同时需要训练更多的数据。
#多层
def lstm_call():
cell = tf.nn.rnn_cell.LSTMCell(num_units=hidden_size,reuse=tf.get_variable_scope().reuse)
return tf.nn.rnn_cell.DropoutWrapper(cell,output_keep_prob=keep_prob)
mlstm_cell = tf.nn.rnn_cell.MultiRNNCell(cells=[lstm_call() for i in range(layer_num)])
inint_state = mlstm_cell.zero_state(batch_size,tf.float32)
output,state = tf.nn.dynamic_rnn(mlstm_cell,inputs=X,initial_state=inint_state)
output = output[:,-1,:]
本节整理自《深入理解TensorFlow》,基本的RN单元,LSTM单元,GRU单元等还可以结合其他特性,从而形成新的RNN单元变种。tensorflow文件中定义的DropoutWrapper,ResidualWrapper,DeviceWrapper,MultiRNNCell等包装器或工具类都继承自RNNCell类,他们分别提供不同的特性。DeviceWrapper比较简单,主要是使某个具体的RNN单元运行在指定的设备上。
该类提供Dropout