美文网首页
循环神经网络

循环神经网络

作者: 单调不减 | 来源:发表于2019-07-29 23:10 被阅读0次

    花书中关于RNN的内容记录于https://www.jianshu.com/p/206090600f13

    在前馈神经网络中,信息的传递是单向的,这种限制虽然使得网络变得更容易学习,但在一定程度上也减弱了神经网络模型的能力。在生物神经网络中,神经元之间的连接关系要复杂的多。前馈神经网络可以看作是一个复杂的函数,每次输入都是独立的,即网络的输出只依赖于当前的输入。但是在很多现实任务中,网络的输入不仅和当前时刻的输入相关,也和其过去一段时间的输出相关。因此,前馈网络难以处理时序数据,比如视频、语音、文本等。时序数据的长度一般是不固定的,而前馈神经网络要求输入和输出的维数都是固定的,不能任意改变。因此,当处理这一类和时序相关的问题时,就需要一种能力更强的模型。

    循环神经网络(Recurrent Neural Network,RNN)是一类具有短期记忆能力的神经网络。在循环神经网络中,神经元不但可以接受其它神经元的信息,也可以接受自身的信息,形成具有环路的网络结构。和前馈神经网络相比,循环神经网络更加符合生物神经网络的结构。循环神经网络已经被广泛应用在语音识别、语言模型以及自然语言生成等任务上。循环神经网络的参数学习可以通过随时间反向传播算法来学习。

    1、给网络增加记忆能力

    为了处理这些时序数据并利用其历史信息,我们需要让网络具有短期记忆能力。而前馈网络是一个静态网络,不具备这种记忆能力。

    1.1、延时神经网络

    一种简单的利用历史信息的方法是建立一个额外的延时单元,用来存储网络的历史信息(可以包括输入、输出、隐状态等)。比较有代表性的模型是延时神经网络。

    延时神经网络是在前馈网络中的非输出层都添加一个延时器,记录最近几次神经元的输出。在第t个时刻,第l + 1层神经元和第l层神经元的最近p次输出相关,即:

    \mathbf{h}_{t}^{(l+1)}=f\left(\mathbf{h}_{t}^{(l)}, \mathbf{h}_{t-1}^{(l)}, \cdots, \mathbf{h}_{t-p}^{(l)}\right)

    延时神经网络在时间维度上共享权值,以降低参数数量。因此对于序列输入来讲,延时神经网络就相当于卷积神经网络

    1.2、有外部输入的非线性自回归模型

    自回归模型(Autoregressive Model,AR)是统计学上常用的一类时间序列模型,用一个变量y_t的历史信息来预测自己:

    \mathbf{y}_{t}=w_{0}+\sum_{i=1}^{p} w_{p} \mathbf{y}_{t-i}+\epsilon_{t}

    其中p为超参数,w_p为参数,\epsilon_{t} \sim \mathcal{N}\left(0, \sigma^{2}\right)为第t个时刻的噪声,方差σ^2和时间无关。

    有外部输入的非线性自回归模型(Nonlinear Autoregressive with ExogenousInputs Model,NARX)是自回归模型的扩展,在每个时刻t都有一个外部输入x_t,产生一个输出y_t。NARX通过一个延时器记录最近几次的外部输入和输出,第t个时刻的输出y_t为:

    \mathbf{y}_{t}=f\left(\mathbf{x}_{t}, \mathbf{x}_{t-1}, \cdots, \mathbf{x}_{t-p}, \mathbf{y}_{t-1}, \mathbf{y}_{t-2}, \cdots, \mathbf{y}_{t-q}\right)

    其中f(·)表示非线性函数,可以是一个前馈网络,pq为超参数。

    1.3、循环神经网络

    循环神经网络通过使用带自反馈的神经元,能够处理任意长度的时序数据。

    给定一个输入序列\mathbf{x}_{1 : T}=\left(\mathbf{x}_{1}, \mathbf{x}_{2}, \dots, \mathbf{x}_{t}, \dots, \mathbf{x}_{T}\right),循环神经网络通过下面
    公式更新带反馈边的隐藏层的活性值h_t

    \mathbf{h}_{t}=f\left(\mathbf{h}_{t-1}, \mathbf{x}_{t}\right)

    其中h_0 = 0f(·)为一个非线性函数,也可以是一个前馈网络。

    从数学上讲,上式可以看成一个动力系统。动力系统(Dynamical System)是一个数学上的概念,指系统状态按照一定的规律随时间变化的系统。具体地讲,动力系统是使用一个函数来描述一个给定空间(如某个物理系统的状态空间)中所有点随时间的变化情况。因此,隐藏层的活性值h_t在很多文献上也称为状态(State)或隐状态(Hidden States)。理论上,循环神经网络可以近似任意的非线性动力系统。

    2、简单循环网络

    简单循环网络(Simple Recurrent Network,SRN)是一个非常简单的循环神经网络,只有一个隐藏层的神经网络。

    在一个两层的前馈神经网络中,连接存在相邻的层与层之间,隐藏层的节点之间是无连接的。而简单循环网络增加了从隐藏层到隐藏层的反馈连接

    假设在时刻t时,网络的输入为x_t,隐藏层状态(即隐藏层神经元活性值)h_t不仅和当前时刻的输入x_t相关,也和上一个时刻的隐藏层状态h_{t−1}相关:

    \begin{array}{l}{\mathbf{z}_{t}=U \mathbf{h}_{t-1}+W \mathbf{x}_{t}+\mathbf{b}} \\ {\mathbf{h}_{t}=f\left(\mathbf{z}_{t}\right)}\\ \end{array}

    其中z_t为隐藏层的净输入,f(·)是非线性激活函数,通常为Logistic函数或Tanh函数,U为状态-状态权重矩阵,W为状态-输入权重矩阵,b为偏置。上面两式也经常直接写为:

    \mathbf{h}_{t}=f\left(U \mathbf{h}_{t-1}+W \mathbf{x}_{t}+\mathbf{b}\right)

    如果我们把每个时刻的状态都看作是前馈神经网络的一层的话,循环神经网络可以看作是在时间维度上权值共享的神经网络。下图给出了按时间展开的循环神经网络。

    由于循环神经网络具有短期记忆能力,相当于存储装置,因此其计算能力十分强大。前馈神经网络可以模拟任何连续函数,而循环神经网络可以模拟任何程序。

    定义一个完全连接的循环神经网络,其输入为x_t,输出为y_t

    \begin{aligned} \mathbf{h}_{t} &=f\left(U \mathbf{h}_{t-1}+W \mathbf{x}_{t}+\mathbf{b}\right) \\ \mathbf{y}_{t} &=V \mathbf{h}_{t} \\ \end{aligned}

    其中h为隐状态,f(·)为非线性激活函数,U、W、bV为网络参数。

    这样一个完全连接的循环神经网络可以近似解决所有的可计算问题

    3、应用到机器学习

    循环神经网络可以应用到很多不同类型的机器学习任务。根据这些任务的特点可以分为以下几种模式:序列到类别模式、同步的序列到序列模式、异步的序列到序列模式

    3.1、序列到类别模式

    序列到类别模式主要用于序列数据的分类问题:输入为序列,输出为类别。比如在文本分类中,输入数据为单词的序列,输出为该文本的类别。

    假设一个样本\mathbf{x}_{1 : T}=\left(\mathbf{x}_{1}, \cdots, \mathbf{x}_{T}\right)为一个长度为T的序列,输出为一个类别y \in\{1, \cdots, C\}。我们可以将样本x按不同时刻输入到循环神经网络中,并得到不同时刻的隐藏状态\mathbf{h}_{1}, \cdots, \mathbf{h}_{T}。我们可以将h_T看作整个序列的最终表示(或特征),并输入给分类器g(·)进行分类:

    \hat{y}=g\left(\mathbf{h}_{T}\right)

    其中g(·)可以是简单的线性分类器(比如Logistic 回归)或复杂的分类器(比如多层前馈神经网络)

    除了将最后时刻的状态作为序列表示之外,我们还可以对整个序列的所有状态进行平均,并用这个平均状态来作为整个序列的表示:

    \hat{y}=g\left(\frac{1}{T} \sum_{t=1}^{T} \mathbf{h}_{t}\right)

    3.2、同步的序列到序列模式

    同步的序列到序列模式主要用于序列标注(Sequence Labeling)任务,即每一时刻都有输入和输出,输入序列和输出序列的长度相同。比如词性标注(Partof-Speech Tagging)中,每一个单词都需要标注其对应的词性标签。

    输入为序列\mathbf{x}_{1 : T}=\left(\mathbf{x}_{1}, \cdots, \mathbf{x}_{T}\right),输出为序列y_{1 : T}=\left(y_{1}, \cdots, y_{T}\right)。样本x按不同时刻输入到循环神经网络中,并得到不同时刻的隐状态h_1,\cdots,h_T。每个时刻的隐状态h_t代表当前和历史的信息,并输入给分类器g(·)得到当前时刻的标签\hat{y}_{t}

    \hat{y}_{t}=g\left(\mathbf{h}_{t}\right), \quad \forall t \in[1, T]

    3.3、异步的序列到序列模式

    异步的序列到序列模式也称为编码器-解码器(Encoder-Decoder)模型,即输入序列和输出序列不需要有严格的对应关系,也不需要保持相同的长度。比如在机器翻译中,输入为源语言的单词序列,输出为目标语言的单词序列。

    在异步的序列到序列模式中,输入为长度为T的序列\mathbf{x}_{1 : T}=\left(\mathbf{x}_{1}, \cdots, \mathbf{x}_{T}\right),输出为长度为M的序列y_{1 : T}=\left(y_{1}, \cdots, y_{M}\right)。经常通过先编码后解码的方式来实现。先将样本x按不同时刻输入到一个循环神经网络(编码器)中,并得到其编码h_T。然后再使用另一个循环神经网络(解码器)中,得到输出序列\hat{y}_{1:M}。为了建立输出序列之间的依赖关系,在解码器中通常使用非线性的自回归模型。

    \begin{aligned} \mathbf{h}_{t}&=f_{1}\left(\mathbf{h}_{t-1}, \mathbf{x}_{t}\right),&\forall t \in[1, T]\\ \mathbf{h}_{T+t} &=f_{2}\left(\mathbf{h}_{T+t-1}, \hat{\mathbf{y}}_{t-1}\right),&\forall t \in[1, M] \\ \hat{y}_{t} &=g\left(\mathbf{h}_{T+t}\right),&\forall t \in[1, M] \end{aligned}

    其中f1(·), f2(·)分别为用作编码器和解码器的循环神经网络,g(·)为分类器,\hat{\mathbf{y}}_{t}为预测输出\hat{y}_{t}的向量表示。

    4、参数学习

    循环神经网络的参数可以通过梯度下降方法来进行学习。给定一个训练样本(x, y),其中\mathbf{x}_{1 : T}=\left(\mathbf{x}_{1}, \cdots, \mathbf{x}_{T}\right)为长度是T的输入序列,y_{1 : T}=\left(y_{1}, \cdots, y_{T}\right)是长度为T的标签序列。即在每个时刻t,都有一个监督信息y_t,我们定义时刻t的损失函数为:

    \mathcal{L}_{t}=\mathcal{L}\left(y_{t}, g\left(\mathbf{h}_{t}\right)\right)

    其中g\left(\mathbf{h}_{t}\right)为第t时刻的输出,\mathcal{L}为可微分的损失函数,比如交叉熵。那么整个序列上损失函数为:

    \mathcal{L}=\sum_{t=1}^{T} \mathcal{L}_{t}

    整个序列的损失函数\mathcal{L}关于参数U的梯度为:

    \frac{\partial \mathcal{L}}{\partial U}=\sum_{t=1}^{T} \frac{\partial \mathcal{L}_{t}}{\partial U}

    即每个时刻损失\mathcal{L}_{t}对参数U的偏导数之和。

    循环神经网络中存在一个递归调用的函数f(·),因此其计算参数梯度的方式和前馈神经网络不太相同。在循环神经网络中主要有两种计算梯度的方式:随时间反向传播(BPTT)和实时循环学习(RTRL)算法。

    4.1、随时间反向传播算法(BPTT)

    随时间反向传播(Backpropagation Through Time,BPTT)算法的主要思想是通过类似前馈神经网络的错误反向传播算法来进行计算梯度。

    BPTT算法将循环神经网络看作是一个展开的多层前馈网络,其中“每一层”对应循环网络中的“每个时刻”。在“展开”的前馈网络中,所有层的参数是共享的,因此参数的真实梯度是将所有“展开层”的参数梯度之和

    因为参数U和隐藏层在每个时刻k的净输入\mathbf{z}_{k}=U \mathbf{h}_{k-1}+W \mathbf{x}_{k}+\mathbf{b}有关,因此第t时刻的损失函数\mathcal{L}_{t}关于参数u_{ij}的梯度为:

    \frac{\partial \mathcal{L}_{t}}{\partial u_{i j}}=\sum_{k=1}^{t} \frac{\partial^{+} \mathbf{z}_{k}}{\partial u_{i j}} \frac{\partial \mathcal{L}_{t}}{\partial \mathbf{z}_{k}}

    其中\frac{\partial^{+} \mathbf{z}_{k}}{\partial \boldsymbol{u}_{i j}}表示“直接”偏导数,即公式\mathbf{z}_{k}=U \mathbf{h}_{k-1}+W \mathbf{x}_{k}+\mathbf{b}中保持h_{k−1}不变,对u_{ij}求偏导数,得到:

    \begin{aligned} \frac{\partial^{+} \mathbf{z}_{k}}{\partial u_{i j}} &=\left[0, \cdots,\left[\mathbf{h}_{k-1}\right]_{j}, \cdots, 0\right] \\ & \triangleq \mathbb{I}_{i}\left(\left[\mathbf{h}_{k-1}\right]_{j}\right) \end{aligned}

    其中\left[\mathbf{h}_{k-1}\right]_{j}为第k − 1时刻隐状态的第j维;I_i(x)除了第i个值为x外,其余都为0的行向量。

    定义误差项\delta_{t, k}=\frac{\partial \mathcal{L}_{t}}{\partial \mathbf{z}_{k}}为第t时刻的损失对第k时刻隐藏神经层的净输入z_k的导数,则:

    \begin{aligned} \delta_{t, k} &=\frac{\partial \mathcal{L}_{t}}{\partial \mathbf{z}_{k}} \\ &=\frac{\partial \mathbf{h}_{k}}{\partial \mathbf{z}_{k}} \frac{\partial \mathbf{z}_{k+1}}{\partial \mathbf{h}_{k}} \frac{\partial \mathcal{L}_{t}}{\partial \mathbf{z}_{k+1}} \\ &=\operatorname{diag}\left(f^{\prime}\left(\mathbf{z}_{k}\right)\right) U^{\mathrm{T}} \delta_{t, k+1} \end{aligned}

    从而:

    \frac{\partial \mathcal{L}_{t}}{\partial u_{i j}}=\sum_{k=1}^{t}\left[\delta_{t, k}\right]_{i}\left[\mathbf{h}_{k-1}\right]_{j}

    写成矩阵形式为:

    \frac{\partial \mathcal{L}_{t}}{\partial U}=\sum_{k=1}^{t} \delta_{t, k} \mathbf{h}_{k-1}^{\mathrm{T}}

    由此得到整个序列的损失函数\mathcal{L}关于参数U的梯度:

    \frac{\partial \mathcal{L}}{\partial U}=\sum_{t=1}^{T} \sum_{k=1}^{t} \delta_{t, k} \mathbf{h}_{k-1}^{\mathrm{T}}

    同理可得,\mathcal{L}关于权重W和偏置b的梯度为:

    \begin{aligned} \frac{\partial \mathcal{L}}{\partial W} &=\sum_{t=1}^{T} \sum_{k=1}^{t} \delta_{t, k} \mathbf{x}_{k}^{\mathrm{T}} \\ \frac{\partial \mathcal{L}}{\partial \mathbf{b}} &=\sum_{t=1}^{T} \sum_{k=1}^{t} \delta_{t, k} \\ \end{aligned}

    在BPTT算法中,参数的梯度需要在一个完整的“前向”计算和“反向”计算后才能得到并进行参数更新。如下图所示。

    4.2、实时循环学习算法

    与反向传播的BPTT算法不同的是,实时循环学习(Real-Time Recurrent Learning)是通过前向传播的方式来计算梯度。

    假设循环神经网络中第t + 1时刻的状态h_{t+1}为:

    \mathbf{h}_{t+1}=f\left(\mathbf{z}_{t+1}\right)=f\left(U \mathbf{h}_{t}+W \mathbf{x}_{t+1}+\mathbf{b}\right)

    其关于参数u_{ij}的偏导数为:

    \frac{\partial \mathbf{h}_{t+1}}{\partial u_{i j}}=\left(\frac{\partial^{+} \mathbf{z}_{t+1}}{\partial u_{i j}}+\frac{\partial \mathbf{h}_{t}}{\partial u_{i j}} U^{\mathrm{T}}\right) \frac{\partial \mathbf{h}_{t+1}}{\partial \mathbf{z}_{t+1}}

    RTRL算法从第1 个时刻开始,除了计算循环神经网络的隐状态之外,还依次前向计算偏导数\frac{\partial \mathbf{h}_{1}}{\partial u_{i j}}, \frac{\partial \mathbf{h}_{2}}{\partial u_{i j}}, \frac{\partial \mathbf{h}_{3}}{\partial u_{i j}}, \cdots

    两种学习算法比较:

    RTRL算法和BPTT算法都是基于梯度下降的算法,分别通过前向模式和反向模式应用链式法则来计算梯度。在循环神经网络中,一般网络输出维度远低于输入维度,因此BPTT算法的计算量会更小,但BPTT算法需要保存所有时刻的中间梯度,空间复杂度较高。RTRL算法不需要梯度回传,因此非常适合于需要在线学习或无限序列的任务中

    5、长程依赖问题

    循环神经网络在学习过程中的主要问题是由于梯度消失或爆炸问题,很难建模长时间间隔(Long Range)的状态之间的依赖关系。

    在BPTT算法中,我们有:

    \delta_{t, k}=\prod_{i=k}^{t-1}\left(\operatorname{diag}\left(f^{\prime}\left(\mathbf{z}_{i}\right)\right) U^{\mathrm{T}}\right) \delta_{t, t}

    如果定义\gamma \cong\left\|\operatorname{diag}\left(f^{\prime}\left(\mathbf{z}_{i}\right)\right) U^{\mathrm{T}}\right\|,则:

    \delta_{t, k} \cong \gamma^{t-k} \delta_{t, t}

    γ > 1,当t − k → ∞时,γ^{t−k} → ∞,会造成系统不稳定,称为梯度爆炸问题;相反,若γ < 1,当t−k → ∞时,γ^{t−k} → 0,会出现和深度前馈神经网络类似的梯度消失问题。

    虽然简单循环网络理论上可以建立长时间间隔的状态之间的依赖关系,但是由于梯度爆炸或消失问题,实际上只能学习到短期的依赖关系。这样,如果t时刻的输出y_t依赖于t − k时刻的输入x_{t−k},当间隔k比较大时,简单神经网络很难建模这种长距离的依赖关系,称为长程依赖问题(Long-Term dependencies Problem)

    5.1、梯度爆炸解决方法

    一般而言,循环网络的梯度爆炸问题比较容易解决,一般通过权重衰减或梯度截断来避免。权重衰减是通过给参数增加ℓ1ℓ2范数的正则化项来限制参数的取值范围,从而使得γ ≤ 1。梯度截断是另一种有效的启发式方法,当梯度的模大于一定阈值时,就将它截断成为一个较小的数。

    5.2、梯度消失解决方法

    梯度消失是循环网络的主要问题。除了使用一些优化技巧外,更有效的方式就是改变模型,比如让U = I,同时使用f′(z_i) = 1,即:

    \mathbf{h}_{t}=\mathbf{h}_{t-1}+g\left(\mathbf{x}_{t} ; \theta\right)

    其中g(·)是一个非线性函数,θ为参数。

    上式中,h_th_{t−1}之间为线性依赖关系,且权重系数为1,这样就不存在梯度爆炸或消失问题。但是,这种改变也丢失了神经元在反馈边上的非线性激活的性质,因此也降低了模型的表示能力。

    为了避免这个缺点,我们可以采用一种更加有效的改进策略:

    \mathbf{h}_{t}=\mathbf{h}_{t-1}+g\left(\mathbf{x}_{t}, \mathbf{h}_{t-1} ; \theta\right)

    这样h_th_{t−1}之间为既有线性关系,也有非线性关系,并且可以缓解梯度消失问题。但这种改进依然存在两个问题:

    • 梯度爆炸问题:令\mathbf{z}_{k}=U \mathbf{h}_{k-1}+W \mathbf{x}_{k}+\mathbf{b}为在第k时刻函数g(·)的输入,在计算误差项\delta_{t, k}=\frac{\partial \mathcal{L}_{t}}{\partial \mathbf{z}_{k}},梯度可能会过大,从而导致梯度爆炸问题;

    • 记忆容量(Memory Capacity)问题:随着h_t不断累积存储新的输入信息,会发生饱和现象。假设g(·)为Logistic 函数,则随着时间t的增长,h_t会变得越来越大,从而导致h变得饱和。也就是说,隐状态h_t可以存储的信息是有限的,随着记忆单元存储的内容越来越多,其丢失的信息也越来越多。

    为了解决这两个问题,可以通过引入门控机制来进一步改进模型。

    6、基于门控的循环神经网络

    为了改善循环神经网络的长程依赖问题,一种非常好的解决方案是引入门控机制来控制信息的累积速度,包括有选择地加入新的信息,并有选择地遗忘之前累积的信息。这一类网络可以称为基于门控的循环神经网络(Gated RNN)。本节中,主要介绍两种基于门控的循环神经网络:长短期记忆网络和门控循环单元网络。

    6.1、长短期记忆网络

    长短期记忆(Long Short-Term Memory,LSTM)网络是循环神经网络的一个变体,可以有效地解决简单循环神经网络的梯度爆炸或消失问题。

    \mathbf{h}_{t}=\mathbf{h}_{t-1}+g\left(\mathbf{x}_{t}, \mathbf{h}_{t-1} ; \theta\right)基础上,LSTM网络主要改进在以下两个方面:

    • 新的内部状态:LSTM网络引入一个新的内部状态(internal state)c_t专门进行线性的循环信息传递,同时(非线性)输出信息给隐藏层的外部状态h_t

    \begin{aligned} \mathbf{c}_{t} &=\mathbf{f}_{t} \odot \mathbf{c}_{t-1}+\mathbf{i}_{t} \odot \tilde{\mathbf{c}}_{t} \\ \mathbf{h}_{t} &=\mathbf{o}_{t} \odot \tanh \left(\mathbf{c}_{t}\right) \end{aligned}

    其中f_t,i_to_t三个门(gate)来控制信息传递的路径;⊙为向量元素乘积;c_{t−1}为上一时刻的记忆单元;\tilde{\mathbf{c}}_{t}是通过非线性函数得到的候选状态:

    \tilde{\mathbf{c}}_{t}=\tanh \left(W_{c} \mathbf{x}_{t}+U_{c} \mathbf{h}_{t-1}+\mathbf{b}_{c}\right)

    在每个时刻t,LSTM网络的内部状态c_t记录了到当前时刻为止的历史信息。

    • 门控机制:LSTM网络引入门控机制(Gating Mechanism)来控制信息传递的路径。上面的三个门分别为输入门i_t, 遗忘门f_t和输出门o_t

    在数字电路中,门(Gate)为一个二值变量{0, 1},0代表关闭状态,不许任何信息通过;1代表开放状态,允许所有信息通过。LSTM网络中的“门”是一种“软”门,取值在(0, 1) 之间,表示以一定的比例运行信息通过。LSTM网络中三个门的作用为:

    (1)遗忘门f_t控制上一个时刻的内部状态c_{t−1}需要遗忘多少信息。
    (2)输入门i_t控制当前时刻的候选状态\tilde{c}_t有多少信息需要保存。
    (3)输出门o_t控制当前时刻的内部状态c_t有多少信息需要输出给外部状态h_t

    三个门的计算方式为:

    \begin{aligned} \mathbf{i}_{t} &=\sigma\left(W_{i} \mathbf{x}_{t}+U_{i} \mathbf{h}_{t-1}+\mathbf{b}_{i}\right) \\ \mathbf{f}_{t} &=\sigma\left(W_{f} \mathbf{x}_{t}+U_{f} \mathbf{h}_{t-1}+\mathbf{b}_{f}\right) \\ \mathbf{o}_{t} &=\sigma\left(W_{o} \mathbf{x}_{t}+U_{o} \mathbf{h}_{t-1}+\mathbf{b}_{o}\right) \end{aligned}

    其中σ(·)为Logistic函数,其输出区间为(0, 1)x_t为当前时刻的输入,h_{t−1}为上一时刻的外部状态。

    下图给出了LSTM网络的循环单元结构,其计算过程为:(1)首先利用上一时刻的外部状态h_{t−1}和当前时刻的输入x_t,计算出三个门,以及候选状态\tilde{c}_t;(2)结合遗忘门f_t和输入门i_t来更新记忆单元c_t;(3)结合输出门o_t,将内部状态的信息传递给外部状态h_t

    通过LSTM循环单元,整个网络可以建立较长距离的时序依赖关系。以上计算过程可以简洁表达如下:

    \left[\begin{array}{c}{\tilde{\mathbf{c}}_{t}} \\ {\mathbf{o}_{t}} \\ {\mathbf{i}_{t}} \\ {\mathbf{f}_{t}}\end{array}\right]=\left[\begin{array}{c}{\tanh } \\ {\sigma} \\ {\sigma} \\ {\sigma}\end{array}\right]\left(\mathbf{[}W,U\mathbf{]}\left[\begin{array}{c}{\mathbf{x}_{t}} \\ {\mathbf{h}_{t-1}}\end{array}\right]+\mathbf{b}\right)

    \begin{aligned} \mathbf{c}_{t} &=\mathbf{f}_{t} \odot \mathbf{c}_{t-1}+\mathbf{i}_{t} \odot \tilde{\mathbf{c}}_{t} \\ \mathbf{h}_{t} &=\mathbf{o}_{t} \odot \tanh \left(\mathbf{c}_{t}\right) \end{aligned}

    记忆循环神经网络中的隐状态h存储了历史信息,可以看作是一种记忆(Memory)。在简单循环网络中,隐状态每个时刻都会被重写,因此可以看作是一种短期记忆(Short-Term Memory)。在神经网络中,长期记忆(Long-Term Memory)可以看作是网络参数,隐含了从训练数据中学到的经验,其更新周期要远远慢于短期记忆。而在LSTM网络中,记忆单元c可以在某个时刻捕捉到某个关键信息,并有能力将此关键信息保存一定的时间间隔。记忆单元c中保存信息的生命周期要长于短期记忆h,但又远远短于长期记忆,因此称为长的短期记忆(Long Short-Term Memory)

    注意,一般在深度网络参数学习时,参数初始化的值一般都比较小。但是在训练LSTM网络时,过小值会使得遗忘门的值比较小。这意味着前一时刻的信息大部分都丢失了,这样网络很难捕捉到长距离的依赖信息。并且相邻时间间隔的梯度会非常小,这会导致梯度弥散问题。因此遗忘的参数初始值一般都设得比较大,其偏置向量b_f设为1或2。

    6.2、门控循环单元网络

    门控循环单元(Gated Recurrent Unit,GRU)网络是一种比LSTM网络更加简单的循环神经网络。GRU不引入额外的记忆单元,而是在\mathbf{h}_{t}=\mathbf{h}_{t-1}+g\left(\mathbf{x}_{t}, \mathbf{h}_{t-1} ; \theta\right)的基础上引入一个更新门(Update Gate)来控制当前状态需要从历史状态中保留多少信息(不经过非线性变换),以及需要从候选状态中接受多少新信息。

    \mathbf{h}_{t}=\mathbf{z}_{t} \odot \mathbf{h}_{t-1}+\left(1-\mathbf{z}_{t}\right) \odot g\left(\mathbf{x}_{t}, \mathbf{h}_{t-1} ; \theta\right)

    其中\mathbf{z}_{t} \in[0,1]为更新门。

    \mathbf{z}_{t}=\sigma\left(\mathbf{W}_{z} \mathbf{x}_{t}+\mathbf{U}_{z} \mathbf{h}_{t-1}+\mathbf{b}_{z}\right)

    在LSTM网络中,输入门和遗忘门是互补关系,具有一定的冗余性。GRU网络直接使用一个门来控制输入和遗忘之间的平衡。当z_t = 0时,当前状态h_t和前一时刻的状态h_{t−1}之间为非线性函数关系;当z_t = 1时,h_th_{t−1}之间为线性函数关系。

    在GRU网络中,函数g\left(\mathbf{x}_{t}, \mathbf{h}_{t-1} ; \theta\right)的定义为:

    \tilde{\mathbf{h}}_{t}=\tanh \left(W_{h} \mathbf{x}_{t}+U_{h}\left(\mathbf{r}_{t} \odot \mathbf{h}_{t-1}\right)+\mathbf{b}_{h}\right)

    其中\tilde{\mathbf{h}}_{t}表示当前时刻的候选状态,\mathbf{r}_{t} \in[0,1]为重置门(Reset Gate),用来控制
    候选状态\tilde{\mathbf{h}}_{t}的计算是否依赖上一时刻的状态h_{t−1}

    \mathbf{r}_{t}=\sigma\left(W_{r} \mathbf{x}_{t}+U_{r} \mathbf{h}_{t-1}+\mathbf{b}_{r}\right)

    r_t = 0时,候选状态\tilde{\mathbf{h}}_{t}=\tanh \left(W_{c} \mathbf{x}_{t}+\mathbf{b}\right)只和当前输入x_t相关,和历史状态无关。当\mathbf{r}_{t}=1时,候选状态\tilde{\mathbf{h}}_{t}=\tanh \left(W_{h} \mathbf{x}_{t}+U_{h} \mathbf{h}_{t-1}+\mathbf{b}_{h}\right)和当前输入x_t和历史状态h_{t−1}相关,和简单循环网络一致。

    综上,GRU网络的状态更新方式为:

    \mathbf{h}_{t}=\mathbf{z}_{t} \odot \mathbf{h}_{t-1}+\left(1-\mathbf{z}_{t}\right) \odot \tilde{\mathbf{h}}_{t}

    7、深层循环神经网络

    如果将深度定义为网络中信息传递路径长度的话,循环神经网络可以看作是既深又浅的网络。一方面来说,如果我们把循环网络按时间展开,长时间间隔的状态之间的路径很长,循环网络可以看作是一个非常深的网络了。从另一方面来说,如果同一时刻网络输入到输出之间的路径x_t → y_t,这个网络是非常浅的

    因此,我们可以增加循环神经网络的深度从而增强循环神经网络的能力。增加循环神经网络的深度主要是增加同一时刻网络输入到输出之间的路径x_t → y_t。比如增加隐状态到输出h_t → y_t,以及输入到隐状态x_t → h_t之间的路径的深度。

    7.1、堆叠循环神经网络

    常见的做法是将多个循环网络堆叠起来,称为堆叠循环神经网络(Stacked Recurrent Neural Network,SRNN)。一个堆叠的简单循环网络(stacked SRN)也称为循环网络循环多层感知器(Recurrent Multi-Layer Perceptron,RMLP)。

    下图给出了按时间展开的堆叠循环神经网络。第l层网络的输入是第l − 1层网络的输出。我们定义\mathbf{h}_{t}^{(l)}为在时刻t时第l层的隐状态:

    \mathbf{h}_{t}^{(l)}=f\left(U^{(l)} \mathbf{h}_{t-1}^{(l)}+W^{(l)} \mathbf{h}_{t}^{(l-1)}+\mathbf{b}^{(l)}\right)

    其中U^{(l)}, W^{(l)}b^{(l)}为权重矩阵和偏置向量,\mathbf{h}_{t}^{(0)}=\mathbf{x}_{t}

    7.2、双向循环神经网络

    双向循环神经网络(Bidirectional Recurrent Neural Network,Bi-RNN)由两层循环神经网络组成,它们的输入相同,只是信息传递的方向不同

    假设第1层按时间顺序,第2层按时间逆序,在时刻t时的隐状态定义为\mathbf{h}_{t}^{(1)}\mathbf{h}_{t}^{(2)},则:

    \mathbf{h}_{t}^{(1)}=f\left(U^{(1)} \mathbf{h}_{t-1}^{(1)}+W^{(1)} \mathbf{x}_{t}+\mathbf{b}^{(1)}\right)

    \mathbf{h}_{t}^{(2)}=f\left(U^{(2)} \mathbf{h}_{t+1}^{(2)}+W^{(2)} \mathbf{x}_{t}+\mathbf{b}^{(2)}\right)

    \mathbf{h}_{t}=\mathbf{h}_{t}^{(1)} \oplus \mathbf{h}_{t}^{(2)}

    其中⊕为向量拼接操作。

    下图给出了按时间展开的双向循环神经网络。

    8、拓展到图网络

    如果将循环神经网络按时间展开,每个时刻的隐状态h_t看做一个节点,那么这些节点构成一个链式结构,每个节点t都收到其父节点的消息(Message),更新自己的状态,并传递给其子节点。而链式结构是一种特殊的图结构,我们可以比较容易地将这种消息传递(Message Passing)的思想扩展到任意的图结构上。

    8.1、递归神经网络

    递归神经网络(Recursive Neural Network,RecNN)是循环神经网络在有向无循环图上的扩展。递归神经网络的一般结构为树状的层次结构,如图所示。

    递归神经网络主要用来建模自然语言句子的语义。给定一个句子的语法结构(一般为树状结构),可以使用递归神经网络来按照句法的组合关系来合成一个句子的语义。

    8.2、图网络

    在实际应用中,很多数据是图结构的,比如知识图谱、社交网络、分子网络等。而前馈网络和反馈网络很难处理图结构的数据。

    对于一个任意的图结构G(V, E),其中V表示节点集合,E表示边集合。每条边表示两个节点之间的依赖关系。节点之间的连接可以是有向的,也可以是无向的。图中每个节点v都用一组神经元来表示其状态h^{(v)},初始状态可为节点v的输入特征x^{(v)}。每个节点可收到来自相邻节点的消息,并更新自己的状态。

    \begin{aligned} \mathbf{m}_{t}^{(v)} &=\sum_{u \in N(v)} f\left(\mathbf{h}_{t-1}^{(v)}, \mathbf{h}_{t-1}^{(u)}, \mathbf{e}^{(u, v)}\right) \\ \mathbf{h}_{t}^{(v)} &=g\left(\mathbf{h}_{t-1}^{(v)}, \mathbf{m}_{t}^{(v)}\right) \end{aligned}

    其中N(v)表示节点v的邻居,m^{(v)}_t表示在第t时刻节点v收到的信息,e^{(u,v)}为边e^{(u,v)}上的特征。

    在整个图更新T次后,可以通过一个读出函数(Readout Function)g(·)来得到整个网络的表示。

    \mathbf{y}_{t}=g\left(\left\{\mathbf{h}_{T}^{(v)} | v \in \mathcal{V}\right\}\right)

    相关文章

      网友评论

          本文标题:循环神经网络

          本文链接:https://www.haomeiwen.com/subject/knevrctx.html