6.2.1 递归神经网络(RNN)
对于不同的任务,存在不同类型的神经网络体系结构。这里介绍在时间序列中用得最多的递归神经网络(recurrent neural networks,RNN),它是很多深度学习处理时间序列模型的基础。
递归神经网络主要用于自然语言处理,典型的例子是翻译。在处理序列时,它与中枢神经系统有许多共同的方面,都在每个时间步骤应用了递归。此外,模型大小不会随着输入的大小(可以是任何长度)而增加。当输入到下一层时,RNNs允许层具有隐藏状态,因此历史值可以在预测中发挥作用(尽管在输入序列中访问非常早期的数据相对困难)。
RNNs包含:输入单元(input units),输入集标记为{x0,x1,…,xt,xt+1,…};输出单元(output units),输出集标记为{y0,y1,…,yt,yt+1,…};隐藏单元(hidden units),输出集标记为{s0,s1,…,st,st+1,…}。
在图6-1中有一条单向流动的信息流是从输入单元到达隐藏单元的,与此同时另一条单向流动的信息流从隐藏单元到达输出单元。在某些情况下,RNNs会打破后者的限制,引导信息从输出单元返回隐藏单元,这些被称为“Back Projections”,并且隐藏层的输入还包括上一隐藏层的状态,即隐藏层内的节点可以自连也可以互连。

图6-1 RNN结构图
如图6-1所示,循环神经网络展开成一个全神经网络。例如,对一个包含5个单词的语句,展开的网络便是一个五层的神经网络,每一层代表一个单词。对于该网络的计算过程如下:
(1)xt表示第t(t=1,2,3…)步的输入。例如,x1为第二个词的one-hot向量(根据图6-1,x0为第一个词)。
(2)st为隐藏层的第t步的状态,它是网络的记忆单元。st根据当前输入层的输出与上一步隐藏层的状态进行计算。st=f(Uxt+Wst-1),其中f一般是非线性的激活函数,如tanh或ReLU,在计算s0时,即第一个单词的隐藏层状态,需要用到s-1,但是其并不存在,在实现中一般置为0向量。
(3)ot是第t步的输出,如下个单词的向量表示ot=Softmax(Vst)。
需要注意的是:
·我们可以认为隐藏层状态st是网络的记忆单元。st包含了前面所有步的隐藏层状态。而输出层的输出ot只与当前步的st有关,在实践中,为了降低网络的复杂度,往往st只包含前面若干步而不是所有步的隐藏层状态。
·在RNNs中,每输入一步,每一层各自都共享参数U、V、W。其反映了RNNs中的每一步都在做相同的事,只是输入不同,因此大大地降低了网络中需要学习的参数。
·图6-1中每一步都会有输出,但不是必需的。例如,我们需要预测一条语句所表达的情绪,仅仅需要关心最后一个单词输入后的输出,而不需要知道每个单词输入后的输出,同理每步也不是必须需要输入。RNNs的关键之处在于隐藏层,隐藏层能够捕捉序列的信息。
这个网络在t时刻接收到输入xt之后,隐藏层的值是st,输出值是ot。关键一点是,st的值不仅仅取决于xt,还取决于st-1。我们可以用下面的公式来表示循环神经网络的计算方法:

式(6-11)是输出层的计算公式,输出层是一个全连接层,也就是说它的每个节点都和隐藏层的每个节点相连。V是输出层的权重矩阵,g是激活函数。式(6-12)是隐藏层的计算公式,它是循环层。U是输入x的权重矩阵,W是上一次的值st-1作为这一次的输入的权重矩阵,f是激活函数。
从上面的公式可以看出,循环层和全连接层的区别就是循环层多了一个权重矩阵W。
如果将式(6-12)代入式(6-11),我们将得到:

从上面可以看出,循环神经网络的输出值ot,是受前面历次输入值xt,xt-1,xt-2,x-3,…影响的,这就是为什么循环神经网络可以往前看任意多个输入值的原因。
如果将RNNs进行网络展开,那么参数W、U、V是共享的,并且在使用梯度下降算法中,每一步的输出不仅依赖当前步网络的状态,还依赖前面若干步网络的状态。例如,当t=4时,还需要向后传递三步,后面的三步都需要加上各种梯度。该学习算法称为Back Propagation Through Time(BPTT)。BPTT算法是针对循环层的训练算法,它的基本原理和BP算法是一样的,也包含同样的四个步骤:
(1)前向计算每个神经元的输出值;
(2)反向计算每个神经元的误差项值δj,它是误差函数E对神经元j的加权输入的netj偏导数;
(3)计算每个权重的梯度;
(4)最后再用随机梯度下降算法更新权重。
需要意识到的是,在RNNs训练中,BPTT无法解决长时依赖问题(即当前的输出与前面很长的一段序列有关,一般超过十步就无能为力了),因为BPTT会带来所谓的梯度消失或梯度爆炸问题(the vanishing/exploding gradient problem)。
6.2.2 时间序列深度学习模型LSTM
时间序列的序列到序列建模在过去几年中相当流行,不仅仅是在工业领域,从研究领域到Kaggle竞赛也是如此。序列到序列模型具体指的是神经网络,其中输入是序列(如时间序列),输出的也是序列。为了允许序列操作,模型需要跟踪序列的历史相关性,记住时间索引排序,并允许在序列的持续时间内进行参数调整。其中最常见的是长短期记忆(long short term memory network,LSTM)模型。
长短期记忆(LSTM)模型是RNN的一种类型,随着时间的推移学习从输入到输出的映射,但是该映射不再像标准RNN那样固定。在RNN的反向传播中,出现的一个问题是梯度消失和爆炸。为了解决这个问题,LSTM使用“门”来控制信息流,允许它们“过滤”不太有用的历史信息,其结构如图6-2所示。

图6-2 LSTM结构图
长短期记忆网络成功地解决了原始循环神经网络的缺陷,成为当前最流行的RNN,在语音识别、图片描述、自然语言处理等许多领域中得到成功应用。
原始RNN的隐藏层只有一个状态h,它对于短期的输入非常敏感。那么可以再增加一个状态c,让它来保存长期的状态,如图6-3所示。(https://www.daowen.com)

图6-3 RNN与LSTM单元比较图
新增加的状态c,称为单元状态(cell state)。我们把图6-3按照时间维度展开,如图6-4所示。
图6-4仅仅是一个示意图。从图6-4可以看出,在t时刻,LSTM的输入有3个:当前时刻网络的输入值xt、上一时刻LSTM的输出值ht-1以及上一时刻的单元状态ct-1;LSTM的输出有2个:当前时刻LSTM输出值ht和当前时刻的单元状态ct。注意:x、c、h都是向量。

图6-4 LSTM单元展开图
LSTM的关键就是如何控制长期状态c。在这里,LSTM的思路是使用3个控制开关:第一个开关,负责控制继续保存长期状态c;第二个开关,负责控制把即时状态输入到长期状态c;第三个开关,负责控制是否把长期状态c作为当前的LSTM的输出。3个开关的作用如图6-5所示。

图6-5 LSTM开关控制图
上述3个控制开关是如何在算法中实现的呢?这就用到了门(gate)的概念。门实际上就是一层全连接层,它的输入是一个向量,输出是一个0~1的实数向量。假设W是门的权重向量,b是偏置项,那么门可以表示为
![]()
门的使用,就是用门的输出向量按元素乘以我们需要控制的那个向量。因为门的输出是0~1的实数向量,那么当门输出为0时,任何向量与之相乘都会得到0向量,这就相当于啥都不能通过;当门输出为1时,任何向量与之相乘都不会有任何改变,这就相当于啥都可以通过。因为σ(也就是sigmoid函数)的值域是(0,1),所以门的状态都是半开半闭的。
LSTM用2个门来控制单元状态c的内容:一个是遗忘门(forget gate),它决定了上一时刻的单元状态ct-1有多少保留到当前时刻ct;另一个是输入门(input gate),它决定了当前时刻网络的输入xt有多少保存到单元状态ct。LSTM用输出门(output gate)来控制单元状态ct有多少输出到LSTM的当前输出值ht。
我们先来看一下遗忘门:
![]()
式中:Wf是遗忘门的权重矩阵;[ht-1,xt]表示把两个向量连接成一个更长的向量;bf是遗忘门的偏置项;σ是sigmoid函数。如果输入的维度是dx,隐藏层的维度是dh,单元状态的维度是dc(通常dc=dh),则遗忘门的权重矩阵Wf维度是dc×(dh+dx)。事实上,权重矩阵Wf都是由两个矩阵拼接而成的:一个是Whf,它对应着输入项ht-1,其维度为dc×dh;另一个是Wfx,它对应着输入项dc×dx,其维度为dc×dx。Wf可以写为

接下来看看输入门:
![]()
式中:Wi是输入门的权重矩阵;bi是输入门的偏置项。
接下来,计算用于描述当前输入的单元状态
,它是根据上一次的输出和本次输入来计算的:
![]()
现在,计算当前时刻的单元状态ct。它是由上一次的单元状态ct-1按元素乘以遗忘门ft,再用当前输入的单元状态
按元素乘以输入门it,再将两个积加和产生的:
![]()
式中:符号。表示按元素乘。
这样,我们就把LSTM关于当前的记忆
和长期的记忆ct-1组合在一起,形成新的单元状态ct。由于遗忘门的控制,它可以保存很久之前的信息,由于输入门的控制,它又可以避免保存当前无关紧要的内容。下面,我们要看看输出门,它控制了长期记忆对当前输出的影响:
![]()
LSTM最终的输出是由输出门和单元状态共同确定的:
![]()
式(6-15)~式(6-21)就是LSTM前向计算的全部公式。
LSTM的训练算法仍然是反向传播算法,主要有以下三个步骤:
(1)前向计算每个神经元的输出值,对于LSTM来说,即ft、it、ct、ot、ht 5个向量的值。
(2)反向计算每个神经元的误差项值δ。与循环神经网络一样,LSTM误差项的反向传播也包括两个方向:一个是沿时间的反向传播,即从当前t时刻开始,计算每个时刻的误差项;另一个是将误差项向上一层传播。
(3)根据相应的误差项,计算每个权重的梯度。