循环神经网络(Recurrent Neural Network, RNN)是一类以序列(sequence)数据为输入,在序列的演进方向进行递归(recursion)且所有节点(循环单元)按链式连接的递归神经网络(recursive neural network) [1] 。 对循环神经网络的研究始于二十世纪80-90年代,并在二十一世纪初发展为深度学习(deep learning)算法之一 [2] ,其中双向循环神经网络(Bidirectional RNN, Bi-RNN)和长短期记忆网络(Long Short-Term Memory networks,LSTM)是常见的循环神经网络 [3] 。 循环神经网络具有记忆性、参数共享并且图灵完备(Turing completeness),因此在对序列的非线性特征进行学习时具有一定优势 [4] 。循环神经网络在自然语言处理(Natural Language Processing, NLP),例如语音识别、语言建模、机器翻译等领域有应用,也被用于各类时间序列预报。引入了卷积神经网络(Convolutional Neural Network,CNN)构筑的循环神经网络可以处理包含序列输入的计算机视觉问题。

1、为什么需要RNN

神经网络可以当做是能够拟合任意函数的黑盒子,只要训练数据足够,将神经网络模型训练好之后,在输入层给定一个x,通过网络之后就能够在输出层得到特定的y,那么既然有了这么强大的模型,为什么还需要RNN(循环神经网络)呢?

RNN只能单独的取处理一个个的输入,前一个输入和后一个输入是完全没有关系的。但是,某些任务需要能够更好的处理序列的信息,即前面的输入和后面的输入是有关系的。所以为了解决一些这样类似的问题,能够更好的处理序列的信息,RNN就诞生了。

2、RNN基本原理

2.1、基本原理

假设用户输入:what time is it?首先,我们将句子分解为单个单词。RNN按顺序工作,所以我们一次只能输入一个字。
1.gif

第一步是将“What”输入RNN,RNN编码“what”并产生输出。

2.gif

对于下一步,我们提供单词“time”和上一步中的隐藏状态。RNN现在有关于“what”和“time”这两个词的信息。

3.gif

我们重复这个过程,直到最后一步。你可以通过最后一步看到RNN编码了前面步骤中所有单词的信息。

4.gif

由于最终输出是从序列的部分创建的,因此我们应该能够获取最终输出并将其传递给前馈层以对意图进行分类。

5.gif

首先,初始化网络层和初始隐藏状态。隐藏状态的形状和维度将取决于你的递归神经网络的形状和维度。然后循环输入,将单词和隐藏状态传递给RNN。RNN返回输出和修改的隐藏状态,接着就继续循环。最后,将输出传递给前馈层,然后返回预测。整个过程就是这样!进行递归神经网络的正向传递的控制流程是for循环。

2.2、memory单元

设想一个简单的前馈神经网络,输入、输出、隐层均只有一个神经元,如下图。这里的圆圈没有任何抽象的含义,一个圆圈就是一个神经元:

image.png

当输入时间序列的第一个数据点后,就把这时隐层的值用一个记忆单元存起来,这个记忆单元并不是一个实体,而是一个用来存取东西的结构:
image.png
我们存入的memory单元的作用就存取了X1的特征,当我们输入时间序列的第二个数据点时,要注意,网络的结构保持不变,只是我们将memory中的信息也输入到隐层中,相当于,第二个数据点的隐层接受了数据和第一个数据点的特征进行输出,同时将此时隐层的信息返回到memory,再次存起来:
image.png
在第三个数据点输入的时候,memory单元所操作就是前一步得到的信息,并将得到的信息存起来,供下一个时间步的输入:
image.png
这样依次进行下去,就得到了与大家喜闻乐见的那幅图类似的结构,为了表达先前的信息对现在的影响,我们在输入memory单元时,采用一个权值矩阵W参数化记忆单元,那么一一对应关系就变成了:
image.png

3、RNN结构

一般的MLP结构,不同时序之间没有联系:
image.png
RNN结构,不同时序的关系:
image.png

一个简单的循环神经网络如,它由输入层、一个隐藏层和一个输出层组成:

image.png

X是一个向量,它表示输入层的值(这里面没有画出来表示神经元节点的圆圈); S是一个向量,它表示隐藏层的值(这里隐藏层面画了一个节点,你也可以想象这一层其实是多个节点,节点数与向量S的维度相同); U是输入层到隐藏层的权重矩阵; O也是一个向量,它表示输出层的值; V是隐藏层到输出层的权重矩阵; W权重矩阵就是隐藏层上一次的值作为这一次的输入的权重。循环神经网络的隐藏层的值S不仅仅取决于当前这次的输入X,还取决于上一次隐藏层的值S。

image.png

从上图就能够很清楚的看到,上一时刻的隐藏层是如何影响当前时刻的隐藏层的。如果把上面的图展开,循环神经网络结构如下:

image.png

这个网络在t时刻接收到输入 [公式] 之后,隐藏层的值是 [公式] ,输出值是 [公式] 。关键一点是, [公式] 的值不仅仅取决于 [公式] ,还取决于 [公式] 。我们可以用下面的公式来表示循环神经网络的计算方法:

image.png

4、RNN分类

RNN大致可以分为4种,输出和输入序列不同数量rnn可以有多种不同的结构,不同结构自然就有不同的引用场合。image.png

one to one 结构: 仅仅只是简单的给一个输入得到一个输出,此处并未体现序列的特征,例如图像分类场景。 one to many 结构:给一个输入得到一系列输出,这种结构可用于生产图片描述的场景。 many to one 结构: 给一系列输入得到一个输出,这种结构可用于文本情感分析,对一些列的文本输入进行分类,看是消极还是积 极情感。 many to many 结构: 给一些列输入得到一系列输出,这种结构可用于翻译或聊天对话场景,对输入的文本转换成另外一些列文本。 同步 many to many 结构: 它是经典的rnn结构,前一输入的状态会带到下一个状态中,而且每个输入都会对应一个输出,我们最熟悉的就是用于字符预测了,同样也可以用于视频分类,对视频的帧打标签。

5、RNN缺陷

你可能已经注意到隐藏状态中奇怪的颜色分布。这是为了说明RNN被称为短期记忆的问题。
image.png

短期记忆问题是由臭名昭着的梯度消失问题引起的,这在其他神经网络架构中也很普遍。由于RNN处理很多步骤,因此难以保留先前步骤中的信息。正如你所看到的,在最后的时间步骤中,“what”和“time”这个词的信息几乎不存在。短期记忆和梯度消失是由于反向传播的性质引起的,反向传播是用于训练和优化神经网络的算法。为了理解这是为什么,让我们来看看反向传播对深度前馈神经网络的影响。

训练神经网络有三个主要步骤。
首先,它进行前向传递并进行预测。
其次,它使用损失函数将预测与基础事实进行比较。损失函数输出一个错误值,该错误值是对网络执行得有多糟糕的估计。
最后,它使用该误差值进行反向传播,计算网络中每个节点的梯度。
7.gif

梯度是用于调整网络内部权重的值从而更新整个网络。梯度越大,调整越大,反之亦然,这也就是问题所在。在进行反向传播时,图层中的每个节点都会根据渐变效果计算它在其前面的图层中的渐变。因此,如果在它之前对层的调整很小,那么对当前层的调整将更小。

这会导致渐变在向后传播时呈指数级收缩。由于梯度极小,内部权重几乎没有调整,因此较早的层无法进行任何学习。这就是消失的梯度问题。

8.gif

为了训练一个递归神经网络,使用了一种称为通过时间反向传播的方法。这样梯度值在每个时间步长传播时将呈指数级收缩。同样,梯度值将用于在神经网络权重中进行调整,从而允许其学习。小的渐变意味着小的调整。这将导致最前面的层没有优化。

由于梯度消失,RNN不会跨时间步骤学习远程依赖性。这意味着在尝试预测用户的意图时,有可能不考虑“what”和“time”这两个词。然后网络就可能作出的猜测是“is it?”。这很模糊,即使是人类也很难辨认这到底是什么意思。因此,无法在较早的时间步骤上学习会导致网络具有短期记忆。

LSTM和GRU
RNN会受到短期记忆的影响,那么我们如何应对呢?为了减轻短期记忆的影响,研究者们创建了两个专门的递归神经网络,一种叫做长短期记忆或简称LSTM。另一个是门控循环单位或GRU。LSTM和GRU本质上就像RNN一样,但它们能够使用称为“门”的机制来学习长期依赖。这些门是不同的张量操作,可以学习添加或删除隐藏状态的信息。由于这种能力,短期记忆对他们来说不是一个问题。如果你想了解有关LSTM和GRU的更多信息,你可以在其上查看我的插图视频。

总结

总而言之,RNN适用于处理序列数据以进行预测,但却会受到短期记忆的影响。RNN具有更快训练和使用更少计算资源的优势,这是因为要计算的张量操作较少。

image.png