文章目录
- [RNN(Recurrent Neural Network,循环神经网络)](#RNN(Recurrent Neural Network,循环神经网络))
-
- [1. 什么是RNN?](#1. 什么是RNN?)
- [2. 经典RNN的结构](#2. 经典RNN的结构)
- [3. RNN的主要特点](#3. RNN的主要特点)
- [4. RNN存在问题------长期依赖(Long-TermDependencies)问题](#4. RNN存在问题——长期依赖(Long-TermDependencies)问题)
- [LSTM(Long Short-Term Memory,长短期记忆网络)](#LSTM(Long Short-Term Memory,长短期记忆网络))
-
- [1. 什么是LSTM?](#1. 什么是LSTM?)
- [2. LSTM的网络结构](#2. LSTM的网络结构)
-
- [2.1 与RNN的不同之处](#2.1 与RNN的不同之处)
- [2.2 LSTM核心](#2.2 LSTM核心)
- [2.3 遗忘门(Forget Gate)](#2.3 遗忘门(Forget Gate))
- [2.4 输入门(Input Gate)](#2.4 输入门(Input Gate))
- [2.5 细胞状态](#2.5 细胞状态)
- [2.6 输出门(Output Gate)](#2.6 输出门(Output Gate))
- [3. LSTM网络结构总结](#3. LSTM网络结构总结)
- [4. 梯度消失与爆炸问题](#4. 梯度消失与爆炸问题)
- [GRU(Gate Recurrent Unit,门控循环单元)](#GRU(Gate Recurrent Unit,门控循环单元))
-
- [1. 什么是GRU?](#1. 什么是GRU?)
- [2. GRU的网络结构](#2. GRU的网络结构)
-
- [2.1 重置门(Reset Gate)](#2.1 重置门(Reset Gate))
- [2.2 更新门(Update Gate)](#2.2 更新门(Update Gate))
- [2.3 候选记忆状态(candidate memory)](#2.3 候选记忆状态(candidate memory))
- [2.4 最终记忆状态(hidden state)](#2.4 最终记忆状态(hidden state))
- [3. GRU网络结构总结](#3. GRU网络结构总结)
- [4. GRU为何能够缓解梯度消失?](#4. GRU为何能够缓解梯度消失?)
- BiGRU(双向GRU)
- 参考文献
RNN(Recurrent Neural Network,循环神经网络)
1. 什么是RNN?
循环神经网络是一类用于处理序列数据 的神经网络,它一般以序列数据作为输入,通过网络内部的结构设计有效地捕捉序列之间的关系,以序列的形式输出。与传统的前馈神经网络不同,RNN具有"记忆"能力,通过在网络中引入循环连接,使得其可以利用先前的输入信息来影响当前的输出。这使得RNN非常适合处理具有时间依赖性或顺序性的任务。
2. 经典RNN的结构
在介绍RNN之前,需要先了解最基本的单层网络,结构如图所示:
其含义是:输入 x x x,经过变换 W x + b Wx+b Wx+b 和激活函数 f f f,得到输出 y y y。
常用激活函数主要有:
在实际应用中,我们会遇到很多序列型的数据:
以自言语言处理问题为例,简单来说,这可以看成是一句话, x 1 x_1 x1可以看做是第一个单词, x 2 x_2 x2可以看做是第二个单词,以此类推。
为了建模这种序列问题,RNN引入了 隐藏状态(hidden state) h h h 的概念。隐状态 h h h可以对序列类型的数据提取特征,然后再转换为输出。
以 h 1 h_1 h1 的计算为例:
其中:圆圈或方框 表示的是向量 ,一个箭头 就表示对该向量做一次变换 (例如上图中表示对 h 0 h_0 h0 和 x 1 x_1 x1 各做了一次变换)。
具体来说, h 1 h_1 h1 是基于上一个隐藏层的状态 h 0 h_0 h0 和当前的输入 x 1 x_1 x1 计算得到来的。泛化到任意时刻就是 h t = f ( W h t − 1 + U x t + b t ) h_t = f(Wh_{t-1}+Ux_t+b_t) ht=f(Wht−1+Uxt+bt),这里激活函数 f f f 一般是tanh、sigmoid、ReLU等非线性激活函数。在实践中, h t h_t ht 一般只包含前面若干步而不是所有步的隐藏状态。
h 2 h_2 h2 的计算与 h 1 h_1 h1 相似:
计算时,每一步使用的参数U、W、b都是一样的,也就是说每个步骤的参数是共享的,这是RNN的重要特点。 而在LSTM中权重是不共享的。
那为什么RNN的权值是共享的呢?是因为RNN的权值是在同一个向量中,只是不同的时刻而已。【进一步解释权重共享,指的是 x i x_i xi 在不同的时刻 i i i 乘的一直都是 U , h i h_i hi 在不同的时刻 i i i 乘的一直都是 W 。在 LSTM 中因为多出了门的概念,每个门对应的 W 是不同的(即不同的门权重不共享),但是相同的门之间的 W 是共享的。】
依次计算剩下的(使用相同的参数U、W和b ):
到此,我们得到了所有的隐藏状态 h 1 h_1 h1, h 2 h_2 h2, h 3 h_3 h3, h 4 h_4 h4。
RNN的输出通过隐藏状态进行计算:
正如前面提到的,一个箭头就表示对向量做一次类似于 f ( W x + b ) f(Wx+b) f(Wx+b) 的变换,这里箭头表示对 h 1 h_1 h1 进行一次变换,得到输出 y 1 y_1 y1。
剩下的输出可以类似得到(使用相同的参数 V 和 c ):
到此为止,得到了所有的输出,这就是经典的RNN结构,输入和输出序列是等长的。
通过上面的描述,我们知道RNN是包含循环的网络,在这个循环的结构中,每个神经网络的模块,读取到某个输入 x t x_t xt,并输出一个值 y t y_t yt,然后不断循环,使得信息可以从当前步传递到下一步。RNN可以被看做是同一神经网络的多次复制,每个神经网络模块会把消息传递给下一个,将这个循环展开:
链式的特征揭示了RNN本质上是与序列相关的,它们是对这类数据的最自然的神经网络架构。
3. RNN的主要特点
循环连接:RNN的核心在于它的循环连接,即网络的输出会作为下一个时间步的输入,这使得网络能够保持对之前信息的记忆。
参数共享:在RNN中,无论序列的长度如何,使用的权重和参数是共享的。
记忆能力:RNN能够记住序列中的信息,这使得它在处理时间序列数据、自然语言处理等领域表现出色。
4. RNN存在问题------长期依赖(Long-TermDependencies)问题
有时候,我们仅仅需要知道先前的信息来执行当前的任务。例如,我们有一个语言模型用来基于先前的词来预测下一个词。如果我们试着预测这句话中 "the clouds are in the sky" 最后的这个词 "sky",我们并不再需要其他的信息,因为很显然下一个词应该是sky。在这样的场景中,相关的信息和预测的词位置之间的间隔是非常小的,RNN可以学会使用先前的信息 。
但是同样会有一些更加复杂的场景。比如我们试着去预测 "I grew up in France...I speak fluent French" 最后的词 "French"。当前的信息建议下一个词可能是一种语言的名字,但是如果我们需要弄清楚是什么语言,我们是需要先前提到的离当前位置很远的 "French" 的上下文。这说明相关信息和当前预测位置之间的间隔就肯定变得相当的大。不幸的是,在这个间隔不断增大时,RNN会丧失学习到连接如此远的信息的能力。
换句话说, RNN 会受到短时记忆的影响。如果一条序列足够长,那它们将很难将信息从较早的时间步传送到后面的时间步。
因此,如果你正在尝试处理一段文本进行预测,RNN 可能从一开始就会遗漏重要信息。在反向传播期间(反向传播本质是通过不断缩小误差去更新权值,从而不断去修正拟合的函数),RNN 会面临梯度消失的问题。
因为梯度是用于更新神经网络的权重值(新的权值 = 旧权值 - 学习率*梯度),梯度会随着时间的推移不断下降减少,而当梯度值变得非常小时,就不会继续学习。
换言之,在递归神经网络中,获得小梯度更新的层会停止学习------ 那些通常是较早的层。 由于这些层不学习,RNN会忘记它在较长序列中以前看到的内容,因此RNN只具有短时记忆。
而梯度爆炸则是因为计算的难度越来越复杂导致。
然而,幸运的是,有个RNN的变体------LSTM,可以在一定程度上解决梯度消失和梯度爆炸这两个问题!
LSTM(Long Short-Term Memory,长短期记忆网络)
1. 什么是LSTM?
长短期记忆网络(LSTM, Long Short-Term Memory)是一种特殊的循环神经网络RNN,设计用来解决传统RNN在处理长序列数据时遇到的梯度消失和梯度爆炸问题。
LSTM 网络的核心是三个门的机制:遗忘门(forget gate) 、输入门(input gate) 、输出门(output gate)。这些门通过自适应的方式控制信息的流动,从而实现对长期依赖信息的捕捉。
2. LSTM的网络结构
2.1 与RNN的不同之处
所有的RNN都具有一种重复神经网络模块的链式的形式。在标准的RNN中,这个重复的模块只有一个非常简单的结构,例如一个tanh层。
激活函数tanh的作用在于帮助调节流经网络的值,使得数值始终限制在-1到1之间。
LSTM也同样是这种结构,但是重复的模块有一个不同的结构。具体来说,RNN重复单一的神经网络层,LSTM中的重复模块则包含四个交互的层,三个Sigmoid和一个tanh层,并以一种非常特殊的方式进行交互。
图中,每一条黑线传输着一整个向量,从一个节点的输出到其他节点的输入。粉色的圈代表pointwise的操作,诸如向量的和,而黄色的矩阵就是学习到的神经网络层。合在一起的线表示向量的连接,分开的线表示内容被复制,然后分发到不同的位置。
上图中,σ表示Sigmoid 激活函数,与tanh不同,sigmoid把值压缩到0到1之间。
这样的设置有助于更新或忘记信息:
- 因为任何数乘以 0 都得 0,这部分信息就会剔除掉;
- 同样的,任何数乘以 1 都得到它本身,这部分信息就会完美地保存下来
相当于要么是1则记住,要么是0则忘掉,所以还是这个原则:因记忆能力有限,记住重要的,忘记无关紧要的。
2.2 LSTM核心
记忆细胞(Memory Cell) 是LSTM网络的核心,负责在整个序列处理过程中保持和更新长期依赖信息。记忆单元的结构相对简单,主要由一个或多个神经元组成,其状态通过时间步传递,仅通过线性方式更新。
LSTM有通过精心设计的称作为"门"的结构来去除或者增加信息到记忆细胞状态的能力。门是一种让信息选择式通过的方法。他们包含一个sigmoid神经网络层和一个pointwise乘法的非线性操作。
0代表"不许任何量通过",1就指"允许任意量通过"!从而使得网络就能了解哪些数据是需要遗忘,哪些数据是需要保存。
2.3 遗忘门(Forget Gate)
LSTM第一步是决定我们会从细胞状态中丢弃什么信息,这个决定通过一个称为 "遗忘门" 的结构完成。
遗忘门会读取上一个输出 h t − 1 h_{t-1} ht−1 和当前输入 x t x_t xt,做一个sigmoid的非线性映射,然后输出一个向量 f t f_t ft(该向量每一个维度的值都在0到1之间,1表示完全保留,0表示完全舍弃,相当于记住了重要的,忘记了无关紧要的 ),最后与细胞状态 C t − 1 C_{t-1} Ct−1 相乘。
- W f W_f Wf 权值是不共享的: f t = σ ( W f h h t − 1 + W f x x t + b f ) f_t = \sigma(W_{fh}h_{t-1}+W_{fx}x_t+b_f) ft=σ(Wfhht−1+Wfxxt+bf)
2.4 输入门(Input Gate)
这一步是确定什么样的新信息被存放在细胞状态中。包含两个部分:
- sigmoid层决定哪些值将要更新
- tanh层创建一个新的候选值向量 C ~ t \tilde C_t C~t,该向量被加入状态中。
- i t = σ ( W i h h t − 1 + W i x x t + b i ) i_t = \sigma(W_{ih}h_{t-1}+W_{ix}x_t+b_i) it=σ(Wihht−1+Wixxt+bi)
- C ~ t = t a n h ( W C h h t − 1 + W C x x t + b C ) \tilde C_t=tanh(W_{Ch}h_{t-1}+W_{Cx}x_t+b_C) C~t=tanh(WChht−1+WCxxt+bC)
2.5 细胞状态
更新旧细胞状态, C t − 1 C_{t-1} Ct−1 更新为 C t C_t Ct。
我们把旧状态与 f t f_t ft 相乘,丢弃掉我们确定需要丢弃的信息,接着加上 i t ∗ C ~ t i_t * \tilde C_t it∗C~t,这就是新的候选值。
2.6 输出门(Output Gate)
最终,输出门负责决定记忆单元状态的哪一部分将被输出到隐藏状态。包含两个操作:
- sigmoid层确定细胞状态的哪个部分将输出
- tanh层处理细胞状态(得到一个-1到1之间的值),并将其与sigmoid门的输出相乘
- o t = σ ( W o h h t − 1 + W o x x t + b o ) o_t=\sigma(W_{oh}h_{t-1}+W_{ox}x_t+b_o) ot=σ(Wohht−1+Woxxt+bo)
3. LSTM网络结构总结
- 遗忘门 :决定从单元状态中丢弃哪些信息 f t = σ ( W f ⋅ [ h t − 1 , x t ] + b f ) f_t=\sigma\left(W_f\cdot[h_{t-1},x_t] + b_f\right) ft=σ(Wf⋅[ht−1,xt]+bf)
- 输入门 :两部分组成:sigmoid层决定哪些值将被更新,tanh层创建一个新的候选值向量 i t = σ ( W i ⋅ [ h t − 1 , x t ] + b i ) C ~ t = tanh ( W C ⋅ [ h t − 1 , x t ] + b C ) \begin{aligned}i_{t}&=\sigma\left(W_i\cdot[h_{t-1},x_t] + b_i\right)\\\tilde{C}{t}&=\tanh(W_C\cdot[h{t-1},x_t] + b_C)\end{aligned} itC~t=σ(Wi⋅[ht−1,xt]+bi)=tanh(WC⋅[ht−1,xt]+bC)
- 细胞状态 :更新结合了遗忘门和输入门的信息 C t = f t ∗ C t − 1 + i t ∗ C ~ t C_t=f_t*C_{t-1}+i_t*\tilde{C}_t Ct=ft∗Ct−1+it∗C~t
- 输出门 :决定输出哪些信息,同时输出的值通过tanh函数进行缩放 o t = σ ( W o [ h t − 1 , x t ] + b o ) h t = o t ∗ tanh ( C t ) \begin{aligned}&o_{t}=\sigma\left(W_o [ h_{t-1},x_t] + b_o\right)\\&h_{t}=o_t*\tanh\left(C_t\right)\end{aligned} ot=σ(Wo[ht−1,xt]+bo)ht=ot∗tanh(Ct)
4. 梯度消失与爆炸问题
在标准的RNN中,梯度消失或爆炸问题是一个常见的问题,这会导致网络难以学习长期依赖关系。LSTM通过引入门控机制来解决这个问题。
梯度消失意味着随着时间的推移,梯度值逐渐减小,导致网络权重更新非常缓慢。梯度爆炸则是指梯度值随着时间的推移而变得非常大,导致权重更新过于剧烈,从而影响学习过程。
LSTM通过以下方式缓解这些问题:
- 遗忘门允许网络有选择性地保留或遗忘信息,这有助于防止无关信息的积累。
- 输入门允许网络更新单元状态,但仅当新输入与单元状态相关时。
通过这种方式,LSTM可以维持梯度在一个合理的范围内,避免消失或爆炸。
此外,现代的优化算法,如Adam或RMSprop,也可以有效缓解这些问题,它们通过调整学习率来适应每个参数的更新需求。
GRU(Gate Recurrent Unit,门控循环单元)
1. 什么是GRU?
GRU(Gate Recurrent Unit)门控循环单元,是循环神经网络(RNN)的变体,与LSTM类似,通过门控单元解决RNN中不能长期记忆和反向传播中的梯度等问题。
简单来说,GRU简化了LSTM的结构,将遗忘门和输入门合并为一个单一的 "更新门",并且合并了细胞状态和隐藏状态。
GRU的核心思想是减少模型参数,同时保持对长短期依赖的记忆能力。
2. GRU的网络结构
更新门 z t z_t zt 和重置门 r t r_t rt 都是对 h t − 1 h_{t-1} ht−1 和 x t x_t xt 做的sigmoid非线性映射,区别在哪?
更新门控制信息的流动,而重置门则决定了之前的记忆有多少应该被保留。
2.1 重置门(Reset Gate)
重置门记为 r t r_t rt,这个门决定了之前的记忆有多少应该被保留(或者理解为控制以往状态的影响程度 )。也就是说,重置门控制着前一状态的信息 h t − 1 h_{t-1} ht−1 传入候选状态 h t h_t ht 的比例,重置门 r t r_t rt 的值越小,则与 h t − 1 h_{t-1} ht−1 的乘积越小, h t − 1 h_{t-1} ht−1 的信息添加到 h t h_t ht 的越少。
计算时会结合前一时间步的隐藏状态 h t − 1 h_{t-1} ht−1 和当前输入 x t x_t xt,输出是一个0到1之间的值。值越接近1表示越多地保留之前的状态,越接近0表示遗忘更多旧状态。对应的数学表达如下:
r t = σ ( W r ⋅ [ h t − 1 , x t ] ) r_t=\sigma (W_r\cdot[h_{t-1},x_t]) rt=σ(Wr⋅[ht−1,xt])
2.2 更新门(Update Gate)
更新门记为 z t z_t zt,这个门决定了上一时间步的记忆状态有多少需要传递到当前步,以及当前的输入信息有多少需要加到这个新的记忆状态中 。也就是说,更新门用于控制前一状态的信息 h t − 1 h_{t-1} ht−1 有多少保留到新状态 h t h_t ht 中,当 1 − z t 1-z_t 1−zt越大,保留的信息越多。
同样,它也是基于 h t − 1 h_{t-1} ht−1 和 x t x_t xt计算得到的。
z t = σ ( W z ⋅ [ h t − 1 , x t ] ) z_t=\sigma (W_z\cdot[h_{t-1},x_t]) zt=σ(Wz⋅[ht−1,xt])
2.3 候选记忆状态(candidate memory)
新的候选记忆 h ~ t \tilde h_t h~t 是基于当前输入 x t x_t xt、上一时间步的隐藏状态 h t − 1 h_{t-1} ht−1 以及重置门的输出 r t r_t rt 三者得到的。其中重置门决定了如何重置旧的记忆状态,以便更好地整合新信息。
h ~ t = t a n h ( W ⋅ [ r t ∗ h t − 1 , x t ] ) \tilde h_t = tanh(W\cdot[r_t*h_{t-1},x_t]) h~t=tanh(W⋅[rt∗ht−1,xt])
2.4 最终记忆状态(hidden state)
更新后的隐藏状态 h t h_t ht 为最终记忆状态,通过结合更新门的输出 z t z_t zt、候选记忆状态 h ~ t \tilde h_t h~t 以及上一时间步的记忆状态 h t − 1 h_{t-1} ht−1 计算得出的。其中更新门决定了新旧记忆的混合比例。
h t = ( 1 − z t ) ∗ h t − 1 + z t ∗ h ~ t h_t=(1-z_t)*h_{t-1}+z_t*\tilde h_t ht=(1−zt)∗ht−1+zt∗h~t
3. GRU网络结构总结
- 重置门 :控制前一个状态在当前时间步骤的计算中保留多少历史信息,帮助模型决定忽略多少之前的信息。
- r t = σ ( W r ⋅ [ h t − 1 , x t ] ) r_t=\sigma (W_r\cdot[h_{t-1},x_t]) rt=σ(Wr⋅[ht−1,xt])
- 输出接近于0:表示较多地忽略前一个隐状态的信息
- 输出接近于1:表示较多地保留前一个隐状态的信息
- 更新门 :控制当前时间步的候选隐状态对最终隐状态更新的贡献程度,有助于模型决定在每一步保留多少之前时刻的信息。
- z t = σ ( W z ⋅ [ h t − 1 , x t ] ) z_t=\sigma (W_z\cdot[h_{t-1},x_t]) zt=σ(Wz⋅[ht−1,xt])
- 输出接近于0:表示较少地更新当前时间步的隐状态
- 输出接近于1:表示较多地更新当前时间步的隐状态
- 候选隐藏状态: h ~ t = t a n h ( W ⋅ [ r t ∗ h t − 1 , x t ] ) \tilde h_t = tanh(W\cdot[r_t*h_{t-1},x_t]) h~t=tanh(W⋅[rt∗ht−1,xt])
- 最终隐藏状态: h t = ( 1 − z t ) ∗ h t − 1 + z t ∗ h ~ t h_t=(1-z_t)*h_{t-1}+z_t*\tilde h_t ht=(1−zt)∗ht−1+zt∗h~t
GRU通过这种方式,实现了对信息的动态过滤和更新,同时减少了模型的复杂性。由于其结构的简化,GRU在某些任务上能够更快地训练,并且在某些情况下能够与LSTM相媲美或甚至更优。
4. GRU为何能够缓解梯度消失?
在传统的RNN中,由于长时间依赖问题,反向传播过程中梯度可能会因连续乘以小于1的数而变得非常小,导致早期时间步的权重几乎不更新,这就是梯度消失问题。
而GRU通过其独特的门控机制,特别是更新门和重置门的设计,能够更加灵活地控制信息流,可以更好地捕获时间步距离很长的序列上的依赖关系。
- 重置门有助于捕获序列中的短期依赖关系。
- 重置门帮助模型决定忽略多少之前的信息。重置门可以用来减少那些不太相关信息的影响,从而保护模型不会把注意力放在不相关的长期依赖上。当选择忽略一些不相关的信息时,梯度将不会在这部分信息上进行传递,这有助于集中于更相关的信息,并有助于梯度完整地在其他相关部分传递。
- 更新门有助于捕获序列中的长期依赖关系。
- 更新门有助于模型决定在每一步中应该保留多少之前时刻的信息。它可以让模型在需要的时候保持激活状态,这样有助于后续的梯度传递而不会随时间迅速减小。如果更新门接近1,那么梯度可以在很多时间步内传递而不衰减,使得长期依赖的信息得到保留。
- 重置门打开时,门控循环单元包含基本循环神经网络;更新门打开时,门控循环单元可以跳过子序列。
因为有了这样的机制,GRU能够在每次更新中将梯度既不是完全传递也不是完全阻断,而是能够在相关的部分进行传递。这样在优化过程中,即使对于较长的序列,也能够更加稳定地保留梯度,防止了梯度极端消失,这对于学习长期依赖至关重要。因此,GRU往往在处理长序列数据时比传统RNN更加有效。
BiGRU(双向GRU)
BiGRU(双向门控循环单元)是一种改进的循环神经网络(RNN)结构,它由两个独立的GRU层组成,一个沿正向处理序列,另一个沿反向处理序列。这种双向结构使得BiGRU能够捕捉到序列中的长距离依赖关系,从而提高模型的性能。
首先,对于一个输入序列 X = x 1 , x 2 , ... , x T X = x_1,x_2,\dots,x_T X=x1,x2,...,xT,BiGRU模型的前向计算可以表示为:
h t → = G R U ( h t − 1 → , x t ) h t ← = G R U ( h t + 1 ← , x t ) \overrightarrow{h_t}=\mathrm{GRU}(\overrightarrow{h_{t-1}},x_t)\\\\\overleftarrow{h_t}=\mathrm{GRU}(\overleftarrow{h_{t+1}},x_t) ht =GRU(ht−1 ,xt)ht =GRU(ht+1 ,xt)
其中, h t → \overrightarrow{h_t} ht 和 h t ← \overleftarrow{h_t} ht 分别表示从左到右和从右到左的隐藏状态, G R U GRU GRU 表示GRU单元, x t x_t xt 表示输入序列中的第 t t t 个元素。
然后,将两个方向的隐藏状态拼接在一起,得到最终的隐藏状态 h t h_t ht:
h t = [ h t → ; h t ← ] h_t=[\overrightarrow{h_t};\overleftarrow{h_t}] ht=[ht ;ht ]
其中, [ ⋅ ; ⋅ ] [\cdot;\cdot] [⋅;⋅] 表示向量的拼接操作。
最后,将隐藏状态 h t h_t ht 传递给一个全连接层,得到输出 y t y_t yt:
y t = s o f t m a x ( W h t + b ) y_t=\mathrm{softmax}(Wh_t+b) yt=softmax(Wht+b)