- 介绍GRU之前,首先我们先直观的理解一下梯度消失(Gradient Vanishing)问题。
RNN在NLP中具有很大的应用价值,但是其存在一个很大的缺陷,那就是梯度消失的问题。例如下面的例句中:
The cat, which already ate …,was full;
The cats, which already ate …,were full.
在这两个句子中,cat对应着was,cats对应着were,(中间存在很多很长省略的单词),句子中存在长期依赖(long-term dependencies),前面的单词对后面的单词有很重要的影响。但是我们目前所见到的基本的RNN模型,是不擅长捕获这种长期依赖关系的。
和基本的深度神经网络结构类似,输出
y
y
y得到的梯度很难通过反向传播再传播回去,也就是很难对前面几层的权重产生影响,所以RNN也有同样的问题,也就是很难让网络记住前面的单词是单数或者复数,进而对后面的输出产生影响。
对于梯度消失问题,在RNN的结构中是我们首要关心的问题,也更难解决; 虽然梯度爆炸在RNN中也会出现,但对于梯度爆炸问题,因为参数会指数级的梯度,会让我们的网络参数变得很大,得到很多的Nan或者数值溢出,所以梯度爆炸是很容易发现的,我们的解决方法就是用梯度修剪(gradient clipping),也就是观察梯度向量,如果其大于某个阈值,则对其进行缩放,保证它不会太大。
1. GRU
- 一个包含一个更新门
Γ
u
\Gamma_u
Γu的GRU简化版本如下图示:
公式如下:
c ~ < t > = t a n h ( W c [ c < t − 1 > , x < t > ] + b c ) \tilde c^{<t>}=tanh(W_c[c^{<t-1>},x^{<t>}]+b_c) c~<t>=tanh(Wc[c<t−1>,x<t>]+bc)
Γ u = σ ( W u [ c < t − 1 > , x < t > ] + b u ) \Gamma_u=\sigma(W_u[c^{<t-1>},x^{<t>}]+b_u) Γu=σ(Wu[c<t−1>,x<t>]+bu)
c < t > = Γ u ∗ c ~ < t > + ( 1 − Γ u ) ∗ c < t − 1 > c^{<t>}=\Gamma_u*\tilde c^{<t>}+(1-\Gamma_u)*c^{<t-1>} c<t>=Γu∗c~<t>+(1−Γu)∗c<t−1> - 完整的GRU单元存在着
Γ
u
,
Γ
r
\Gamma_u, \Gamma_r
Γu,Γr两个门,决定着每个时间步的候选值,图示如下:
公式如下:
Γ r = σ ( W r [ c < t − 1 > , x < t > ] + b r ) \Gamma_r=\sigma(W_r[c^{<t-1>},x^{<t>}]+b_r) Γr=σ(Wr[c<t−1>,x<t>]+br)
c ~ < t > = t a n h ( W c [ Γ r ∗ c < t − 1 > , x < t > ] + b c ) \tilde c^{<t>}=tanh(W_c[\Gamma_r*c^{<t-1>},x^{<t>}]+b_c) c~<t>=tanh(Wc[Γr∗c<t−1>,x<t>]+bc)
Γ u = σ ( W u [ c < t − 1 > , x < t > ] + b u ) \Gamma_u=\sigma(W_u[c^{<t-1>},x^{<t>}]+b_u) Γu=σ(Wu[c<t−1>,x<t>]+bu)
c < t > = Γ u ∗ c ~ < t > + ( 1 − Γ u ) ∗ c < t − 1 > c^{<t>}=\Gamma_u*\tilde c^{<t>}+(1-\Gamma_u)*c^{<t-1>} c<t>=Γu∗c~<t>+(1−Γu)∗c<t−1>
2. LSTM
GRU能够让我们在序列中学习到更深的联系,LSTM(long short-term memory)对捕捉序列中更深层次的联系要比GRU更加有效,当然也更复杂。
LSTM中,使用了单独的更新门
Γ
u
Γ_u
Γu和遗忘门
Γ
f
Γ_f
Γf,以及一个输出门
Γ
o
Γ_o
Γo,LSTM单元的可视化图如下所示:
c
~
<
t
>
=
t
a
n
h
(
W
c
[
a
<
t
−
1
>
,
x
<
t
>
]
+
b
c
)
\tilde c^{<t>}=tanh(W_c[a^{<t-1>},x^{<t>}]+b_c)
c~<t>=tanh(Wc[a<t−1>,x<t>]+bc)
Γ
u
=
σ
(
W
u
[
a
<
t
−
1
>
,
x
<
t
>
]
+
b
u
)
\Gamma_u=\sigma(W_u[a^{<t-1>},x^{<t>}]+b_u)
Γu=σ(Wu[a<t−1>,x<t>]+bu)
Γ
f
=
σ
(
W
f
[
a
<
t
−
1
>
,
x
<
t
>
]
+
b
f
)
\Gamma_f=\sigma(W_f[a^{<t-1>},x^{<t>}]+b_f)
Γf=σ(Wf[a<t−1>,x<t>]+bf)
Γ
o
=
σ
(
W
o
[
a
<
t
−
1
>
,
x
<
t
>
]
+
b
o
)
\Gamma_o=\sigma(W_o[a^{<t-1>},x^{<t>}]+b_o)
Γo=σ(Wo[a<t−1>,x<t>]+bo)
c
<
t
>
=
Γ
u
∗
c
~
<
t
>
+
Γ
f
∗
c
<
t
−
1
>
c^{<t>}=\Gamma_u*\tilde c^{<t>}+\Gamma_f*c^{<t-1>}
c<t>=Γu∗c~<t>+Γf∗c<t−1>
a
<
t
>
=
Γ
o
∗
t
a
n
h
(
c
<
t
>
)
a^{<t>}=\Gamma_o*tanh(c^{<t>})
a<t>=Γo∗tanh(c<t>)
在实际使用时,几个门值不仅仅取决于
a
<
t
−
1
>
a^{<t-1>}
a<t−1> 和
x
<
t
−
1
>
x^{<t-1>}
x<t−1> ,还可能会取决于上一个记忆细胞的值
c
<
t
−
1
>
c^{<t-1>}
c<t−1> ,这也叫做peephole connection。