前言
处理时间序列数据 (语音识别,语言模型,自然语言生成…)
前馈神经网络(卷积神经网络):
- 信息单向传递 在一定程度上也减弱了神经网络模型的能力
- 时序数据的长度一般是不固定的,而前馈神经网络要求输入和输出的维数都是固定的,不能任意改变
循环神经网络具有短期记忆能力
的神经网络.在循环神经网络中,神经元不但可以接受其他神经元的信息,也可以接受自身的信息,形成具有环路的网络结构.
循环神经网络已经被广泛应用在语音识别
、语言模型
以及自然语言生成
等任务上
循环神经网络的参数学习可以通过随时间反向传播算法
来学习.
随时间反向传播算法
即按照时间的逆序将错误信息一步步地往前传递.当输入序列比较长时,会存在梯度爆炸和消失问题,也称为长程依赖问题.
为了解决这个问题,人们对循环神经网络进行了很多的改进,其中最有效的改进方式引入门控机制
.
短期记忆能力实现
- 添加延时器
- 自反馈神经元
延时神经网络(Time Delay Neural Network,TDNN)
建立一个额外的延时单元,用来存储网络的历史信息(可以包括输入、输出、隐状态等)
延时神经网络是在前馈网络中的 非输出层都添加一个延时器 ,记录神经元的最近几次活性值.在第
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
)
)
h_t^{(l)}=f\big(h_t^{(l-1)},h_{t-1}^{(l-1)},...,h_{t-K}^{(l-1)}\big)
ht(l)=f(ht(l−1),ht−1(l−1),...,ht−K(l−1))
其中
h
t
(
l
)
∈
R
M
l
h_t^{(l)}\in R^{M_l}
ht(l)∈RMl 表示第
l
l
l 层神经元时刻
t
t
t 的活性值,
M
l
M_l
Ml 为第
l
l
l 层的神经元数量。
有外部输入的非线性自回归模型
自回归模型(AutoRegressive Model,AR)
是统计学上常用的一类时间序列模型,用一个变量
y
t
y_t
yt 的历史信息来预测自己.
y
t
=
w
0
+
∑
k
=
1
K
w
k
y
t
−
k
+
ϵ
t
y_t=w_0+\sum_{k=1}^{K}{w_ky_{t-k}+\epsilon_t}
yt=w0+k=1∑Kwkyt−k+ϵt
其中K 为超参数,
w
0
,
.
.
.
,
w
K
w_0,...,w_K
w0,...,wK 为可学习参数,
ϵ
t
∼
N
(
0
,
σ
2
)
\epsilon_t \sim N(0,\sigma^2)
ϵt∼N(0,σ2) 为第𝑡 个时刻的噪声,方差
σ
2
\sigma^2
σ2 和时间无关.
有外部输入的非线性自回归模型(Nonlinear AutoRegressive with Exogenous Inputs Model,NARX)
在每个时刻
t
t
t 都有一个外部输入
x
t
x_t
xt ,产生一个输出
y
t
y_t
yt.
NARX
通过一个 延时器 记录最近
K
x
K_x
Kx 次的外部输入和最近
K
y
K_y
Ky 次的输出 ,第
t
t
t 个时刻的输出
y
t
y_t
yt 为
y
t
=
f
(
x
t
,
x
t
−
1
,
.
.
.
,
x
t
−
K
x
,
y
t
−
1
,
y
t
−
2
,
.
.
.
,
y
t
−
K
y
)
y_t=f\big(x_t,x_{t-1},...,x_{t-K_x},y_{t-1},y_{t-2},...,y_{t-K_y}\big)
yt=f(xt,xt−1,...,xt−Kx,yt−1,yt−2,...,yt−Ky)
其中
f
(
.
)
f(.)
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
)
x_{1:T}=(x_1,x_2,...,x_t,...,x_T)
x1:T=(x1,x2,...,xt,...,xT) ,循环神经网络通过下面公式更新带反馈边
的隐藏层的活性值
h
t
:
h_t:
ht:
h t = f ( h t − 1 , x t ) , h_t=f(h_{t-1},x_t), ht=f(ht−1,xt),
其中
h
0
=
0
h_0=0
h0=0 ,
f
(
.
)
f(.)
f(.) 为一个非线性函数,可以是一个前馈网络.
隐藏层循环:隐藏层数据会根据上一时刻该层数据进行循环。
前馈神经网络可以模拟任何连续函数,而循环神经网络可以模拟任何程序.
简单循环网络
简单循环网络(Simple Recurrent Network,SRN)是一个非常简单的循环神经网络,只有一个隐藏层的神经网络.
在一个两层的前馈神经网络中,连接存在相邻的层与层之间, 隐藏层的节点之间是无连接的. 而简单循环网络
增加了 从隐藏层到隐藏层的反馈连接.
令向量
x
t
∈
R
M
x_t \in R^M
xt∈RM 表示在时刻
t
t
t 时网络的输入,
h
t
∈
R
D
h_t \in R^D
ht∈RD 表示隐藏层状态(即隐藏层神经元活性值),则
h
t
h_t
ht 不仅和当前时刻的输入
x
t
x_t
xt 相关,也和上一个时刻的隐藏层状态
h
t
−
1
h_{t-1}
ht−1 相关.简单循环网络在时刻t 的更新公式为
净
输
入
:
z
t
=
U
h
t
−
1
+
W
x
t
+
b
t
时
刻
状
态
:
h
t
=
f
(
z
t
)
净输入:z_t=Uh_{t-1}+Wx_t+b\\ t时刻状态:h_t=f(z_t)
净输入:zt=Uht−1+Wxt+bt时刻状态:ht=f(zt)
U
∈
R
D
∗
D
U \in R^{D*D}
U∈RD∗D 为 状态-状态权重矩阵,
W
∈
R
D
∗
M
W\in R^{D*M}
W∈RD∗M 为状态-输入权重矩阵,
b
∈
R
D
b \in R^D
b∈RD 为偏置向量,
f
(
.
)
f(.)
f(.) 通常取sigmoid型函数。
如果我们把每个时刻的状态都看作前馈神经网络的一层,循环神经网络可以看作在时间维度上权值共享的神经网络。
循环神经网络的计算能力
定义:完全连接的循环神经网络,输入 x t x_t xt , 输出 y t y_t yt ,
h t = f ( U h t − 1 + W x t + b ) y t = V h t h_t=f(Uh_{t-1}+Wx_t+b)\\y_t=Vh_t ht=f(Uht−1+Wxt+b)yt=Vht
其中 h h h 为隐状态, f ( . ) f(.) f(.) 为非线性激活函数, U , W , b , V U,W,b,V U,W,b,V 为RNN的参数。
循环神经网络的通用近似定理
如果一个完全连接的循环神经网络有足够数量的 sigmoid 型隐藏神经元,它可以 以任意的准确率去近似任何一个非线性动力系统1
非
线
性
动
力
系
统
:
s
t
=
g
(
s
t
−
1
,
x
t
)
y
t
=
o
(
s
t
)
\begin{aligned} 非线性动力系统:&\\ s_t&=g(s_{t-1},x_t)\\ y_t&=o(s_t) \end{aligned}
非线性动力系统:styt=g(st−1,xt)=o(st)
其中
s
t
s_t
st 为每个时刻的隐状态,
x
t
x_t
xt 是外部输入,
g
(
.
)
g(.)
g(.) 是可测的状态转换函数
,
o
(
.
)
o(.)
o(.) 是连续输出函数,并且对状态空间的紧致性没有限制.
证明:首先根据通用近似原理2:两层的前馈神经网络可以近似任意有界闭集上的任意连续函数.因此,动力系统的两个函数可以用两层的全连接前馈网络近似.
证明思路:非线性动态系统的两个函数可以分别用两层前馈神经网络表示
首先,非线性动力系统的状态转换函数 s t = g ( s t − 1 , x t ) s_t=g(s_{t-1},x_t) st=g(st−1,xt) 可以由一个两层的神经网络 s t = C f ( A s t − 1 + B x t + b ) s_t=Cf(As_{t-1}+Bx_t+b) st=Cf(Ast−1+Bxt+b) 来近似,可以分解为
s t ∗ = f ( A s t − 1 + B x t + b ) = f ( A C s t − 1 ∗ + B x t + b ) , s t = C s t ∗ \begin{aligned} s_t^*&=f(As_{t-1}+Bx_t+b)\\ &=f(ACs_{t-1}^*+Bx_t+b),\\ s_t&=Cs_t^* \end{aligned} st∗st=f(Ast−1+Bxt+b)=f(ACst−1∗+Bxt+b),=Cst∗
其中𝑨, 𝑩, 𝑪 为权重矩阵,𝒃为偏置向量.
非线性动力系统的输出函数 y t = o ( s t ) = o ( g ( s t − 1 , x t ) ) y_t=o(s_t)=o(g(s_{t-1},x_t)) yt=o(st)=o(g(st−1,xt)) 也可以用一个两层的前馈神经网络近似.
y
t
∗
=
f
(
A
∗
s
t
−
1
+
B
∗
x
t
+
b
∗
)
=
f
(
A
∗
C
s
t
−
1
∗
+
B
∗
x
t
+
b
∗
)
,
y
t
=
D
y
t
∗
\begin{aligned} y_t^*&=f(A^*s_{t-1}+B^*x_t+b^*)\\ &=f(A^*Cs^*_{t-1}+B^*x_t+b^*),\\ y_t&=Dy_t^* \end{aligned}
yt∗yt=f(A∗st−1+B∗xt+b∗)=f(A∗Cst−1∗+B∗xt+b∗),=Dyt∗
其中
A
∗
,
B
∗
,
D
A^*,B^*,D
A∗,B∗,D 为权重矩阵,
b
∗
b^*
b∗ 为偏置向量.
即
[ s t ∗ y t ∗ ] = f ( [ A C 0 A ∗ C 0 ] [ s t − 1 ∗ y t − 1 ∗ ] + [ B B ∗ ] x t + [ b b ∗ ] ) y t = [ 0 D ] [ s t ∗ y t ∗ ] \begin{bmatrix} s_t^* \\y_t^* \end{bmatrix}=f\bigg( \begin{bmatrix} AC & 0 \\ A^*C & 0\end{bmatrix} \begin{bmatrix} s_{t-1}^* \\y_{t-1}^*\end{bmatrix} + \begin{bmatrix} B\\B^* \end{bmatrix}x_t+\begin{bmatrix} b\\b^* \end{bmatrix}\bigg) \\ y_t=\begin{bmatrix} 0& D \end{bmatrix}\begin{bmatrix} s_t^*\\y_t^* \end{bmatrix} [st∗yt∗]=f([ACA∗C00][st−1∗yt−1∗]+[BB∗]xt+[bb∗])yt=[0D][st∗yt∗]
令 h t = [ s t ∗ ; y t ∗ ] h_t=\begin{bmatrix}s_t^*;y_t^*\end{bmatrix} ht=[st∗;yt∗] 则非线性动力系统可以由下面的全连接循环神经网络来近似.
h t = f ( U h t − 1 + W x t + b ) y t = V h t , 其 中 : U = [ A C 0 A ∗ C 0 ] , W = [ B B ∗ ] , b = [ b b ∗ ] , V = [ 0 D ] \begin{aligned} h_t&=f(Uh_{t-1}+Wx_t+b)\\ y_t&=Vh_t,\\ 其中: &U=\begin{bmatrix} AC & 0 \\ A^*C & 0\end{bmatrix}, W=\begin{bmatrix}B\\B^*\end{bmatrix},b=\begin{bmatrix}b\\b^*\end{bmatrix},V=\begin{bmatrix}0 & D\end{bmatrix} \end{aligned} htyt其中:=f(Uht−1+Wxt+b)=Vht,U=[ACA∗C00],W=[BB∗],b=[bb∗],V=[0D]
应用到机器学习
循环神经网络可以应用到很多不同类型的机器学习任务.
根据这些任务的特点可以分为以下几种模式:序列到类别模式、同步的序列到序列模式、异步的序列到序列模式.
RNN – 文本处理
类比:编译原理
文本分类问题: 给定文档p(可能含有标题t),将文档分类为n个类别中的一个或多个。
文本分类应用: 常见的有垃圾邮件识别,情感分析
文本分类方向: 主要有二分类,多分类,多标签分类
文本分类方法: 传统机器学习方法(贝叶斯,svm等),深度学习方法(fastText,TextCNN等)
序列到类别模式
输入为序列,输出为类别.
比如在 文 本 分 类 \textcolor{red}{文本分类} 文本分类 中,输入数据为单词的序列,输出为该文本的类别.
假设一个样本 x 1 : T = ( x 1 , . . . , x T ) x_{1:T}=(x_1,...,x_T) x1:T=(x1,...,xT) 为一个长度为 T T T 的序列,输出为一个类别 y ∈ { 1 , . . . , C } y \in \{1,...,C\} y∈{1,...,C} .我们可以将样本 x x x 按不同时刻输入到循环神经网络中,并得到不同时刻的隐藏状态 h 1 , . . , h T h_1,..,h_T h1,..,hT .我们可以将 h T h_T hT 看作整个序列的最终表示(或特征),并输入给分类器 g ( . ) g(.) g(.) 进行分类. y ^ = g ( h T ) \hat y=g(h_T) y^=g(hT) 其中 g ( . ) g(.) g(.) 可以是简单的线性分类器(比如Logistic回归)或复杂的分类器.
RNN一般取法:隐藏状态: h t = f ( h t − 1 , x t ) h_{t}=f(h_{t-1},x_t) ht=f(ht−1,xt) 预测: y ^ = g ( h T ) \hat y=g(h_T) y^=g(hT)
除了将最后时刻的状态作为整个序列的表示之外,我们还可以对整个序列的所有状态进行平均,并用这个平均状态来作为整个序列的表示 y ^ = g ( 1 T ∑ t = 1 T h t ) \hat y=g(\frac 1 T\sum_{t=1}^{T}{h_t}) y^=g(T1t=1∑Tht)
此时 取隐藏状态的平均状态: h ˉ = 1 T ∑ t = 1 T h t \bar{h}=\frac 1 T\sum_{t=1}^{T}{h_t} hˉ=T1∑t=1Tht
前项所占比例增加 --> 文本数据具体处理时 – 捕捉文本的上下文信息(考虑语序信息)
同步的序列到序列模式
同步的序列到序列模式主要用于 序列标注(Sequence Labeling)
任务,即每一时刻都有输入和输出,输入序列和输出序列的长度相同.
在 词 性 标 注 \textcolor{red}{词性标注} 词性标注(Part-of-Speech Tagging)中,每一个单词都需要标注其对应的词性标签.
在同步的序列到序列模式中,输入为一个长度为 T T T 的序列 x 1 : T = ( x 1 , . . . , x T ) x_{1:T}=(x_1,...,x_T) x1:T=(x1,...,xT) ,输出为序列 y 1 : T = ( y 1 , . . . , y T ) y_{1:T}=(y_1,...,y_T) y1:T=(y1,...,yT) .样本 x x x 按不同时刻输入到循环神经网络中,并得到不同时刻的隐状态 h 1 , . . . , h T h_1,...,h_T h1,...,hT .
每个时刻隐状态 h t h_t ht 代表了当前时刻和历史的信息,并输入给分类器 g ( . ) g(.) g(.) 得到当前时刻的标签 y ^ t \hat y_t y^t,即
h t = f ( h t − 1 , x t ) y ^ t = g ( h t ) h_t=f(h_{t-1},x_t) \quad \hat y_t=g(h_t) ht=f(ht−1,xt)y^t=g(ht)
当前词的词性与之前词存在关联
异步的序列到序列模式
异步的序列到序列模式也称为编码器-解码器(Encoder-Decoder)模型,即
输入序列和输出序列不需要有严格的对应关系,也不需要保持相同的长度
在 机 器 翻 译 \textcolor{red}{机器翻译} 机器翻译中,输入为源语言的单词序列,输出为目标语言的单词序列.
在异步的序列到序列模式中,输入为长度为 T T T 的序列 x 1 : T = ( x 1 , . . . , x T ) x_{1:T}=(x_1,...,x_T) x1:T=(x1,...,xT) ,输出为长度为 M M M 的序列 y 1 : M = ( y 1 , . . . , y M ) y_{1:M}=(y_1,...,y_M) y1:M=(y1,...,yM) .
异步的序列到序列模式一般通过先编码后解码的方式来实现.
先将样本 x x x 按不同时刻输入到 一个循环神经网络(编码器) 中,并得到其编码 h T h_T hT.然后再使用 另一个循环神经网络(解码器) ,得到输出序列 y ^ 1 : M \hat y_{1:M} y^1:M.为了建立输出序列之间的依赖关系,在解码器中通常使用非线性的自回归模型.
令 f 1 ( . ) f_1(.) f1(.) 和 f 2 ( . ) f_2(.) f2(.) 分别为用作编码器和解码器的循环神经网络,则编码器-解码器模型可以写为
h t = f 1 ( h t − 1 , x t ) ∀ t ∈ ( 1 , T ) h T + t = f 2 ( h T + t − 1 , y ^ t − 1 ) ∀ t ∈ ( 1 , M ) y ^ t = g ( h T + t ) ∀ t ∈ ( 1 , M ) \begin{aligned} h_t &= f_1(h_{t-1},x_t) && \forall t \in (1,T)\\ h_{T+t}&=f_2(h_{T+t-1},\hat y_{t-1}) && \forall t \in (1,M)\\ \hat y_t&=g(h_{T+t}) && \forall t \in (1,M) \end{aligned} hthT+ty^t=f1(ht−1,xt)=f2(hT+t−1,y^t−1)=g(hT+t)∀t∈(1,T)∀t∈(1,M)∀t∈(1,M)
其中 g ( . ) g(.) g(.) 为分类器, y ^ t \hat y_t y^t 为预测输出 y ^ t \hat y_t y^t 的向量表示.在解码器通常采用自回归模型,每个时刻的输入为上一时刻的预测结果 y ^ t − 1 \hat y_{t-1} y^t−1.
其中⟨𝐸𝑂𝑆⟩表示输入序列的结束,虚线表示将上一个时刻的输出作为下一个时刻的输入.
参数学习
给定一个训练样本
(
x
,
y
)
(x,y)
(x,y) ,其中
x
1
:
T
=
(
x
1
,
.
.
.
,
x
T
)
x_{1:T}=(x_1,...,x_T)
x1:T=(x1,...,xT) 为长度是
T
T
T 的输入序列,
t
1
:
T
=
(
y
1
,
.
.
.
,
y
T
)
t_{1:T}=(y_1,...,y_T)
t1:T=(y1,...,yT) 是长度为𝑇 的标签序列.
h
t
=
f
(
U
h
t
−
1
+
W
x
t
+
b
)
y
t
=
V
h
(
t
)
=
g
(
h
t
)
h_t=f(Uh_{t-1}+Wx_t+b)\\y_t=Vh(t)=g(h_t)
ht=f(Uht−1+Wxt+b)yt=Vh(t)=g(ht)
即在每个时刻
t
t
t ,都有一个监督信息
y
t
y_t
yt ,我们定义时刻𝑡 的损失函数为
L
t
=
L
(
y
t
,
g
(
h
t
)
)
L_t=L(y_t,g(h_t))
Lt=L(yt,g(ht))
其中 g ( h t ) g(h_t) g(ht) 为第 t t t 时刻的输出, L L L 为可微分的损失函数.
那么整个序列的损失函数为 L = ∑ t = 1 T L t L=\sum_{t=1}^{T}{L_t} L=t=1∑TLt
整个序列的损失函数 L L L 关于参数 U U U 的梯度为 ∂ L ∂ U = ∑ t = 1 T ∂ L t ∂ U \frac {\partial L}{\partial U}=\sum_{t=1}^{T}{\frac {\partial L_t}{\partial U}} ∂U∂L=t=1∑T∂U∂Lt 即每个时刻损失 L t L_t Lt 对参数 U U U 的偏导数之和.
- 随时间反向传播(BPTT)算法
- 实时循环学习(RTRL)算法
随时间反向传播算法(BPTT)
链式求导法则
计算偏导数 ∂ L t ∂ U \frac {\partial L_t}{\partial U} ∂U∂Lt
因为参数 U U U 和隐藏层在每个时刻 k ( 1 ≤ k ≤ t ) k(1\le k \le t) k(1≤k≤t) 的净输入 z k = U h k − 1 + W x k + b z_k=Uh_{k-1} +Wx_k+b zk=Uhk−1+Wxk+b 有关,因此第 t t t 时刻的损失函数 L t L_t Lt 关于参数 U 的梯度为:
∂ L t ∂ U = ? ? ? ∂ L t ∂ u i j = ∑ k = 1 t ∂ z k ′ ∂ u i j ∂ L t ∂ z k \begin{aligned} \frac {\partial L_t}{\partial U} &=???\\ \frac {\partial L_t}{\partial u_{ij}} &= \sum_{k=1}^{t}{\frac {\partial {z'_k}}{\partial u_{ij}} \frac{\partial L_t}{\partial z_k}} \end{aligned} ∂U∂Lt∂uij∂Lt=???=k=1∑t∂uij∂zk′∂zk∂Lt
其中
∂
z
k
′
∂
u
i
j
\frac {\partial {z'_k}}{\partial u_{ij}}
∂uij∂zk′ 表示当前
k
k
k 时刻的直接偏导数.
∂
z
k
′
∂
u
i
j
=
[
0
,
.
.
.
,
[
h
k
−
1
]
j
,
.
.
.
,
0
]
=
I
i
(
[
h
k
−
1
]
j
)
\frac {\partial {z'_k}}{\partial u_{ij}}=[0,...,[h_{k-1}]_j,...,0]=I_i([h_{k-1}]_j)
∂uij∂zk′=[0,...,[hk−1]j,...,0]=Ii([hk−1]j) 其中
[
h
k
−
1
]
j
[h_{k-1}]_j
[hk−1]j 为第
k
−
1
k-1
k−1 时刻隐状态的第
j
j
j 维;
I
i
(
x
)
I_i(x)
Ii(x)
除了第
i
i
i 行值为x外,其余都为0的行向量. 矩阵的偏导
定义误差项
δ
t
,
k
=
∂
L
t
∂
z
k
\delta_{t,k}=\frac {\partial L_t}{\partial z_k}
δt,k=∂zk∂Lt 为第
t
t
t 时刻的损失对第
k
k
k 时刻隐藏神经网络层的净输入
z
k
z_k
zk 的导数,则当
1
≤
k
≤
t
1\le k \le t
1≤k≤t 时
δ
t
,
k
=
∂
L
t
∂
z
k
=
∂
h
k
∂
z
k
∂
z
k
+
1
∂
h
k
∂
L
t
∂
z
k
+
1
=
d
i
a
g
(
f
′
(
z
k
)
)
U
T
δ
t
,
k
+
1
\begin{aligned} \delta_{t,k} &= \frac {\partial L_t}{\partial z_k} \\ &= \frac{\partial h_k}{\partial z_k} \frac{\partial z_{k+1}}{\partial h_k} \frac {\partial L_t}{\partial z_{k+1}}\\ &=\textcolor{red}{diag(f'(z_k))}U^T\delta_{t,k+1} \end{aligned}
δt,k=∂zk∂Lt=∂zk∂hk∂hk∂zk+1∂zk+1∂Lt=diag(f′(zk))UTδt,k+1
故而
∂
L
t
∂
u
i
j
=
∑
k
=
1
t
∂
z
k
′
∂
u
i
j
∂
L
t
∂
z
k
=
∑
k
=
1
t
[
δ
t
,
k
]
i
[
h
k
−
1
]
j
\begin{aligned} \frac {\partial L_t}{\partial u_{ij}} &= \sum_{k=1}^{t}{\frac {\partial {z'_k}}{\partial u_{ij}} \frac{\partial L_t}{\partial z_k}}\\ &= \sum_{k=1}^{t}{ [\delta_{t,k}]_i [h_{k-1}]_j} \end{aligned}
∂uij∂Lt=k=1∑t∂uij∂zk′∂zk∂Lt=k=1∑t[δt,k]i[hk−1]j
参数梯度:整个序列的损失函数 L L L 关于参数 U U U 的梯度
∂ L ∂ U = ∑ t = 1 T ∑ k = 1 t δ t , k h k − 1 T \frac {\partial L}{\partial U}=\sum_{t=1}^{T}{\sum_{k=1}^{t}{\delta_{t,k}h_{k-1}^T}} ∂U∂L=t=1∑Tk=1∑tδt,khk−1T
实时循环学习(RTRL)
实时循环学习(Real-Time Recurrent Learning,RTRL)是通过 前向传播的方式来计算梯度
两种算法比较 RTRL算法和BPTT算法都是基于梯度下降的算法,分别通过前向模式和反向模式应用链式法则来计算梯度.
在循环神经网络中,一般网络输出维度远低于输入维度
BPTT 算法的计算量会更小,但是 BPTT 算法 需要保存所有时刻的中间梯度,空间复杂度较高.
RTRL算法 不需要梯度回传,因此非常适合用于需要在线学习或无限序列的任务中.
长程依赖问题
由于 梯度消失或爆炸问题
,很难建模长时间间隔(Long Range)的状态之间的依赖关系
在BPTT算法中 – 第𝑡时刻的损失对第𝑘时刻隐藏神经层的净输入
z
k
z_k
zk
的导数 – 误差项
δ
t
,
k
1
≤
k
≤
t
\delta_{t,k} \quad 1\le k \le t
δt,k1≤k≤t
δ t , k = d i a g ( f ′ ( z k ) ) U T δ t , k + 1 \delta_{t,k} =diag(f'(z_k))U^T\delta_{t,k+1} δt,k=diag(f′(zk))UTδt,k+1
向 后 展 开 : δ t , k + 1 , δ t , k + 2 , . . . . , δ t , t − 1 , δ t , t \textcolor{red}{向后展开:\delta_{t,k+1} ,\delta_{t,k+2} , ....,\delta_{t,t-1},\delta_{t,t} } 向后展开:δt,k+1,δt,k+2,....,δt,t−1,δt,t
δ t , k = ∏ τ = k t − 1 ( d i a g ( f ′ ( z τ ) ) U T ) δ t , t \delta_{t,k}=\prod_{\tau=k}^{t-1}{\big(diag(f'(z_{\tau}))U^T\big)}\delta_{t,t} δt,k=τ=k∏t−1(diag(f′(zτ))UT)δt,t
定义
γ
≈
∥
d
i
a
g
(
f
′
(
z
τ
)
)
U
T
∥
\gamma \approx \Vert diag(f'(z_{\tau}))U^T\Vert
γ≈∥diag(f′(zτ))UT∥ 则
δ
t
,
k
≈
γ
t
−
k
δ
t
,
t
\delta_{t,k}\approx \gamma^{t-k}\delta_{t,t}
δt,k≈γt−kδt,t
时间序列数据t很大时, 1. 若
γ
>
1
\gamma>1
γ>1 梯度变得很大,会造成系统不稳定,称为梯度爆炸问题(Gradient Exploding Problem).
2. 若
γ
<
1
\gamma<1
γ<1 梯度变得非常小,会出现和深层前馈神经网络类似的梯度消失问题(Vanishing Gradient Problem).
改进方案
为了避免梯度爆炸或消失问题,一种最直接的方式就是选取合适的参数,同时使用非饱和的激活函数,尽量使得 d i a g ( f ′ ( z ) ) U T ≈ 1 diag(f'(z))U^T\approx 1 diag(f′(z))UT≈1 ,这种方式需要足够的人工调参经验,限制了模型的广泛应用.
比较有效的方式是通过改进模型或优化方法来缓解循环网络的梯度爆炸和梯度消失问题.
梯度爆炸:权重衰减、梯度截断
梯度消失:改变模型
令
U
=
I
,
∂
h
t
∂
h
t
−
1
=
I
即
:
h
t
=
h
t
−
1
+
g
(
x
t
;
θ
)
令U=I,\frac{\partial h_t} {\partial h_{t-1}}=I\\ 即:h_t=h_{t-1}+g(x_t;\theta)
令U=I,∂ht−1∂ht=I即:ht=ht−1+g(xt;θ)
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 ; θ ) \textcolor{blue}{\huge h_t=h_{t-1}+g(x_t,h_{t-1};\theta)} ht=ht−1+g(xt,ht−1;θ)
h t h_t ht 和 h t − 1 h_{t-1} ht−1 之间为既有线性关系,也有非线性关系,并且可以缓解梯度消失问题.但这种改进依然存在两个问题:
- 梯度爆炸问题
对于 h t = h t − 1 + g ( x t , h t − 1 ; θ ) h_t=h_{t-1}+ \textcolor{red}{g(x_t,h_{t-1};\theta)} ht=ht−1+g(xt,ht−1;θ) ,令 g ( x t , h t − 1 ; θ ) = g ( z k ) z k = U h k − 1 + W x k + b g(x_t,h_{t-1};\theta)=g(z_k)\\z_k=Uh_{k-1}+Wx_k+b g(xt,ht−1;θ)=g(zk)zk=Uhk−1+Wxk+b 那么在计算 δ t , k \delta_{t,k} δt,k 时仍会出现梯度爆炸 - 记忆容量问题
随着 h t h_t ht 不断累积存储新的输入信息,会发生饱和现象.假设 𝑔(⋅) 为 Logistic 函数,则随着时间 𝑡 的增长, h t h_t ht 会变得越来越大,从而导致𝒉变得饱和.
也就是说,隐状态 h t h_t ht 可以存储的信息是有限的,随着记忆单元存储的内容越来越多,其丢失的信息也越来越多.
引入门控机制
基于门控的循环神经网络
增加系数来控制信息的来源比例 ≈ \approx ≈ 遗忘速度or 记忆能力
门控机制: 控制信息的累积速度,包括有选择地加入新的信息,并有选择地遗忘之前累积的信息。
长短期记忆网络(Long Short-Term Memory Network,LSTM)
- 新的内部状态
c t ∈ R D c_t \in R^D ct∈RD专门进行线性的循环信息传递,同时(非线性地)输出信息给隐藏层的外部状态 h t ∈ R D h_t \in R^D ht∈RD .内部状态 c t c_t ct 通过下面公式计算:
c t = f t ⊙ c t − 1 + i t ⊙ c t ~ h t = o t ⊙ t a n h ( c t ) c_t=f_t \odot c_{t-1}+i_t\odot \tilde{c_t}\\ h_t=o_t\odot tanh(c_t) ct=ft⊙ct−1+it⊙ct~ht=ot⊙tanh(ct)
其中 f t ∈ [ 0 , 1 ] D , i t ∈ [ 0 , 1 ] D , o t ∈ [ 0 , 1 ] D f_t\in [0,1]^D , i_t \in [0,1]^D , o_t \in [0,1]^D ft∈[0,1]D,it∈[0,1]D,ot∈[0,1]D 为三个门(gate)来控制信息传递的路径; ⊙ \odot ⊙ 为向量元素乘积; c t − 1 c_{t-1} ct−1 为上一时刻的记忆单元; c t ~ ∈ R D \tilde{c_t} \in R^D ct~∈RD 是通过非线性函数得到的候选状态:
c t ~ = t a n h ( W c x t + U c h t − 1 + b c ) \tilde{c_t}=tanh(W_cx_t+U_ch_{t-1}+b_c) ct~=tanh(Wcxt+Ucht−1+bc)
在每个时刻𝑡,LSTM网络的内部状态 c t c_t ct 记录了到当前时刻为止的历史信息. - 门控机制
LSTM 网络引入门控机制(Gating Mechanism)来控制信息传递的路径.
以上公式中三个“门”分别为输入门 i t i_t it 、遗忘门 f t f_t ft 和输出门 o t o_t ot.这三个门的作用(系数okay)为- 遗忘门 f t f_t ft 控制上一个时刻的内部状态 c t − 1 c_{t-1} ct−1 需要遗忘多少信息.
- 输入门 i t i_t it 控制当前时刻的候选状态 c t ~ \tilde{c_t} ct~ 有多少信息需要保存.
- 输出门 o t o_t ot 控制当前时刻的内部状态 c t c_t ct 有多少信息需要输出给外部状态 h t h_t ht.
具体实现以及后续的参数学习
LSTM网络中的“门”是一种“软”门,取值在 (0, 1)之间,表示以一定的比例允许信息通过.
三个门的计算方式为:
i
t
=
σ
(
W
i
x
t
+
U
i
h
t
−
1
+
b
i
)
f
t
=
σ
(
W
f
x
t
+
U
f
h
t
−
1
+
b
f
)
o
t
=
σ
(
W
o
x
t
+
U
o
h
t
−
1
+
b
o
)
i_t=\sigma(W_ix_t+U_ih_{t-1}+b_i)\\ f_t=\sigma(W_fx_t+U_fh_{t-1}+b_f)\\ o_t=\sigma(W_ox_t+U_oh_{t-1}+b_o)
it=σ(Wixt+Uiht−1+bi)ft=σ(Wfxt+Ufht−1+bf)ot=σ(Woxt+Uoht−1+bo)
其中 𝜎(⋅)为Logistic函数,其输出区间为 (0, 1). 参数学习:
W
∗
,
U
∗
,
b
∗
W_*,U_*,b_*
W∗,U∗,b∗
待学习参数:
- 状态: W c , U c , b c W_c,U_c,b_c Wc,Uc,bc
- 门: W i , W f , W o W_i,W_f,W_o Wi,Wf,Wo , U i , U f , U o U_i,U_f,U_o Ui,Uf,Uo, b i , b f , b o b_i,b_f,b_o bi,bf,bo
关系:
候选状态:
c
t
~
=
f
(
x
t
,
h
t
−
1
)
\tilde{c_t}=f(x_t,h_{t-1})
ct~=f(xt,ht−1)
内部状态:
c
t
=
g
a
t
e
(
c
t
−
1
,
c
t
~
)
c_t=gate(c_{t-1},\tilde{c_t})
ct=gate(ct−1,ct~)
隐藏状态:
h
t
=
g
a
t
e
(
c
t
)
h_t=gate(c_t)
ht=gate(ct)
f:非线性函数(sigmoid) tanh函数 ; gate:含门控的函数
通过 LSTM 循环单元,整个网络可以建立较长距离的时序依赖关系
[
c
t
~
o
t
i
t
f
t
]
=
[
t
a
n
h
σ
σ
σ
]
(
W
[
x
t
h
t
−
1
]
+
b
)
c
t
=
f
t
⊙
c
t
−
1
+
i
t
⊙
c
t
~
h
t
=
o
t
⊙
t
a
n
h
(
c
t
)
\begin{bmatrix} \tilde{c_t}\\o_t\\i_t\\f_t \end{bmatrix}= \begin{bmatrix} tanh\\ \sigma \\ \sigma \\ \sigma \end{bmatrix} \bigg(W \begin{bmatrix} x_t \\ h_{t-1} \end{bmatrix}+b \bigg)\\ c_t=f_t\odot c_{t-1}+i_t\odot \tilde{c_t}\\ h_t=o_t \odot tanh(c_t)
⎣⎢⎢⎡ct~otitft⎦⎥⎥⎤=⎣⎢⎢⎡tanhσσσ⎦⎥⎥⎤(W[xtht−1]+b)ct=ft⊙ct−1+it⊙ct~ht=ot⊙tanh(ct)
其中
x
t
∈
R
M
,
参
数
:
W
∈
R
4
D
×
(
D
+
M
)
,
b
∈
R
4
D
x_t \in R^M,\textcolor{red}{参数:W\in R^{4D\times (D+M)}, b\in R^{4D}}
xt∈RM,参数:W∈R4D×(D+M),b∈R4D
长短期记忆:记忆保存的时间取决于门控
一般在深度网络参数学习时,参数初始化的值一般都比较小.
但是在训练 LSTM 网络时,过小的值会使得遗忘门的值比较小.
这意味着前一时刻的信息大部分都丢失了,这样网络很难捕捉到长距离的依赖信息.
并且相邻时间间隔的梯度会非常小,这会导致梯度弥散问题.
因此遗忘的参数初始值一般都设得比较大,其偏置向量
b
f
b_f
bf 设为1或2.
参数学习:W,U,b
LSTM网络的各种变体
LSTM:
c
t
=
f
t
⊙
c
t
−
1
+
i
t
⊙
c
t
~
h
t
=
o
t
⊙
t
a
n
h
(
c
t
)
g
a
t
e
:
i
t
=
σ
(
W
i
x
t
+
U
i
h
t
−
1
+
b
i
)
f
t
=
σ
(
W
f
x
t
+
U
f
h
t
−
1
+
b
f
)
o
t
=
σ
(
W
o
x
t
+
U
o
h
t
−
1
+
b
o
)
c_t=f_t \odot c_{t-1}+i_t\odot \tilde{c_t}\\ h_t=o_t\odot tanh(c_t)\\ gate:\\ i_t=\sigma(W_ix_t+U_ih_{t-1}+b_i)\\ f_t=\sigma(W_fx_t+U_fh_{t-1}+b_f)\\ o_t=\sigma(W_ox_t+U_oh_{t-1}+b_o)
ct=ft⊙ct−1+it⊙ct~ht=ot⊙tanh(ct)gate:it=σ(Wixt+Uiht−1+bi)ft=σ(Wfxt+Ufht−1+bf)ot=σ(Woxt+Uoht−1+bo)
- 无遗忘门的LSTM:
f
t
=
1
;
对
上
一
信
息
进
行
保
存
f_t=1;对上一信息进行保存
ft=1;对上一信息进行保存
c t = c t − 1 + i t ⊙ c t ~ c_t=c_{t-1}+i_t\odot \tilde{c_t} ct=ct−1+it⊙ct~
记忆单元 𝒄 会不断增大.当输入序列的长度非常大时,记忆单元的容量会饱和,从而大大降低LSTM模型的性能. - 耦合输入门和遗忘门 :同时用两个门比较冗余.
为了减少LSTM网络的计算复杂度,将这两门合并为一个门.
令 f t = 1 − i t f_t=1-i_t ft=1−it ,内部状态的更新方式为
c t = ( 1 − i t ) c t − 1 + i t c t ~ c_t=(1-i_t)c_{t-1}+i_t\tilde{c_t} ct=(1−it)ct−1+itct~ - peephole 连接 :三个门不但依赖于输入
x
t
x_t
xt 和上一时刻的隐状态
h
t
−
1
h_{t-1}
ht−1,也依赖于上一个时刻的记忆单元
c
t
−
1
c_{t-1}
ct−1.
i t = σ ( W i x t + U i h t − 1 + V i c t − 1 + b i ) f t = σ ( W f x t + U f h t − 1 + V f c t − 1 + b f ) o t = σ ( W o x t + U o h t − 1 + V o c t − 1 + b o ) i_t=\sigma(W_ix_t+U_ih_{t-1}+V_ic_{t-1}+b_i)\\ f_t=\sigma(W_fx_t+U_fh_{t-1}+V_fc_{t-1}+b_f)\\ o_t=\sigma(W_ox_t+U_oh_{t-1}+V_oc_{t-1}+b_o) it=σ(Wixt+Uiht−1+Vict−1+bi)ft=σ(Wfxt+Ufht−1+Vfct−1+bf)ot=σ(Woxt+Uoht−1+Voct−1+bo)
其中 V i , V f , V o V_i,V_f,V_o Vi,Vf,Vo 为对角矩阵
门控循环单元网络
门控循环单元(Gated Recurrent Unit,GRU)网络
h
t
=
h
t
−
1
+
g
(
x
t
,
h
t
−
1
;
θ
)
h_t=h_{t-1}+g(x_t,h_{t-1}; \theta)
ht=ht−1+g(xt,ht−1;θ)
引入门控来控制信息更新方式,而不增加新的状态
h
t
=
z
t
⊙
h
t
−
1
+
(
1
−
z
t
)
⊙
g
(
x
t
,
h
t
−
1
;
θ
)
h_t=z_t\odot h_{t-1}+(1-z_t)\odot g(x_t,h_{t-1};\theta)
ht=zt⊙ht−1+(1−zt)⊙g(xt,ht−1;θ)
其中
z
t
∈
[
0
,
1
]
D
z_t\in [0,1]^D
zt∈[0,1]D 为更新门,
z
t
=
σ
(
W
z
x
t
+
U
z
h
t
−
1
+
b
z
)
z_t=\sigma(W_zx_t+U_zh_{t-1}+b_z)
zt=σ(Wzxt+Uzht−1+bz)
在GRU网络中,函数
g
(
x
t
,
h
t
−
1
;
θ
)
g(x_t,h_{t-1};\theta)
g(xt,ht−1;θ) 的定义为
g
(
x
t
,
h
t
−
1
;
θ
)
≜
h
t
~
=
t
a
n
h
(
W
h
x
t
+
U
h
(
r
t
⊙
h
t
−
1
)
+
b
h
)
g(x_t,h_{t-1};\theta)\triangleq \tilde{h_t}=tanh(W_hx_t+U_h(r_t\odot h_{t-1})+b_h)
g(xt,ht−1;θ)≜ht~=tanh(Whxt+Uh(rt⊙ht−1)+bh)
候选状态:
h
t
~
\tilde{h_t}
ht~ 门:
r
t
∈
[
0
,
1
]
D
r_t\in[0,1]^D
rt∈[0,1]D
r
t
=
σ
(
W
r
x
t
+
U
r
h
t
−
1
+
b
r
)
r_t=\sigma(W_rx_t+U_rh_{t-1}+b_r)
rt=σ(Wrxt+Urht−1+br)
综上,GRU网络的状态更新方式为
h t = z t ⊙ h t − 1 + ( 1 − z t ) ⊙ h t ~ h_t=z_t\odot h_{t-1}+(1-z_t)\odot \tilde{h_t} ht=zt⊙ht−1+(1−zt)⊙ht~
可以看出,当 z t = 0 , r t = 1 z_t=0,r_t=1 zt=0,rt=1 时,GRU网络退化为简单循环网络
深层循环神经网络
增加同一时刻网络输入到输出之间的路径 x t → y t x_t\rarr y_t xt→yt,
比如增加隐状态到输出 h t → y t h_t\rarr y_t ht→yt,以及输入到隐状态 x t → h t x_t\rarr h_t xt→ht 之间的路径的深度.
堆叠循环神经网络
将多个循环网络堆叠起来
定义 h t ( l ) h_t^{(l)} ht(l) 为在时刻 t t t 时第 l l l 层的隐状态
h
t
(
l
)
=
f
(
U
(
l
)
h
t
−
1
(
l
)
+
W
(
l
)
h
t
(
l
−
1
)
+
b
(
l
)
)
h_t^{(l)}=f(U^{(l)}h_{t-1}^{(l)}+W^{(l)}h_t^{(l-1)}+b^{(l)})
ht(l)=f(U(l)ht−1(l)+W(l)ht(l−1)+b(l))
其中
U
(
l
)
、
W
(
l
)
、
b
(
l
)
U^{(l)}、W^{(l)}、b^{(l)}
U(l)、W(l)、b(l) 为权重矩阵和偏置向量,
h
t
(
0
)
=
x
t
h_t^{(0)}=x_t
ht(0)=xt
双向循环神经网络
一个时刻的输出不但和过去时刻的信息有关,也和后续时刻的信息有关.
比如给定一个句子,其中一个词的词性由它的上下文决定,即包含左右两边的信息
文本数据:词性标注
增加一个按照时间的逆序来传递信息的网络层,来增强网络的能力
双向循环神经网络(Bidirectional Recurrent Neural Network,Bi-RNN)由两层循环神经网络组成,它们的输入相同,只是信息传递的方向不同.
假设第1层按时间顺序,第2层按时间逆序,在时刻𝑡 时的隐状态定义为
h
t
(
1
)
和
h
t
(
2
)
h_t^{(1)}和h_t^{(2)}
ht(1)和ht(2) 那么:
h
t
(
1
)
=
f
(
U
(
1
)
h
t
−
1
(
1
)
+
W
(
1
)
x
t
+
b
(
1
)
)
h
t
(
2
)
=
f
(
U
(
2
)
h
t
+
1
(
2
)
+
W
(
2
)
x
t
+
b
(
2
)
)
h
t
=
h
t
(
1
)
⊕
h
t
(
2
)
#
#
向
量
拼
接
h_t^{(1)}=f(U^{(1)}\textcolor{blue}{h_{t-1}^{(1)}}+W^{(1)}x_t+b^{(1)})\\ h_t^{(2)}=f(U^{(2)}\textcolor{blue}{h_{t+1}^{(2)}}+W^{(2)}x_t+b^{(2)})\\ h_t=h_t^{(1)} \oplus h_t^{(2)} \quad \#\# 向量拼接
ht(1)=f(U(1)ht−1(1)+W(1)xt+b(1))ht(2)=f(U(2)ht+1(2)+W(2)xt+b(2))ht=ht(1)⊕ht(2)##向量拼接