时序数据处理需要历史信息。前馈网络无记忆能力。介绍三种方法给网络增加记忆能力。
延时神经网络通过在前馈网络的非输出层中都添加一个延时器,记录神经元的最近几次活性值,增加前馈网络的短期记忆能力。在 t t t 时刻,第 l l l 层神经元的活性值依赖于第 l − 1 l-1 l−1层神经元的最近 K K K 个时刻的活性值:
h t ( l ) = f ( h t ( l − 1 ) , h t − 1 ( l − 1 ) , ⋅ ⋅ ⋅ , h t − K ( l − 1 ) ) \pmb{h}_t^{(l)} = f(\pmb{h}_t^{(l-1)},\pmb{h}_{t-1}^{(l-1)},\cdot\cdot\cdot,\pmb{h}_{t-K}^{(l-1)}) hhht(l)=f(hhht(l−1),hhht−1(l−1),⋅⋅⋅,hhht−K(l−1))
其中 h t ( l ) ∈ R M l \pmb{h}_t^{(l)} \in \mathbb{R}^{ \pmb{M}_l } hhht(l)∈RMMMl 表示第 l l l 层神经元在时刻 t t t 的活性值, M l M_l Ml 为第 l l l 层神经元的数量。前馈神经网络的活性值:
a ( l ) = f l ( W ( l ) a ( l − 1 ) + b ( l ) ) \pmb{a}^{(l)} = f_l(\pmb{W}^{(l)}\pmb{a}^{(l-1)} + \pmb{b}^{(l)}) aaa(l)=fl(WWW(l)aaa(l−1)+bbb(l))
自回归模型 (AutoRegressive Model,AR)统计学上的时间序列模型,用一个变量 y t \pmb{y}_t yyyt 的历史信息来预测自己:
y t = w 0 + ∑ k = 1 K w k y t − k + ϵ t \pmb{y}_t = w_0 + \sum_{k=1}^K w_k \pmb{y}_{t-k} + \epsilon_t yyyt=w0+k=1∑Kwkyyyt−k+ϵt
其中 K K K 为超参数, w 0 , ⋅ ⋅ ⋅ , w K w_0, \cdot\cdot\cdot, w_K w0,⋅⋅⋅,wK 为可学习参数, ϵ t \epsilon_t ϵt ~ N ( 0 , σ 2 ) N(0, \sigma^2) N(0,σ2) 为第 t t t 个时刻的噪声,方差 σ 2 \sigma^2 σ2 与时间无关。
有外部输入的自回归模型 (Nonlinear AutoRegressive with Exogenous Inputs Model,NARX),在每个时刻 t t t 都有一个外部输入 x t \pmb{x}_t xxxt, 产生一个输出 y t \pmb{y}_t yyyt, NARX 通过一个延时器记录最近 K x K_x Kx次的外部输入和最近 K y K_y Ky次的输出,第 t t t 个时刻的输出 y t \pmb{y}_t yyyt为:
y t = f ( x t , x t − 1 , ⋅ ⋅ ⋅ , x t − K x , y t − 1 , y t − 2 , ⋅ ⋅ ⋅ , y t − K y ) \pmb{y}_t = f(\pmb{x}_t,\pmb{x}_{t-1},\cdot\cdot\cdot,\pmb{x}_{t-K_x}, \pmb{y}_{t-1},\pmb{y}_{t-2},\cdot\cdot\cdot,\pmb{y}_{t-K_y}) yyyt=f(xxxt,xxxt−1,⋅⋅⋅,xxxt−Kx,yyyt−1,yyyt−2,⋅⋅⋅,yyyt−Ky)
其中 f ( ⋅ ) f(\cdot) f(⋅) 表示非线性函数,可以前馈网络, K x K_x Kx 和 K y K_y Ky 为超参数。
循环神经网络 (Recurrent Neural Network,RNN)通过使用带自反馈的神经元处理任意长度的时序数据。
给定输入序列 x 1 : T = ( x 1 , x 2 , . . . , x t , . . . , x T ) \pmb{x}_{1:T} = (\pmb{x_1}, \pmb{x_2}, ... ,\pmb{x_t}, ..., \pmb{x_T}) xxx1:T=(x1x1x1,x2x2x2,...,xtxtxt,...,xTxTxT),RNN 这样更新带反馈边的隐藏层的活性值 h t \pmb{h}_t hhht:
h t = f ( h t − 1 , x t ) \pmb{h}_t = f(\pmb{h}_{t-1}, \pmb{x}_t) hhht=f(hhht−1,xxxt)
其中 h 0 = 0 \pmb{h}_0 = 0 hhh0=0, f ( ⋅ ) f(\cdot) f(⋅) 为非线性函数。可谓前馈网络。从数学上来说,该公式可看成动力系统,故隐藏层活性值 h t \pmb{h}_t hhht 又被成为状态(State)或隐状态(Hidden State)。
简单循环网络(SRN)只有一个隐藏层。在一个两层的前馈神经网络中,连接存在相邻的层与层之间,隐藏层的节点之间无连接。简单循环网络增加了隐藏层到隐藏层的反馈连接。
假设向量 x t ∈ R M \pmb{x}_t \in \mathbb{R}^M xxxt∈RM 表示在时刻 t t t时网络的输入, h t ∈ D M \pmb{h}_t \in \mathbb{D}^M hhht∈DM 表示隐藏层状态(隐藏层神经元活性值), h t \pmb{h}_t hhht和当前时刻输入 x t \pmb{x}_t xxxt、上一时刻隐藏层状态 h t − 1 \pmb{h}_{t-1} hhht−1相关。 SRN在t时刻更新公式为:
其中 z t \pmb{z}_t zzzt 为隐藏层的净输入, U ∈ R D × D \pmb{U} \in \mathbb{R}^{D \times D} UUU∈RD×D 是状态-状态权重矩阵, W ∈ R D × D \pmb{W} \in \mathbb{R}^{D \times D} WWW∈RD×D 是状态-输入权重矩阵, b ∈ R D \pmb{b} \in \mathbb{R}^{D} bbb∈RD 是偏移向量, 其中 f ( ⋅ ) f(\cdot) f(⋅) 表示非线性函数,常为Logistic函数或Tanh函数。
若把每个时刻的状态都看做前馈神经网络的一层,循环神经网络可看做在时间维度上权值共享的神经网络。按时间展开的循环神经网络:
前馈神经网络可以模拟任何连续函数,而循环神经网络可以模拟任何程序。定义一个完全连接的循环神经网络。 x t \pmb{x}_t xxxt 为输入, y t \pmb{y}_t yyyt 为输出, h t \pmb{h}_t hhht 为隐状态, f ( ⋅ ) f(\cdot) f(⋅)为非线性激活函数, U \pmb{U} UUU 、 W \pmb{W} WWW 、 b \pmb{b} bbb 、 V \pmb{V} VVV为网络参数:
循环神经网络的拟合能力也十分强大。一个完全连接的循环网络是任何非线性动力系统的近似器。可用通用近似定理解释:
图灵完备(Turing Completeness)是指一种数据操作规则,比如一种编程语言,可以实现图灵机(Turing Machine)的所有功能,解决所有的可计算问题。
故一个完全连接的循环神经网络可以近似解决所有的可计算问题。
循环神经网络可以应用到三种模式的机器学习任务::序列到类别模式、同步的序列到序列模式、异步的序列到序列模式。
序列到类别模式主要用于序列数据的分类问题。比如文本分类任务,输入为单词序列,输出为该文本类别。
假设输入序列 x 1 : T = ( x 1 , x 2 , . . . , x t , . . . , x T ) \pmb{x}_{1:T} = (\pmb{x_1}, \pmb{x_2}, ... ,\pmb{x_t}, ..., \pmb{x_T}) xxx1:T=(x1x1x1,x2x2x2,...,xtxtxt,...,xTxTxT),输出为一个类别 y ∈ y \in y∈ {1, … , C}。可将样本 x \pmb{x} xxx 按不同时刻输入到循环神经网络中,得到不同时刻的隐藏状态: h 1 \pmb{h}_1 hhh1, . . . ... ..., h T \pmb{h}_T hhhT。可将 h T \pmb{h}_T hhhT看做整个序列的最终表示或特征,输入分类器 g ( ⋅ ) g(\cdot) g(⋅):
y ^ = g ( h T ) \hat{y} = g(\pmb{h}_T) y^=g(hhhT)
也可以将整个序列的所有状态进行平均,做为整个序列的表示:
y ^ = g ( 1 T ∑ t = 1 T h t ) \hat{y} = g(\frac{1}{T}\sum_{t=1}^{T}\pmb{h}_t) y^=g(T1t=1∑Thhht)
同步的序列到序列模式主要用于序列标注(Sequence Labeling)任务,即每一时刻都有输入输出,输入输出序列长度相同。比如在词性标注(Part-of-Speech Tagging)中,每一个单词需要标注其词性标签。
假设输入序列 x 1 : T = ( x 1 , x 2 , . . . , x t , . . . , x T ) \pmb{x}_{1:T} = (\pmb{x_1}, \pmb{x_2}, ... ,\pmb{x_t}, ..., \pmb{x_T}) xxx1:T=(x1x1x1,x2x2x2,...,xtxtxt,...,xTxTxT),输出序列为一个类别 y 1 : T = ( y 1 , . . . , y T ) y_{1:T} = (y_1, ... , y_T) y1:T=(y1,...,yT)。样本 x \pmb{x} xxx 按不同时刻输入到循环神经网络中,得到不同时刻的隐含态 h 1 \pmb{h}_1 hhh1, …, h T \pmb{h}_T hhhT 。每个时刻的隐含态 h t \pmb{h}_t hhht 代表了当前时刻和历史的信息,作为输入:
y ^ t = g ( h t ) , ∀ t ∈ [ 1 , T ] \hat{y}_t = g(\pmb{h}_t), \forall t \in [1, T] y^t=g(hhht),∀t∈[1,T]
异步的序列到序列模式 又称编码器-解码器(Encoder-Decoder)模型,即输入序列和输出序列不需具有严格的对应关系,也不需相同长度。比如机器翻译任务中,输入为源语言单词序列,输出为目标语言单词序列。
假设输入为 x 1 : T = ( x 1 , x 2 , . . . , x T ) \pmb{x}_{1:T} = (\pmb{x_1}, \pmb{x_2}, ..., \pmb{x_T}) xxx1:T=(x1x1x1,x2x2x2,...,xTxTxT),输出为 y 1 : M = ( y 1 , y 2 , . . . , x M ) \pmb{y}_{1:M} = (\pmb{y_1}, \pmb{y_2}, ... ,\pmb{x_M}) yyy1:M=(y1y1y1,y2y2y2,...,xMxMxM) 异步的序列到序列模式 一般通过先编码后解码的方式来实现。先将样本 x x x 按不同时刻输入到一个RNN(编码器)中,得到其编码 h T \pmb{h}_T hhhT 。然后再使用另外一个RNN(解码器),得到输出序列 y ^ 1 : M \hat{y}_{1:M} y^1:M ,为建立输出序列之间的依赖关系,在解码器中通常使用非线性的自回归模型:
其中 f 1 ( ⋅ ) f_1(\cdot) f1(⋅) 和 f 2 ( ⋅ ) f_2(\cdot) f2(⋅) 分别作为编码器和解码器, g ( ⋅ ) g(\cdot) g(⋅) 为分类器, y ^ t \hat{\pmb{y}}_t yyy^t 为预测输出 y ^ t \hat{y}_t y^t 的向量表示。
异步的序列到序列模式示例如下图,其中⟨⟩ 表示输入序列的结束,虚线表示将上一个时刻的输出作为下一个时刻的输入:
可用梯度下降学习RNN中的参数。以随机梯度下降为例。给定样本 ( x , y ) (\pmb{x}, \pmb{y}) (xxx,yyy) ,其中输入为 x 1 : T = ( x 1 , x 2 , . . . , x T ) \pmb{x}_{1:T} = (\pmb{x_1}, \pmb{x_2}, ..., \pmb{x_T}) xxx1:T=(x1x1x1,x2x2x2,...,xTxTxT),输出为 y 1 : T = ( y 1 , y 2 , . . . , x T ) \pmb{y}_{1:T} = (\pmb{y_1}, \pmb{y_2}, ... ,\pmb{x_T}) yyy1:T=(y1y1y1,y2y2y2,...,xTxTxT) 每个时刻t,都有一个监督信息 y t y_t yt ,定义时刻 t 的损失函数为:
L t = L ( y t , g ( h t ) ) L_t = L(y_t, g(\pmb{h}_t)) Lt=L(yt,g(hhht))
其中 g ( h t ) g(\pmb{h}_t) g(hhht) 为 t 时刻的输出,L为可微分的损失函数,如交叉熵。整个序列的损失函数为:
L t = ∑ t = 1 T L t L_t = \sum_{t=1}^{T}{L_t} Lt=t=1∑TLt
整个序列的损失函数 L 为关于参数 U 的梯度为每个时刻损失 L_t 对参数U的偏导数之和:
∂ L ∂ U = ∑ t = 1 T ∂ L t ∂ U \frac{\partial{L}}{\partial{\pmb{U}}} = \sum_{t=1}^{T}\frac{\partial{L}_t}{\partial{\pmb{U}}} ∂UUU∂L=t=1∑T∂UUU∂Lt
RNN中存在提个递归调用的 f ( ⋅ ) f(\cdot) f(⋅) ,因此计算参数梯度的方式不同于计算前馈网络,主要有两种::随时间反向传播(BPTT)算法和实时循环学习(RTRL)算法.
随时间反向传播算法类似前馈网络的错误反向传播算法。
BPTT 算法将RNN看做展开的多层前馈网络,其中的“每一层”对应RNN中的“每个时刻”:
这样,RNN就可按照前馈网络中的反向传播算法计算参数梯度。在展开的前馈网络中,所有层参数共享,参数的真实梯度是所有“展开层”的参数梯度之和。
计算偏导数 ∂ L ∂ U \frac{\partial{L}}{\partial{\pmb{U}}} ∂UUU∂L 先计算时刻 t 的损失对参数U的偏导 ∂ L ∂ U \frac{\partial{L}}{\partial{\pmb{U}}} ∂UUU∂L。
参数 U 和隐藏层净输入 z k = U h k − 1 + W x k + b \pmb{z}_k = \pmb{Uh}_{k-1} + \pmb{Wx_k} + b zzzk=UhUhUhk−1+WxkWxkWxk+b 有关,故 t 时刻的损失 L t L_t Lt 关于参数 u i j u_{ij} uij 的梯度为:
其中 ∂ + z k ∂ u i j \frac{\partial^{+}z_k}{\partial{\pmb{u}_{ij}}} ∂uuuij∂+zk 表示直接偏导数 即 z k = U h k − 1 + W x k + b \pmb{z}_k = \pmb{Uh}_{k-1} + \pmb{Wx}_k + b zzzk=UhUhUhk−1+WxWxWxk+b 中保持 h k − 1 \pmb{h}_{k-1} hhhk−1 不变,对 u i j u_{ij} uij 进行求偏导,得到:
其中 [ h k − 1 ] j [\pmb{h}_{k-1}]_j [hhhk−1]j 为第 k-1 时刻隐状态的第 j 维; I i ( x ) \mathbb{I}_i(x) Ii(x) 为除了第 i 行为 x 外,其余部分为 0 的行向量。
定义误差项为第 t 时刻的损失对第 k 时刻隐藏神经层的净输入 z k \pmb{z}_k zzzk 的导数,则当 1 ≤ k ≤ t 1 \leq k \leq t 1≤k≤t时:
由以上可得到:
其矩阵形式:
参数梯度 得到整个序列的损失函数 L 关于参数 U、权重W、偏置b 的梯度:
计算复杂度 在BPTT 算法中,参数的梯度需要在一个完整的“前向”计算和“反向”计算后才能得到并进行参数更新。
与反向传播的BPTT不同,实时循环学习(Real-Time Recurrent earning,RTRL)是通过前向传播的方式来计算梯度。
假设RNN的第 t + 1 t+1 t+1时刻的状态 h t + 1 \pmb{h}_{t+1} hhht+1 为:
其中关于参数 u i j u_{ij} uij 的偏导数为:
RTRL算法从第1个时刻开始,计算RNN的隐状态,同时一次向前计算偏导数 ∂ h 1 ∂ u i j \frac{\partial h_1}{\partial{\pmb{u}_{ij}}} ∂uuuij∂h1, ∂ h 2 ∂ u i j \frac{\partial h_2}{\partial{\pmb{u}_{ij}}} ∂uuuij∂h2, ∂ h 3 ∂ u i j \frac{\partial h_3}{\partial{\pmb{u}_{ij}}} ∂uuuij∂h3,…这样第 t 时刻,可以实时计算损失 L_t 关于参数 U 的梯度,并更新参数。参数 W W W 和 b b b的梯度同理。
RTRL和BPTT算法比较 两者都是基于梯度下降算法,分别通过前向模式和后向模式利用链式法则计算梯度。RNN中,一般网络输出维数原低于输入维度,因此BPTT算法计算量更小,但要保存所有时刻的中间梯度,空间复杂度高。RTRL不需要梯度回传,适合在线学习和无限序列任务。
RNN在学习过程中主要的问题是梯度消失或梯度爆炸。很难建模长时间间隔的状态之间的依赖关系。
将BPTT中的误差项展开:
得到:
再定义:
得到:
若 γ > 1 \gamma > 1 γ>1, 当 t − k → ∞ t-k \rightarrow \infty t−k→∞ 时, γ t − k → ∞ \gamma^{t-k} \rightarrow \infty γt−k→∞。当间隔 t − k t - k t−k 比较大时,梯度也变得很大,会造成系统不稳定,即梯度爆炸问题。
若 γ < 1 \gamma < 1 γ<1, 当 t − k → ∞ t-k \rightarrow \infty t−k→∞ 时, γ t − k → 0 \gamma^{t-k} \rightarrow 0 γt−k→0。当间隔 t − k t - k t−k 比较大时,梯度也变得很小,会出现和深层前馈网络类似的梯度爆炸问题。
注意:
RNN常使用Logistic或Tanh函数作为非线性激活函数,其导数值都小于1,权重矩阵 ∣ ∣ U ∣ ∣ ||\pmb{U}|| ∣∣UUU∣∣ 不会太大,故若时间间隔 t − k t - k t−k 过大, δ t , k \delta_{t,k} δt,k 会趋于0,故出现梯度消失问题。
RNN理论上可以建立长时间间隔的状态之间的依赖关系,但由于梯度爆炸或消失问题,实际上只能学到短期的依赖关系。这样,如时刻 t 的输出 y t y_t yt 依赖于时刻 k 的输入 x k \pmb{x}_k xxxk,当间隔 t − k t-k t−k 较大时,简单RNN难建模长距离依赖关系,成为长程依赖问题。
为避免梯度爆炸或梯度消失,一种直接方式:选取合适参数,使用非饱和激活函数,尽量使 d i a g ( f ′ ( z ) ) U T ≈ 1 diag(f^{'}(\pmb{z})) \pmb{U}^T \approx1 diag(f′(zzz))UUUT≈1。这种方式依赖于人工调参经验,限制模型的广泛应用。一种有效方式:通过改进模型或优化方法。
梯度爆炸 RNN的梯度爆炸更易解决,常通过权重衰减或梯度截断。
权重衰减通过给参数增加 l 1 l1 l1或 l 2 l2 l2 范数的正则化,来限制参数取值范围,从而使 γ ≤ 1 \gamma \leq 1 γ≤1 。梯度截断是另一种有效的启发式方法,梯度的模大于阈值时,将其截断为及较小的数。
梯度消失 RNN的主要问题。解决方式:一是用优化技巧;二是改变模型(更有效),如让 U = I \pmb{U} = \pmb{I} UUU=III ,同时令 ∂ h t ∂ h t − 1 = I \frac{\partial \pmb{h}_t}{\partial \pmb{h}_{t-1}} = \pmb{I} ∂hhht−1∂hhht=III 为单位矩阵,即:
h t = h t − 1 + g ( x t ; θ ) \pmb{h}_t = \pmb{h}_{t-1} + g(\pmb{x}_t; \theta) hhht=hhht−1+g(xxxt;θ)
其中 h t h_t ht 和 h t − 1 h_{t-1} ht−1 之间为线性依赖关系,权重系数为1,不存在梯度爆炸或消失问题,但是,丢失了神经元在反馈边上的非线性激活的性质,故降低了模型的表示能力。更有效的改进策略:
h t = h t − 1 + g ( x t , h t − 1 ; θ ) \pmb{h}_t = \pmb{h}_{t-1} + g(\pmb{x}_t, \pmb{h}_{t-1}; \theta) hhht=hhht−1+g(xxxt,hhht−1;θ)
这样 h t h_t ht 和 h t − 1 h_{t-1} ht−1 既有线性关系,也有非线性关系,并可缓解梯度消失问题。仍存在问题:
为改善RNN的长程依赖问题,在公式:
h t = h t − 1 + g ( x t , h t − 1 ; θ ) \pmb{h}_t = \pmb{h}_{t-1} + g(\pmb{x}_t, \pmb{h}_{t-1}; \theta) hhht=hhht−1+g(xxxt,hhht−1;θ)
上引入门控机制来控制信息积累速度,包括有选择地加入新的信息,并有选择地遗忘之前累积的信息。这类网络叫做 基于门控的循环神经网络 (Gated RNN)。
长短期记忆网络(Long Short-Term Memory Network,LSTM)是RNN的一变体,可有效解决RNN的梯度爆炸或梯度消失问题。在以下公式上,进行两方面的改进:
h t = h t − 1 + g ( x t , h t − 1 ; θ ) \pmb{h}_t = \pmb{h}_{t-1} + g(\pmb{x}_t, \pmb{h}_{t-1}; \theta) hhht=hhht−1+g(xxxt,hhht−1;θ)
新的内部状态 LSTM引入新的内部状态(internal state) c t ∈ R D \pmb{c}_t \in \mathbb{R}^D ccct∈RD 专门进行线性的循环信息传递,同时非线性地输出信息给隐藏层的外部状态 h t ∈ R D \pmb{h}_t \in \mathbb{R}^D hhht∈RD。内部状态 c t \pmb{c}_t ccct 这样计算:
其中 f t ∈ [ 0 , 1 ] D \pmb{f}_t \in [0,1]^D ffft∈[0,1]D、 i t ∈ [ 0 , 1 ] D \pmb{i}_t \in [0,1]^D iiit∈[0,1]D、 o t ∈ [ 0 , 1 ] D \pmb{o}_t \in [0,1]^D ooot∈[0,1]D为三个门(gate)来控制信息传递的路径; ⨀ \bigodot ⨀ 为向量元素乘积; c t − 1 \pmb{c}_{t-1} ccct−1为上一个时刻的记忆单元; c ^ t ∈ R D \hat{\pmb{c}}_t \in \mathbb{R}^D ccc^t∈RD 是通过非线性函数得到的候选状态:
在每个时刻 t ,LSTM 网络的内部状态 c t \pmb{c}_t ccct 记录了到当前时刻为止的历史信息。
门控机制 数字电路中,门为二值变量 {0,1},0代表关闭,不需信息通过。LSTM引入门控机制(Gating Mechanism),控制信息传递的路径。公式:
中有三个门: f t ∈ [ 0 , 1 ] D \pmb{f}_t \in [0,1]^D ffft∈[0,1]D为遗忘门、 i t ∈ [ 0 , 1 ] D \pmb{i}_t \in [0,1]^D iiit∈[0,1]D为输入门、 o t ∈ [ 0 , 1 ] D \pmb{o}_t \in [0,1]^D ooot∈[0,1]D 为输出门。三个门的作用:
当 f t = 0 , i t = 1 \pmb{f}_t = 0,\pmb{i}_t = 1 ffft=0,iiit=1 时,记忆单元将历史信息清空,将候选状态写入,但此时记忆单元 c t \pmb{c}_t ccct 依然和上一时刻的历史信息相关。
当 f t = 1 , i t = 0 \pmb{f}_t = 1,\pmb{i}_t = 0 ffft=1,iiit=0 时,记忆单元将复制上一时刻的内容,不写入新的信息。
LSTM的“门”是“软门”,取值在 (0,1) 之间,并以一定的比例通过信息,三种门的计算如下,其中 σ ( ⋅ ) \sigma(\cdot) σ(⋅) 为 Logistic函数,其输出区间为 (0,1), x t \pmb{x}_t xxxt 为当前时刻的输入, h t − 1 \pmb{h}_{t-1} hhht−1 为上一时刻的外部状态:
通过LSTM循环单元,整个网络可以建立较长距离的时序依赖关系。给出以上LSTM循环单元公式的简洁描述:
其中 x t ∈ R M \pmb{x}_t \in \mathbb{R}^M xxxt∈RM 为当前时刻的输入, W ∈ R 4 D × ( D + M ) \pmb{W} \in \mathbb{R}^{4D \times (D+M)} WWW∈R4D×(D+M)、 b ∈ R 4 D \pmb{b} \in \mathbb{R}^{4D} bbb∈R4D 是网络参数。
记忆 循环神经网络的隐状态 h h h 存储了历史信息,可以看做是一种 记忆。
在简单RNN中,隐状态 h h h 每个时刻都会被重写,看做短期记忆(Short-Term Memory)。
在神经网络中,长期记忆(Long-Term Memory)可看做是网络参数,隐含从训练数据中学到的经验,更新周期远慢于短期记忆。
而在LSTM中,记忆单元 c c c 可以在某个时刻捕捉到某个关键信息,并有能力将此关键信息保存一定的时间。记忆单元 c c c 中保存信息的生命周期要长于短期记忆 h h h ,短于长期记忆,因此称为长短期记忆(Long Short-Term Memory)。
主流的LSTM用三个门动态控制内部状态,遗忘历史信息、输出信息、输入信息的数量。对门控机制修改,得到LSTM变体。
无遗忘门的LSTM 最早的LSTM是没有遗忘门的,内部状态的更新为:
记忆单元 c c c 会不断增大。输入序列很长时,记忆单元容量饱和,大大降低LSTM的性能。
peephole 连接 三种门不但依赖于输入 x t \pmb{x}_t xxxt 和上一个时刻的隐状态 h t − 1 \pmb{h}_{t-1} hhht−1,也依赖于上一个时刻的记忆单元 c t − 1 \pmb{c}_{t-1} ccct−1:
其中 V i 、 V f 、 V o \pmb{V}_i、\pmb{V}_f、\pmb{V}_o VVVi、VVVf、VVVo 为对角矩阵。
耦合输入门和遗忘门 LSTM的输入门和输出门有些互补关系,同时使用两个门较冗余,为减少LSTM的计算复杂度,将输入门输出门合并,令 f t = 1 − i t \pmb{f}_t = 1 - \pmb{i}_t ffft=1−iiit ,内部状态更新方式:
门控循环单元(Gated Recurrent Unit,GRU)网络比LSTM更简单。
GRU网络引入门控机制控制信息更新方式,不同LSTM,GRU不引入额外的记忆单元,在公式:
h t = h t − 1 + g ( x t , h t − 1 ; θ ) \pmb{h}_t = \pmb{h}_{t-1} + g(\pmb{x}_t, \pmb{h}_{t-1}; \theta) hhht=hhht−1+g(xxxt,hhht−1;θ)
上,引入一个更新门控制当前状态需从历史状态中保留多少信息,需从候选状态中接受多少新信息:
h t = z t ⨀ h t − 1 + ( 1 − z t ) ⨀ g ( x t , h t − 1 ; θ ) z t = σ ( W z x t + U z h t − 1 + b z ) \pmb{h}_t = \pmb{z}_t \bigodot \pmb{h}_{t-1} + (1-\pmb{z}_t) \bigodot g(\pmb{x}_t, \pmb{h}_{t-1}; \theta) \\ \pmb{z}_t = \sigma(\pmb{W}_z \pmb{x}_t + \pmb{U}_z \pmb{h}_{t-1} + \pmb{b}_z) hhht=zzzt⨀hhht−1+(1−zzzt)⨀g(xxxt,hhht−1;θ)zzzt=σ(WWWzxxxt+UUUzhhht−1+bbbz)
其中 z t ∈ [ 0 , 1 ] D \pmb{z}_t \in [0,1]^D zzzt∈[0,1]D 为更新门。在LSTM中,输入输出互补,具有冗余性,GRU用更新门平衡输入和遗忘之间的平衡:
在GRU中,函数 g ( x t , h t − 1 ; θ ) g(\pmb{x}_t, \pmb{h}_{t-1}; \theta) g(xxxt,hhht−1;θ)的定义为:
其中 h ^ t \pmb{\hat{h}_t} h^th^th^t 表示当前时刻的候选状态, r t ∈ [ 0 , 1 ] D \pmb{r}_t \in [0,1]^D rrrt∈[0,1]D 为重置门:
用来控制候选状态 h ^ t \pmb{\hat{h}_t} h^th^th^t 的计算是否依赖上一个时刻的状态 h t − 1 \pmb{h}_{t-1} hhht−1 :
综上,GRU网络的状态更新方式为:
h t = z t ⨀ h t − 1 + ( 1 − z t ) ⨀ h ^ t \pmb{h}_t = \pmb{z}_t \bigodot \pmb{h}_{t-1} + (1-\pmb{z}_t) \bigodot \pmb{\hat{h}}_t hhht=zzzt⨀hhht−1+(1−zzzt)⨀h^h^h^t
如果将深度定义为网络中中信息传递路径长度的话,RNN可以看作是既“深”又“浅”的网络。因为,把RNN按时间展开,长时间间隔的状态之间的路径很长,RNN可以看作是一个非常深的网络;而果同一时刻网络输入到输出之间的路径 x t → y t \pmb{x}_t → \pmb{y}_t xxxt→yyyt,这个RNN网络是非常浅的。
故,可增加RNN的深度来增强RNN的能力,即增加同一时刻网络输入到输出的路径 x t → y t \pmb{x}_t → \pmb{y}_t xxxt→yyyt,比如增加隐状态到输出的路径 h t → y t \pmb{h}_t → \pmb{y}_t hhht→yyyt,以及输入 x t → h t \pmb{x}_t → \pmb{h}_t xxxt→hhht到隐状态的路径深度。
常见的简单做法,将多个RNN堆叠起来,称为堆叠循环神经网络(Stacked Recurrent Neural Network,SRNN)。一个堆叠的简单循环网络(Stacked SRN) 也称为循环多层感知器(Recurrent Multi-Layer Perceptron,RMLP)。按时间展开的SRNN如下:
第 l l l 层网络的输入是 l − 1 l-1 l−1 层网络的输出。定义, h t ( l ) \pmb{h}_t^{(l)} hhht(l) 为在时刻 t t t 时第 l l l 层的隐状态:
其中 U ( l ) \pmb{U}^{(l)} UUU(l)、 W ( l ) \pmb{W}^{(l)} WWW(l)、 b ( l ) \pmb{b}^{(l)} bbb(l) 为权重矩阵和偏置向量, h t ( 0 ) = x t \pmb{h}_t^{(0)} = \pmb{x}_t hhht(0)=xxxt。
特定任务中,一个时刻的输出不但和过去时刻的信息有关,也和后续时刻的信息有关。比如给定句子,其中一个词的词性由它的上下文决定。因此,在这些任务中,可以增加一个按时间的逆序来传递信息的网络层,以增强网络的能力。
双向循环神经网络(Bidirectional Recurrent Neural Network,Bi-RNN)由两层循环神经网络组成,他们的输入相同,只是信息传递的方向不同。
假设第1 层按时间顺序,第2 层按时间逆序,在时刻 t t t时的隐状态定义为 h t ( 1 ) \pmb{h}_t^{(1)} hhht(1) 和 h t ( 2 ) \pmb{h}_t^{(2)} hhht(2) ,则:
其中 ⨁ \bigoplus ⨁ 为向量拼接操作。
如果将RNN按时间展开,每个时刻的隐状态 h t \pmb{h}_t hhht看作一个节点,那么这些节点构成一个链式结构,每个节点 t t t都收到其父节点的消息(Message),更新自己的状态,并传递给其子节点。而链式结构是一种特殊的图结构,我们可以比较容易地将这种消息传递(Message Passing)的思想扩展到任意的图结构上。
递归神经网络(Recursive Neural Network,RecNN)是RNN在有向无循环图上的拓展,常为树桩层次结构:
三个隐藏层 h 1 \pmb{h}_1 hhh1、 h 2 \pmb{h}_2 hhh2、 h 3 \pmb{h}_3 hhh3,其中 h 1 \pmb{h}_1 hhh1由两个输入层 x 1 \pmb{x}_1 xxx1、 x 2 \pmb{x}_2 xxx2计算得到。
对一个节点 h i \pmb{h}_i hhhi,他可以接受来自父节点集合 π i \pi_i πi 中所有节点的消息,并更新自己的状态:
h i = f ( h π i ) \pmb{h}_i = f(\pmb{h}_{\pi_i}) hhhi=f(hhhπi)
其中 h π i \pmb{h}_{\pi_i} hhhπi表示集合 π i \pi_i πi中所有节点状态的拼接, f f f 是一个和节点位置无关的非线性函数,可以为一个单层的前馈神经网络。递归神经网络一般结构可以写成:
当递归神经网络的结构退化为线性序列结构(图b),递归神经网络等价于简单RNN。
递归神经网络主要用来建模自然语言句子的语义。
同样,可用门控机制来改进递归神经网络中的长距离依赖问题,比如树结构的长短期记忆模型(Tree-Structured LSTM),就是将LSTM模型的思想应用到树结构的网络中,来实现更灵活的组合函数。
实际中很多数据是图结构的,比如知识图谱、社交网络、分子网络等。而前馈网络和反馈网络很难处理图结构的数据。图神经网络(Graph Neural Network,GNN)是将消息传递的思想扩展到图结构数据上的神经网络,可用来处理图数据。
对一个任意的图结构 G ( V , ϵ ) G(V,\epsilon) G(V,ϵ) 。图中每个节点 v 都用一组神经元来表示状态 h ( v ) \pmb{h}^{(v)} hhh(v),初始状态可以为节点 v 的输入特征 x ( v ) \pmb{x}^{(v)} xxx(v)。每个节点可收到来自相邻节点的消息,并更新自己的状态:
其中 N ( v ) N(v) N(v) 表示节点 v 的邻居, m t ( v ) \pmb{m}_t^{(v)} mmmt(v)表示在第 t 时刻节点 v 收到的信息, e ( u , v ) \pmb{e}^{(u,v)} eee(u,v) 为边 e ( u , v ) e^{(u,v)} e(u,v)上的特征。
该公式是同步的更新方式,所有结构同时接受信息并更新自己的状态。对有向图,异步更新更有效,如RNN或递归神经网络。整个图更新后T此后,可通过一个读出函数 g g g 来得到整个网络的表示: