循环神经网络
循环神经网络为更好的处理时序信息而设计,它引入状态变量来存储过去的信息,并用其与当前的输入共同决定当前的输出。接下来我们以语言模型为例来阐述循环神经网络的方方面面。
语言模型
给定一个长度为T的词的序列 w 1 , w 2 , . . . , w T w_1, w_2, ...,w_T w1,w2,...,wT,语言模型将计算该序列的概率为: P ( w 1 , w 2 , . . . , w T ) P(w_1, w_2, ...,w_T) P(w1,w2,...,wT)
语言模型计算
假设序列 w 1 , w 2 , . . . , w T w_1, w_2, ...,w_T w1,w2,...,wT中每个词依次生成,则有:
$P(w_1, w_2, …,w_T) = \prod_{t=1}^{T}P(w_t| w_1, …,w_{t-1}) $
n元语法
n元语法是指一个词的出现只与前面n个词相关,即n阶马尔科夫链。此时语言模型为:
$P(w_1, w_2, …,w_T) = \prod_{t=1}^{T}P(w_{t-n}| w_1, …,w_{t-1}) $
循环神经网络
H t = ϕ ( X t W x h + H t − 1 W h h + b h ) H_t = \phi(X_t W_{xh}+H_{t-1}W_{hh}+b_h) Ht=ϕ(XtWxh+Ht−1Whh+bh)
O t = H t W h q + b q O_t = H_t W_{hq}+b_q Ot=HtWhq+bq
循环神经网络的参数包含隐藏层权重 W x h , W h h W_{xh}, W_{hh} Wxh,Whh和偏差 b h b_h bh;以及输出层的权重 W h q W_{hq} Whq和偏差 b q b_q bq;循环神经网络的参数数量不随时间增加而增长。
语言模型数据集
随机采样:原始序列中任意截取一段,因此无法用小批量最终时间步的隐藏状态来初始化下一个小批量的隐藏状态。
相邻采样:相邻的两个随机小批量在原始序列上的位置毗邻
循环神经网络从零开始实现
one-hot向量
定义模型
H t ( 2 ∗ 256 ) = X t ( 2 ∗ 1027 ) W x h ( 1027 ∗ 256 ) H_{t(2*256)} = X_{t(2*1027)}W_{xh(1027*256)} Ht(2∗256)=Xt(2∗1027)Wxh(1027∗256)+ H t − 1 ( 2 ∗ 256 ) W h h ( 256 ∗ 256 ) H_{t-1(2*256)}W_{hh(256*256)} Ht−1(2∗256)Whh(256∗256)+ b h ( 256 ) b_{h(256)} bh(256)
O t ( 2 ∗ 1027 ) = H t ( 2 ∗ 256 ) W h q ( 256 ∗ 1027 ) + b q ( 1027 ) O_{t(2*1027)} = H_{t(2*256)}W_{hq(256*1027)}+b_{q(1027)} Ot(2∗1027)=Ht(2∗256)Whq(256∗1027)+bq(1027)
定义预测函数
基于前缀prefix,来预测接下来的num_chars个字符。
裁剪梯度
为避免梯度爆炸,所有模型参数的元素拼成一个向量g,设裁剪阀值为 θ \theta θ,则裁剪后的梯度L2范数不超过 θ \theta θ:
m i n ( θ g , 1 ) g min(\frac{\theta}{g},1)g min(gθ,1)g
困惑度
定义模型训练函数
循环神经网络的简洁实现
通过时间方向传播
h t = w h x x t + w h h h t − 1 h_t = w_{hx}x_t+w_{hh}h_{t-1} ht=whxxt+whhht−1
o t = w q h h t o_t = w_{qh}h_t ot=wqhht
损失函数:
L = 1 T ∑ i = 1 T ℓ ( o t , y t ) L=\frac{1}{T}\sum_{i=1}^{T}\ell(o_t, y_t) L=T1∑i=1Tℓ(ot,yt)
目标函数有关各时间步输出层变量的梯度 ∂ L ∂ o t = ∂ ℓ ( o t , y t ) T ⋅ ∂ o t . \frac{\partial L}{\partial \boldsymbol{o}_t} = \frac{\partial \ell (\boldsymbol{o}_t, y_t)}{T \cdot \partial \boldsymbol{o}_t}. ∂ot∂L=T⋅∂ot∂ℓ(ot,yt).
目标函数有关模型参数$W_{qh}
的
梯
度
:
的梯度:
的梯度:
\frac{\partial L}{\partial \boldsymbol{W}{qh}}
= \sum{t=1}^T \frac{\partial L}{\partial \boldsymbol{o}_t} \boldsymbol{h}_t^\top.
$
t=T: ∂ L ∂ h T = W q h T ∂ L ∂ o T \frac{\partial L}{\partial h_T} = W_{qh}^{T}\frac{\partial L}{\partial o_T} ∂hT∂L=WqhT∂oT∂L
t<T: ∂ L ∂ h t = W h h T ∂ L ∂ h t + 1 + W q h T ∂ L ∂ o t \frac{\partial L}{\partial h_t} = W_{hh}^{T}\frac{\partial L}{\partial h_{t+1}} + W_{qh}^{T}\frac{\partial L}{\partial o_t} ∂ht∂L=WhhT∂ht+1∂L+WqhT∂ot∂L
将上面递归公式展开,对任意时间步1<=t<=T,目标函数有关隐藏状态梯度为
∂ L ∂ h T − 1 = W h h T ∂ L ∂ h T + W q h T ∂ L ∂ o ( T − 1 ) = W h h T W q h T ∂ L ∂ o T + W q h T ∂ L ∂ o ( T − 1 ) \frac{\partial L}{\partial h_{T-1}} = W_{hh}^{T}\frac{\partial L}{\partial h_{T}} + W_{qh}^{T}\frac{\partial L}{\partial o_(T-1)}=W_{hh}^{T} W_{qh}^{T}\frac{\partial L}{\partial o_T} + W_{qh}^{T}\frac{\partial L}{\partial o_(T-1)} ∂hT−1∂L=WhhT∂hT∂L+WqhT∂o(T−1)∂L=WhhTWqhT∂oT∂L+WqhT∂o(T−1)∂L
∂ L ∂ h T − 2 = W h h T ∂ L ∂ h T − 1 + W q h T ∂ L ∂ o ( T − 2 ) = ( W h h T ) 2 W q h T ∂ L ∂ o T + W h h T W q h T ∂ L ∂ o ( T − 1 ) + W q h T ∂ L ∂ o ( T − 2 ) \frac{\partial L}{\partial h_{T-2}} = W_{hh}^{T}\frac{\partial L}{\partial h_{T-1}} + W_{qh}^{T}\frac{\partial L}{\partial o_(T-2)}=(W_{hh}^{T})^2 W_{qh}^{T}\frac{\partial L}{\partial o_T} + W_{hh}^{T}W_{qh}^{T}\frac{\partial L}{\partial o_(T-1)} + W_{qh}^{T}\frac{\partial L}{\partial o_(T-2)} ∂hT−2∂L=WhhT∂hT−1∂L+WqhT∂o(T−2)∂L=(WhhT)2WqhT∂oT∂L+WhhTWqhT∂o(T−1)∂L+WqhT∂o(T−2)∂L
以此类推
$\frac{\partial L}{\partial h_t} =\sum_{T}^{i=t} (W_{hh}{T}){T-i} W_{qh}^{T}\frac{\partial L}{\partial o_{T+t-i}} $
由上式,当时间步数T较大或时间步t较小时,目标函数有关隐藏状态的梯度容易出现衰减或爆炸。
目标函数有关模型参数 W h x W_{hx} Whx的梯度为: ∂ L ∂ W h x = ∑ t = 1 T ∂ L ∂ h t x t ⊤ \frac{\partial L}{\partial \boldsymbol{W}_{hx}}=\sum_{t=1}^{T}\frac{\partial L}{\partial \boldsymbol{h}_t} \boldsymbol{x}_t^{\top} ∂Whx∂L=∑t=1T∂ht∂Lxt⊤
目标函数有关模型参数 W h h W_{hh} Whh的梯度为: ∂ L ∂ W h h = ∑ t = 1 T ∂ L ∂ h t h t − 1 ⊤ \frac{\partial L}{\partial \boldsymbol{W}_{hh}} = \sum_{t=1}^T \frac{\partial L}{\partial \boldsymbol{h}_t} \boldsymbol{h}_{t-1}^\top ∂Whh∂L=∑t=1T∂ht∂Lht−1⊤
门控循环单元(GRU)
裁剪梯度可以应对梯度爆炸,却无法解决梯度衰减问题,从而导致循环神经网络较难捕捉时间序列中时间步距离较大的依赖关系。门控循环神经网络就是为了解决这一问题,首先介绍门控循环单元法(GRU)。
R t = σ ( X t W x r + H t − 1 W h r + b r ) R_t = \sigma(X_tW_{xr}+H_{t-1}W_{hr}+b_r) Rt=σ(XtWxr+Ht−1Whr+br)
Z t = σ ( X t W x z + H t − 1 W h z + b r ) Z_t = \sigma(X_tW_{xz}+H_{t-1}W_{hz}+b_r) Zt=σ(XtWxz+Ht−1Whz+br)
候选隐藏状态计算: H ~ t = t a n h ( X t W x h + ( R t ⊙ H t − 1 ) W h h + b h ) \widetilde{H}_t = tanh(X_tW_{xh} +(R_t\odot H_{t-1})W_{hh}+ b_h) H t=tanh(XtWxh+(Rt⊙Ht−1)Whh+bh)
重置门控制了上一时间步的隐藏状态如何流入当前时间步的候选隐藏状态。而上一时间隐藏状态步包含了时间序列截止上一时间步的全部历史信息。因此重置门可以丢弃与预测无关的历史信息。
最后,时间步t的隐藏状态 H t H_t Ht的计算使用当前时间步的更新门 Z t Z_t Zt来对上一时间步的隐藏状态 H t − 1 H_{t-1} Ht−1和当前时间步的候选隐藏状态 H t ~ \widetilde{H_t} Ht 做组合: H t = Z t ⊙ H t − 1 + ( 1 − Z t ) ⊙ H t ~ H_t = Z_t\odot H_{t-1} + (1-Z_t)\odot\widetilde{H_t} Ht=Zt⊙Ht−1+(1−Zt)⊙Ht 。更新门可以控制隐藏状态应该如何被包含当前时间步信息的候选隐藏状态所更新。如果更新们在时间步t^'到t一直近似为1,那这段时间的输入信息几乎没有流入时间步t的隐藏状态 H t H_t Ht,就相当于较早时间步的隐藏状态一直通过时间保存 并传递到当前时间步t。从而解决循环神经网络中的梯度衰减问题。并更好的捕捉时间步较大情况下的依赖关系。
总结:重置门有助于捕捉时间序列的短期依赖关系;更新门有助于捕捉时间序列的长期依赖关系;
长短期记忆(LSTM)
输入门: I t = σ ( X t W x i + H t − 1 W h i + b i ) I_t = \sigma(X_tW_{xi}+H_{t-1}W_{hi}+b_i) It=σ(XtWxi+Ht−1Whi+bi)
遗忘门: F t = σ ( X t W x f + H t − 1 W h f + b f ) F_t = \sigma(X_tW_{xf}+H_{t-1}W_{hf}+b_f) Ft=σ(XtWxf+Ht−1Whf+bf)
输出门: O t = σ ( X t W x o + H t − 1 W h o + b o ) O_t = \sigma(X_tW_{xo}+H_{t-1}W_{ho}+b_o) Ot=σ(XtWxo+Ht−1Who+bo)
候选记忆细胞: C ~ t = σ ( X t W x c + H t − 1 W h c + b c ) \tilde{C}_t = \sigma(X_tW_{xc}+H_{t-1}W_{hc}+b_c) C~t=σ(XtWxc+Ht−1Whc+bc)
通过元素值域在[0,1]的输入门,遗忘门和输出门来控制隐藏状态中信息的流动。
当前时间步记忆细胞: C t = F t ⊙ C t − 1 + I t ⊙ C ~ t C_t = F_t\odot C_{t-1} + I_t\odot \tilde{C}_t Ct=Ft⊙Ct−1+It⊙C~t
遗忘门控制上一时间步记忆细胞 C t − 1 C_{t-1} Ct−1中的信息是否传递到当前时间步;输入门则控制当前时间步输入通过候选记忆细胞如何流入当前时间步的记忆细胞。
隐藏状态: H t = O t ⊙ t a n h ( C t ) H_t = O_t\odot tanh(C_t) Ht=Ot⊙tanh(Ct)