循环神经网络(RNN)
1. 什么是RNN
循环神经网络(Recurrent Neural Network, RNN)是一类以序列(sequence)数据为输入,在序列的演进方向进行递归(recursion)且所有节点(循环单元)按链式连接的递归神经网络(recursive neural network)
1.1 RNN的应用
- 文本生成(生成序列)、机器翻译、看图说话、文本(情感)分析、智能客服、聊天机器人、语音识别、搜索引擎、个性化推荐
1.2 为什么有了CNN,还要RNN?
- 传统神经网络(包括CNN),输入和输出都是互相独立的。图像上的猫和狗是分隔开的,但有些任务,后续的输出和之前的内容是相关的。例如:我是中国人,我的母语是____。这是一道填空题,需要依赖于之前的输入。
- 所以,RNN引入“记忆”的概念,也就是输出需要依赖于之前的输入序列,并把关键输入记住。循环2字来源于其每个元素都执行相同的任务。
- 它并⾮刚性地记忆所有固定⻓度的序列,而是通过隐藏状态来存储之前时间步的信息。
1.3 RNN的网络结构
首先先上图,然后再解释:
现在我们考虑输入数据存在时间相关性的情况。假设 Xt∈Rn∗d 是序列中时间步t的小批量输入,Ht∈Rn∗h 是该时间步的隐藏变量。那么根据以上结构图当前的隐藏变量的公式如下:
从以上公式我们可以看出,这⾥我们保存上⼀时间步的隐藏变量 Ht−1 ,并引⼊⼀个新的权重参数,该参数⽤来描述在当前时间步如何使⽤上⼀时间步的隐藏变量。具体来说,时间步 t 的隐藏变量的计算由当前时间步的输入和上一时间步的隐藏变量共同决定。ϕ函数其实就是激活函数。
我们在这⾥添加了 Ht−1Whh ⼀项。由上式中相邻时间步的隐藏变量 Ht 和Ht−1之间的关系可知,这⾥的隐藏变量能够捕捉截⾄当前时间步的序列的历史信息,就像是神经⽹络当前时间步的状态或记忆⼀样。因此,该隐藏变量也称为隐藏状态。由于隐藏状态在当前时间步的定义使用了上一时间步的隐藏状态,上式的计算是循环的。使用循环计算的网络即循环神经网络(recurrent neural network)。
在时间步t,输出层的输出和多层感知机中的计算类似:
1.4 双向RNN
之前介绍的循环神经⽹络模型都是假设当前时间步是由前⾯的较早时间步的序列决定的,因此它们都将信息通过隐藏状态从前往后传递。有时候,当前时间步也可能由后⾯时间步决定。例如,当我们写下⼀个句子时,可能会根据句子后⾯的词来修改句子前⾯的⽤词。双向循环神经网络通过增加从后往前传递信息的隐藏层来更灵活地处理这类信息。下图演示了一个含单隐藏层的双向循环神经网络的架构。
然后我们连结两个⽅向的隐藏状态 来得到隐藏状态Ht∈Rn∗2h,并将其输⼊到输出层。输出层计算输出,Ot∈Rn∗q(输出个数为q):
双向循环神经⽹络在每个时间步的隐藏状态同时取决于该时间步之前和之后的子序列(包括当前时间步的输⼊)。
1.5 BPTT算法
在之前你已经见过对于前向传播(上图蓝色箭头所指方向)怎样在神经网络中从左到右地计算这些激活项,直到输出所有地预测结果。而对于反向传播,我想你已经猜到了,反向传播地计算方向(上图红色箭头所指方向)与前向传播基本上是相反的。
在这个计算图中,通过 y′(1)可以计算对应的损失函数,于是计算出第一个时间步的损失函数,然后计算出第二个时间步的损失函数,然后是第三个时间步,一直到最后一个时间步,最后为了计算出总体损失函数,我们要把它们都加起来,通过等式计算出最后的 ,也就是把每个单独时间步的损失函数都加起来。然后你就可以通过导数相关的参数,用梯度下降法来更新参数。
在这个反向传播的过程中,最重要的信息传递或者说最重要的递归运算就是这个从右到左的运算,这也就是为什么这个算法有一个很别致的名字,叫做“通过(穿越)时间反向传播(backpropagation through time)”。取这个名字的原因是对于前向传播,你需要从左到右进行计算,在这个过程中,时刻 不断增加。而对于反向传播,你需要从右到左进行计算,就像时间倒流。“通过时间反向传播”,就像穿越时光,这种说法听起来就像是你需要一台时光机来实现这个算法一样。
2. 其它类型的RNN
- One to one:这个可能没有那么重要,这就是一个小型的标准的神经网络,输入 然后得到输出 。
- One to many:音乐生成,你的目标是使用一个神经网络输出一些音符。对应于一段音乐,输入 可以是一个整数,表示你想要的音乐类型或者是你想要的音乐的第一个音符,并且如果你什么都不想输入, 可以是空的输入,可设为 0 向量。
- Many to one:句子分类问题,输入文档,输出文档的类型。
- Many to many():命名实体识别。
- Many to many():机器翻译。
3. CNN与RNN的区别
4. 为什么RNN 训练的时候Loss波动很大
由于RNN特有的memory会影响后期其他的RNN的特点,梯度时大时小,learning rate没法个性化的调整,导致RNN在train的过程中,Loss会震荡起伏,为了解决RNN的这个问题,在训练的时候,可以设置临界值,当梯度大于某个临界值,直接截断,用这个临界值作为梯度的大小,防止大幅震荡。
门控循环单元(GRU)
1. 什么是GRU
在循环神经网络中的梯度计算方法中,我们发现,当时间步数较大或者时间步较小时,循环神经⽹络的梯度较容易出现衰减或爆炸。虽然裁剪梯度可以应对梯度爆炸,但无法解决梯度衰减的问题。通常由于这个原因,循环神经网络在实际中较难捕捉时间序列中时间步距离较大的依赖关系。
门控循环神经网络(gated recurrent neural network)的提出,正是为了更好地捕捉时间序列中时间步距离较大的依赖关系。它通过可以学习的门来控制信息的流动。其中,门控循环单元(gatedrecurrent unit,GRU)是⼀种常用的门控循环神经网络。
2. 门控循环单元
2.1 重置门和更新门
GRU它引⼊了重置门(reset gate)和更新门(update gate)的概念,从而修改了循环神经网络中隐藏状态的计算方式。
门控循环单元中的重置门和更新门的输入均为当前时间步输入 Xt 与上⼀时间步隐藏状态 Ht−1 ,输出由激活函数为sigmoid函数的全连接层计算得到。 如下图所示:
具体来说,假设隐藏单元个数为 h,给定时间步 t 的小批量输⼊ Xt∈Rn∗d(样本数为n,输⼊个数为d)和上⼀时间步隐藏状态Ht−1∈Rn∗h。重置门 Ht∈Rn∗h和更新门Zt∈Rn∗h 的计算如下:
sigmoid函数可以将元素的值变换到0和1之间。因此,重置门 Rt 和更新门 Zt 中每个元素的值域都是[0,1]。
2.2 候选隐藏状态
接下来,门控循环单元将计算候选隐藏状态来辅助稍后的隐藏状态计算。我们将当前时间步重置门的输出与上⼀时间步隐藏状态做按元素乘法(符号为⊙)。如果重置门中元素值接近0,那么意味着重置对应隐藏状态元素为0,即丢弃上⼀时间步的隐藏状态。如果元素值接近1,那么表⽰保留上⼀时间步的隐藏状态。然后,将按元素乘法的结果与当前时间步的输⼊连结,再通过含激活函数tanh的全连接层计算出候选隐藏状态,其所有元素的值域为[-1,1]。
具体来说,时间步 t 的候选隐藏状态,Ht~∈Rn∗h 的计算为:
从上⾯这个公式可以看出,重置门控制了上⼀时间步的隐藏状态如何流⼊当前时间步的候选隐藏状态。而上⼀时间步的隐藏状态可能包含了时间序列截⾄上⼀时间步的全部历史信息。因此,重置门可以⽤来丢弃与预测无关的历史信息。
2.3 隐藏状态
最后,时间步t的隐藏状态的计算使用当前时间步的更新门 Zt 来对上⼀时间步的隐藏状态 Ht−1 和当前时间步的候选隐藏状态 Ht~ 做组合:
值得注意的是,更新门可以控制隐藏状态应该如何被包含当前时间步信息的候选隐藏状态所更新,如上图所示。假设更新门在时间步 t'到t(t'<t)之间⼀直近似1。那么,在时间步 t'到t间的输入信息几乎没有流入时间步 t 的隐藏状态 Ht 实际上,这可以看作是较早时刻的隐藏状态 直通过时间保存并传递⾄当前时间步 t。这个设计可以应对循环神经⽹络中的梯度衰减问题,并更好地捕捉时间序列中时间步距离较⼤的依赖关系。
我们对门控循环单元的设计稍作总结:
- 重置门有助于捕捉时间序列里短期的依赖关系;
- 更新门有助于捕捉时间序列里长期的依赖关系。
长短期记忆(LSTM)
1. 什么是LSTM
在你阅读这篇文章时候,你都是基于自己已经拥有的对先前所见词的理解来推断当前词的真实含义。我们不会将所有的东西都全部丢弃,然后用空白的大脑进行思考。我们的思想拥有持久性。LSTM就是具备了这一特性。
这篇将介绍另⼀种常用的门控循环神经网络:长短期记忆(long short-term memory,LSTM)。它比门控循环单元的结构稍微复杂⼀点,也是为了解决在RNN网络中梯度衰减的问题,是GRU的一种扩展。
LSTM 中引入了3个门,即输入门(input gate)、遗忘门(forget gate)和输出门(output gate),以及与隐藏状态形状相同的记忆细胞(某些文献把记忆细胞当成⼀种特殊的隐藏状态),从而记录额外的信息。
2. 输入门、遗忘门和输出门
与门控循环单元中的重置门和更新门⼀样,长短期记忆的门的输入均为当前时间步输入 Xt 与上⼀时间步隐藏状态 Ht−1 ,输出由激活函数为sigmoid函数的全连接层计算得到。如此⼀来,这3个门元素的值域均为[0, 1]。如下图所示:
具体来说,假设隐藏单元个数为 h,给定时间步 t 的小批量输入 Xt∈Rn∗d (样本数为n,输⼊个数为d)和上⼀时间步隐藏状态Ht−1∈Rn∗h。三个门的公式如下:
3. 候选记忆细胞
接下来,长短期记忆需要计算候选记忆细胞 Ct~ 。它的计算与上⾯介绍的3个门类似,但使用了值域在[−1, 1]的tanh函数作为激活函数,如下图所示:
具体来说,时间步t的候选记忆细胞计算如下:
4. 记忆细胞
我们可以通过元素值域在[0, 1]的输入门、遗忘门和输出门来控制隐藏状态中信息的流动,这⼀般也是通过使用按元素乘法(符号为⊙)来实现的。当前时间步记忆细胞的计算组合了上⼀时间步记忆细胞和当前时间步候选记忆细胞的信息,并通过遗忘门和输入门来控制信息的流动:
如下图所示,遗忘门控制上⼀时间步的记忆细胞 Ct−1 中的信息是否传递到当前时间步,而输入门则控制当前时间步的输入 Xt 通过候选记忆细胞 Ct~ 如何流⼊当前时间步的记忆细胞。如果遗忘门⼀直近似1且输入门⼀直近似0,过去的记忆细胞将⼀直通过时间保存并传递⾄当前时间步。这个设计可以应对循环神经⽹络中的梯度衰减问题,并更好地捕捉时间序列中时间步距离较⼤的依赖关系。
5. 隐藏状态
有了记忆细胞以后,接下来我们还可以通过输出门来控制从记忆细胞到隐藏状态 Ht 的信息的流动:
这⾥的tanh函数确保隐藏状态元素值在-1到1之间。需要注意的是,当输出门近似1时,记忆细胞信息将传递到隐藏状态供输出层使用;当输出门近似0时,记忆细胞信息只自己保留。下图展示了长短期记忆中隐藏状态的全部计算:
6. LSTM与GRU的区别
LSTM与GRU二者结构十分相似,不同在于:
- 新的记忆都是根据之前状态及输入进行计算,但是GRU中有一个重置门控制之前状态的进入量,而在LSTM里没有类似门;
- 产生新的状态方式不同,LSTM有两个不同的门,分别是遗忘门(forget gate)和输入门(input gate),而GRU只有一种更新门(update gate);
- LSTM对新产生的状态可以通过输出门(output gate)进行调节,而GRU对输出无任何调节。
- GRU的优点是这是个更加简单的模型,所以更容易创建一个更大的网络,而且它只有两个门,在计算性上也运行得更快,然后它可以扩大模型的规模。
- LSTM更加强大和灵活,因为它有三个门而不是两个。
7. LSTM可以使用别的激活函数吗?
关于激活函数的选取,在LSTM中,遗忘门、输入门和输出门使用Sigmoid函数作为激活函数;在生成候选记忆时,使用双曲正切函数Tanh作为激活函数。
值得注意的是,这两个激活函数都是饱和的,也就是说在输入达到一定值的情况下,输出就不会发生明显变化了。如果是用非饱和的激活函数,例如ReLU,那么将难以实现门控的效果。
Sigmoid函数的输出在0~1之间,符合门控的物理定义。且当输入较大或较小时,其输出会非常接近1或0,从而保证该门开或关。在生成候选记忆时,使用Tanh函数,是因为其输出在−1~1之间,这与大多数场景下特征分布是0中心的吻合。此外,Tanh函数在输入为0附近相比Sigmoid函数有更大的梯度,通常使模型收敛更快。
激活函数的选择也不是一成不变的,但要选择合理的激活函数。
一般来说,采用RNN训练时不推荐使用batch normalization方法解决过拟合问题