选自arXiv
作者:Hojjat Salehinejad等
机器之心编译
参与:刘晓坤、路雪、蒋思源
近日,来自多伦多大学和滑铁卢大学的研究者撰文介绍循环神经网络的基础知识、近期发展和面临的挑战。机器之心对该论文进行了编译介绍,重点介绍了论文第二部分循环神经网络的基础与第四部分循环神经网络架构,其中我们概览了该论文所讨论的11种RNN架构。其它部分的详细内容和推导过程请见原论文。
人工神经网络(ANN)由多层互相连接的称为人工神经元的单元构成。「浅层网络」指的是没有循环连接,且只有一个输入层、一个输出层,并至多只有一个隐藏层的 ANN。随着网络层数增加,复杂度也增加。层数或循环连接数的增加通常会增加网络的深度,从而使网络能提供多层次的数据表征以及特征提取,即「深度学习」。一般而言,这些网络由非线性的、简单的单元构成,其中更高的层提供数据的更抽象表征,并压制不需要的可变性 [1]。由于每个层的非线性构成带来的优化困难 [2],直到 2006 年出现重大研究进展之前 [2][3],关于深度网络架构的研究工作很少。结合了循环连接的 ANN 被称为循环神经网络(RNN),可以对序列数据建模,用于序列识别和预测 [4]。RNN 隐藏状态的结构以循环形成记忆的形式工作,每一时刻的隐藏层的状态取决于它的过去状态 [6]。这种结构使得 RNN 可以保存、记住和处理长时期的过去复杂信号。RNN 可以在当前时间步将输入序列映射到输出序列,并预测下一时间步的输出。
从架构设计到应用开发,关于 RNN 的文献已经有大量的论文发表。在本文中,作者重点讨论了离散时间的 RNN 和该领域的最新研究进展,并在表 1 中列出了 RNN 的长期主要进展。反向传播和梯度下降方法的开发使得训练 RNN 变得很高效,加快了开发 RNN 的实际成就 [5]。然而,对长期依赖的序列数据还存在一些挑战,例如梯度消失和梯度爆炸问题,本文将讨论这些问题。
机器之心重点介绍了第二部分循环神经网络的基础与第四部分循环神经网络的架构。该论文的第三部分重点解释了循环神经网络的训练方法,如基于梯度的方法与沿时间反向传播等,我们并不详细探讨这一部分的具体方法。后面第四部分讨论了循环神经网络的正则化方法,限于篇幅,我们也不会过多描述。
论文:Recent Advances in Recurrent Neural Networks
论文链接:https://arxiv.org/pdf/1801.01078.pdf
循环神经网络(RNN)能够从序列和时序数据中学习特征和长期依赖关系。RNN 具备非线性单元的堆叠,其中单元之间至少有一个连接形成有向循环。训练好的 RNN 可以建模任何动态系统;但是,训练 RNN 主要受到学习长期依赖性问题的影响。本论文对 RNN 进行研究,为该领域的新人和专业人员展示多项新的进展。本文介绍了 RNN 的基础知识、近期进展和研究挑战。
图 1:简单的循环神经网络(RNN)及其沿时间 t 的展开结构。每一个箭头代表层之间单元间的全连接。为简洁起见,本图未显示偏置项。
II. 循环神经网络基础
RNN 是一类监督式机器学习模型,由人工神经元和一或多个反馈循环构成 [7]。反馈循环指时间或序列(本文以下使用「时间」)的循环周期 [8],如图 1 所示。以监督式方法训练 RNN 需要一个输入-目标对的训练数据集。其目的在于通过优化网络权重最小化输出和目标对(即损失值)的差。
A. 模型架构
简单 RNN 有三层:输入层、循环隐藏层和输出层,如图 1a 所示。输入层中有 N 个输入单元。该层的输入是一系列沿时间 t 的向量 {..., x_t−1, x_t, x_t+1, ...},其中 x_t = (x_1, x_2, ..., x_N)。全连接 RNN 中的输入单元与隐藏层中的隐藏单元连接,该连接由权重矩阵 W_IH 定义。隐藏层有 M 个隐藏单元 h_t = (h_1, h_2, ..., h_M),它们通过网络定义的循环结构沿时间彼此连接,如图 1b。使用较小非零元素的隐藏单元初始化能够提升网络的整体性能和稳定性 [9]。隐藏层将状态空间或系统的「memory」定义为:
其中 f_H(·) 是隐藏层激活函数,b_h 是隐藏单元的偏置向量。隐藏单元与输出层连接,连接权重为 W_HO。输出层有 P 个单元 y_t = (y_1, y_2, ..., y_P ),可以计算为:
其中 f_O(·) 是激活函数,b_o 是输出层的偏置向量。由于输入-目标对是沿时间的序列,因此上述步骤随着时间 t = (1, ..., T ) 重复。公式 (1) 和 (3) 展示了 RNN 由特定非线性状态公式构成,该公式沿时间迭代。在每个时间步中,隐藏状态根据输入向量预测输出。RNN 的隐藏状态是一组值的集合(除去任何外部因素的影响),该集合总结了与该网络在之前很多时间步上的状态相关的必要信息。该整合信息可定义该网络的未来行为,作出准确的输出预测 [5]。RNN 在每个单元中使用一个简单的非线性激活函数。但是,如果此类简单结构沿时间步经过良好训练,则它能够建模丰富的动态关系。
B. 激活函数
线性网络中,多个线性隐藏层充当单个线性隐藏层 [10]。非线性函数比线性函数强大,因为它们可以绘制非线性边界。RNN 中一个或多个连续隐藏层中的非线性是学习输入-目标关系的关键。
图 2 展示了一些最流行的激活函数。近期 Sigmoid、Tanh 和 ReLU 得到了更多关注。Sigmoid 函数是常见选择,它将真值归一化到 [0, 1] 区间。该激活函数常用语输出层,其中交叉熵损失函数用于训练分类模型。Tanh 和 Sigmoid 激活函数分别被定义为:
Tanh 激活函数实际上是缩放的 Sigmoid 函数,如:
ReLU 是另一个常用激活函数,向正输入值开放 [3],定义为 y(x) = max(x, 0)。
激活函数的选择主要取决于具体问题和数据的本质。例如,Sigmoid 函数适合输出区间为 [0, 1] 的网络。而 Tanh 和 Sigmoid 函数会使神经元快速饱和,并导致梯度消失。Sigmoid 的输出不以零为中心会导致不稳定的权重梯度更新。与 Sigmoid 和 Tanh 函数相比,ReLU 激活函数导致更加稀疏的梯度,并大幅加快随机梯度下降(SGD)的收敛速度 [11]。ReLU 函数的计算成本低廉,因其可通过将激活值二值化为零来实现。但是,ReLU 无法抵抗大型梯度流(gradient flow),随着权重矩阵增大,神经元可能在训练过程中保持未激活状态。
C. 损失函数
损失函数通过对比输出 y_t 和目标 z_t 之间的差距而评估了神经网络的性能,它可以形式化表达为:
该表达式对每一个时间步 [12] 上的损失进行求和而得出最终的损失函数。损失函数的挑选一般与具体问题相关,一般比较流行的损失函数包括预测实数值的欧几里德距离和 Hamming 距离,和用于分类问题 [13] 的交叉熵损失函数。
III. 训练循环神经网络
有效地训练 RNN 一直是重要的话题,该问题的难点在于网络中难以控制的权重初始化和最小化训练损失的优化算法。这两个问题很大程度上是由网络参数之间的关系和隐藏状态的时间动态而引起 [4]。本论文文献综述所展现的关注点很大程度上都在于降低训练算法的复杂度,且加速损失函数的收敛。然而,这样的算法通常需要大量的迭代来训练模型。训练 RNN 的方法包括多表格随机搜索、时间加权的伪牛顿优化算法、梯度下降、扩展 kalman 滤波(EKF)[15]、Hessian-free、期望最大化(EM)[16]、逼近的 Levenberg-Marquardt [17] 和全局优化算法。在这一章节中,本论文具体讨论了这样一些方法。
该论文具体介绍了基于梯度的方法,下表展示了 GD 算法各种变体的优势缺点,其中 N 为神经网络的结点数、O(.) 为每个数据点的复杂度:
其中 BPTT 可能是非常流行的算法,如下所示,当网络随时间推移接收到新的输入,沿时间反向传播将重写激活函数中的隐藏单元。
该论文还讨论了其它非常流行的 SGD 优化策略和二阶梯度优化,如下展示了一般动量法和 Nesterov 加速梯度法之间的差异。
如上所示,左图为一般的动量法,它相当于历史梯度方向和当前梯度方向的加权求和而得到当前最终的下降方向。而右图的 Nesterov 加速梯度法先尝试性地在累积梯度方向上前进一大步,然后再使用当前位置的梯度修正累积梯度而得到最终的下降方向。
这一部分还包含很多优化方法与策略,更详细的内容请查看原论文。
IV. 循环神经网络架构
在该论文中,作者描述了 11 种循环神经网络架构,而且每一种可能还包括一些变体,例如 LSTM 就有八种变体。但限于文章的篇幅,我们只简要介绍了这 11 种循环神经网络架构的基本概念,并且根据我们的理解和往期文章来介绍一般的 LSTM 与 GRU 结构,因此这两部分和论文中所描述的有一些不同。
A. 深度 RNN 结合多层感知机
神经网络的深层架构相比浅层架构可以指数量级高效地表征函数。虽然由于每个隐藏状态都是所有过去隐藏状态的函数,使得循环神经网络在时间上就是内在的深度网络,但是人们已证明其内在运算实际上是很浅层的 [44]。在文献 [44] 中表明,在 RNN 的转换阶段添加一个或多个非线性层可以更好地理解初始输入的潜在变化,从而提升网络的整体性能。结合了感知机层的 RNN 的深度结构可以分成三类:输入到隐藏、隐藏到隐藏,以及隐藏到输出 [44]。
图 5:几种结合多层感知机的深度循环神经网络的架构。
(1)深度输入到隐藏:其基本思想之一是将多层感知机(MLP)结构引入转换和输出阶段,分别称为深度转换 RNN 和深度输出 RNN。
(2)深度隐藏到隐藏和输出:深度 RNN 重点关注于隐藏层的构造。在隐藏层中,来自过去数据抽象和新输入的数据抽象与/或隐藏状态结构都是高度非线性的。
(3)隐藏状态的堆叠:另一种构造深度 RNN 的方法是如图 5d 所示的方式堆叠隐藏层。这种类型的循环结构可以使网络在不同的时间尺度上工作,并允许网络处理多种时间尺度的输入序列 [44]。
B. 双向 RNN(Bidirectional RNN)
传统的 RNN 在训练过程中只考虑数据的过去状态。虽然在很多应用中只考虑过去状态已经充分有效(例如语音识别),但是探索未来的状态也是很有用的 [43]。之前,人们尝试通过对输出延迟确定时间帧数,以在 RNN 的基础架构上利用未来状态作为当前预测的环境。然而,这种方法需要在所有的实现中手动优化延迟时间。而双向 RNN(BRNN)利用了过去和未来的所有可用输入序列评估输出向量 [46]。其中,需要用一个 RNN 以正向时间方向处理从开始到结束的序列,以及用另一个 RNN 处理以反向时间方向处理从开始到结束的序列,如图 6 所示。
图 6:双向 RNN 按时间展开。
C. 循环卷积神经网络
然而,RNN 中仍然缺乏在多个维度对上下文依赖关系的理解。其中最流行的网络架构使用了卷积神经网络(CNN)解决这些问题。
将循环连接整合到每个卷积层中,可以构成循环卷积神经网络(RCNN)[47]。RCNN 单元的激活值依赖于近邻的单元而随时间变化。这种方法可以整合上下文信息,对于目标识别任务很重要。这种方法可以增加模型的深度,而参数数量通过层间的权重共享保持不变。使用从隐藏层中从输出到输入的循环连接使网络可以建模标签依赖关系,并基于它的过去输出平滑输出 [48]。这种 RCNN 方法可以将大量输入上下文馈送到网络中去,同时限制模型的容量。这个系统可以用较低的推理成本建模复杂的空间依赖关系。
D. 多维循环神经网络
多维循环神经网络(MDRNN)是 RNN 的高维序列学习的另一种实现。这种网络在每个维度使用循环连接以学习数据内的关系。
图 7:二维 RNN 的序列排序的前向传递。隐藏层平面的连接是循环的。沿 x_1 和 x_2 的线展示了(从左上角开始)被访问的过去状态的扫描带。
E. 长短期记忆(LSTM)
使用传统的通过时间的反向传播(BPTT)或实时循环学习(RTTL/Real Time Recurrent Learning),在时间中反向流动的误差信号往往会爆炸(explode)或消失(vanish)。但LSTM可以通过遗忘和保留记忆的机制减少这些问题。
LSTM 单元一般会输出两种状态到下一个单元,即单元状态和隐藏状态。记忆块负责记忆各个隐藏状态或前面时间步的事件,这种记忆方式一般是通过三种门控机制实现,即输入门、遗忘门和输出门。
以下是 LSTM 单元的详细结构,其中 Z 为输入部分,Z_i、Z_o 和 Z_f 分别为控制三个门的值,即它们会通过激活函数 f 对输入信息进行筛选。一般激活函数可以选择为 Sigmoid 函数,因为它的输出值为 0 到 1,即表示这三个门被打开的程度。
图片来源于李弘毅机器学习讲义。
若我们输入 Z,那么该输入向量通过激活函数得到的 g(Z) 和输入门 f(Z_i ) 的乘积 g(Z) f(Z_i ) 就表示输入数据经筛选后所保留的信息。Z_f 控制的遗忘门将控制以前记忆的信息到底需要保留多少,保留的记忆可以用方程 c*f(z_f)表示。以前保留的信息加上当前输入有意义的信息将会保留至下一个 LSTM 单元,即我们可以用 c' = g(Z)f(Z_i) + cf(z_f) 表示更新的记忆,更新的记忆 c' 也表示前面与当前所保留的全部有用信息。我们再取这一更新记忆的激活值 h(c') 作为可能的输出,一般可以选择 tanh 激活函数。最后剩下的就是由 Z_o 所控制的输出门,它决定当前记忆所激活的输出到底哪些是有用的。因此最终 LSTM 的输出就可以表示为 a = h(c')f(Z_o)。
F. 门控循环单元(GRU)
GRU 背后的原理与 LSTM 非常相似,即用门控机制控制输入、记忆等信息而在当前时间步做出预测,表达式由以下给出:
GRU 有两个有两个门,即一个重置门(reset gate)和一个更新门(update gate)。从直观上来说,重置门决定了如何将新的输入信息与前面的记忆相结合,更新门定义了前面记忆保存到当前时间步的量。如果我们将重置门设置为 1,更新门设置为 0,那么我们将再次获得标准 RNN 模型。
为了解决标准 RNN 的梯度消失问题,GRU 使用了更新门(update gate)与重置门(reset gate)。基本上,这两个门控向量决定了哪些信息最终能作为门控循环单元的输出。这两个门控机制的特殊之处在于,它们能够保存长期序列中的信息,且不会随时间而清除或因为与预测不相关而移除。以下展示了单个门控循环单元的具体结构。
门控循环单元
1. 更新门
在时间步 t,我们首先需要使用以下公式计算更新门 z_t:
其中 x_t 为第 t 个时间步的输入向量,即输入序列 X 的第 t 个分量,它会经过一个线性变换(与权重矩阵 W(z) 相乘)。h_(t-1) 保存的是前一个时间步 t-1 的信息,它同样也会经过一个线性变换。更新门将这两部分信息相加并投入到 Sigmoid 激活函数中,因此将激活结果压缩到 0 到 1 之间。以下是更新门在整个单元的位置与表示方法。
本质上来说,重置门主要决定了到底有多少过去的信息需要遗忘,我们可以使用以下表达式计算:
现在我们具体讨论一下这些门控到底如何影响最终的输出。在重置门的使用中,新的记忆内容将使用重置门储存过去相关的信息,它的计算表达式为:
输入 x_t 与上一时间步信息 h_(t-1) 先经过一个线性变换,即分别右乘矩阵 W 和 U。
计算重置门 r_t 与 Uh_(t-1) 的 Hadamard 乘积,即 r_t 与 Uh_(t-1) 的对应元素乘积。因为前面计算的重置门是一个由 0 到 1 组成的向量,它会衡量门控开启的大小。例如某个元素对应的门控值为 0,那么它就代表这个元素的信息完全被遗忘掉。该 Hadamard 乘积将确定所要保留与遗忘的以前信息。
在最后一步,网络需要计算 h_t,该向量将保留当前单元的信息并传递到下一个单元中。在这个过程中,我们需要使用更新门,它决定了当前记忆内容 h'_t 和前一时间步 h_(t-1) 中需要收集的信息是什么。这一过程可以表示为:
z_t 为更新门的激活结果,它同样以门控的形式控制了信息的流入。z_t 与 h_(t-1) 的 Hadamard 乘积表示前一时间步保留到最终记忆的信息,该信息加上当前记忆保留至最终记忆的信息就等于最终门控循环单元输出的内容。
G. 记忆网络
卷积 RNN 可用于储存过去输入特征的记忆容量较小 [71] [72]。记忆神经网络(MemNN)利用成功的学习方法和可读、可写的存储器进行推断。MemNN 是一个对象数组,包括输入、响应、泛化和输出特征图 [71] [73]。它将输入转换成内部特征表示,然后根据新的输入更新记忆。之后使用输入和更新后的记忆计算输出特征,并将其解码来生成输出 [71]。使用 BPTT 训练该网络并不简单,每一层都需要监督 [74]。
循环记忆网络(RMN)利用 LSTM 和 MemNN [75]。RMN 中的记忆模块采用 LSTM 的隐藏状态,并使用注意力机制将它和最近的输入进行对比。RMN 算法分析已训练模型的注意力权重,并按时间从 LSTM 的保留信息中提取知识 [75]。
H. 结构受限循环神经网络
另一个解决梯度消失问题的模型是结构受限循环神经网络(structurally constrained recurrent neural network,SCRN)。这种网络基于隐藏状态在训练过程中快速变化的观察现象而设计,如图 12 所示 [6]。在这种方法中,SCRN 结构通过添加等价于单位长期依赖性关系的特定循环矩阵进行扩展。
图 12:带有语境特征(更长记忆)的循环神经网络
I. 酉循环神经网络
减缓梯度消失与梯度爆炸的一个简单方法是使用 RNN 中的酉矩阵(unitary matrices)。梯度消失与梯度爆炸问题归因于隐藏到隐藏权重矩阵的特征值之一的偏离。因此,为了防止这些特征值偏离,可用酉矩阵取代网络中的一般矩阵。
J. 门控正交循环单元(Gated Orthogonal Recurrent Unit)
门控正交循环单元使用正交矩阵取代隐藏状态循环矩阵(loop matrix),并引入了对 ReLU 激活函数的增强,使得它能够处理复数值输入 [77]。这种单元能够使用酉矩阵捕捉数据的长期依赖关系,同时还能利用 GRU 架构中的遗忘机制。
k. 层级子采样循环神经网络
层级子采样循环神经网络(HSRNN) 旨在通过使用固定的窗口大小进行每个层级的子采样,从而更好地学习长序列 [78]。训练这种网络遵循常规 RNN 训练的流程,然后根据每个层级的窗口大小进行略微修改。
以上是循环神经网络的 11 中架构,这一部分其实有详细的解释,但我们并没有深入讨论。该论文后面还讨论了 RNN 中的正则化技术,包括 L1 和 L2 正则化、Dropout、激活值稳定归一化和其它正则化方法。我们只是简要介绍了该论文的基本结构与概念,很多详细的推导与实现都需要读者深入阅读原论文。尽管如此,但本文从 RNN 的基础到循环架构还是全面概述了近年来 RNN 的研究与进步。