自然语言处理-自学笔记-06 递归神经网络
递归神经网络
递归神经网络旨在处理序列数据,如文本或股票价格。RNN维护一个状态变量,用于捕获序列数据中存在的各种模式。RNN随时间共享相同的参数集,随时间共享参数是RNN的重要部分。对于在序列中观察到的每个输入,状态变量将随时间更新。在给定先前观察到的序列值的情况下,这些随时间共享的参数通过与状态向量组合,能够预测序列的下一个值。由于一次只处理一个元素,因此RNN可以处理任意长度的数据,而无需使用特殊标记填充数据。
理解RNN
RNN会维持一个状态变量,这个变量会随时间演化,实现对序列数据建模。一组循环连接会随时间更新状态变量。循环连接根据RNN过去的存储状态更新当前状态变量,使RNN可以基于当前输入以及先前输入进行预测。
前馈神经网络的问题
前馈神经网络在时间 t t t的预测输出 y t y_t yt仅取决于当前输入 x t x_t xt,而对产生 x t x_t xt的输入 ( x 1 , . . . , x t − 1 ) {(x_1,...,x_{t-1})} (x1,...,xt−1)没有了解。前馈神经网络失效。
用递归神经网络进行建模
现有如下数据:
x
=
{
x
1
,
x
2
,
.
.
.
,
x
T
}
,
y
=
{
y
1
,
y
2
,
.
.
.
,
y
T
}
x=\{ x_1,x_2,...,x_T\},y=\{ y_1,y_2,...,y_T\}
x={x1,x2,...,xT},y={y1,y2,...,yT}
假定有如下关系:
h
t
=
g
1
(
x
t
,
h
t
−
1
)
h_t=g_1(x_t,h_{t-1})
ht=g1(xt,ht−1)
y
t
=
g
2
(
h
t
)
y_t=g_2(h_t)
yt=g2(ht)
用参数是
θ
\theta
θ的函数逼近器
f
1
(
x
t
,
h
t
−
1
;
θ
)
{{f}_{1}}({{x}_{t}},{{h}_{t-1}};\theta )
f1(xt,ht−1;θ)替换
g
1
g_1
g1,用
f
2
(
h
t
;
φ
)
{{f}_{2}}({{h}_{t}};\varphi )
f2(ht;φ)替换
g
2
g_2
g2,如下所示:
h
t
=
f
1
(
x
t
,
h
t
−
1
;
θ
)
h_t={{f}_{1}}({{x}_{t}},{{h}_{t-1}};\theta )
ht=f1(xt,ht−1;θ)
y
t
=
f
2
(
h
t
;
φ
)
y_t={{f}_{2}}({{h}_{t}};\varphi )
yt=f2(ht;φ)
可以得到:
y
t
=
f
2
(
f
1
(
x
t
,
h
t
−
1
;
θ
)
;
φ
)
y_t={{f}_{2}}({{f}_{1}}({{x}_{t}},{{h}_{t-1}};\theta );\varphi )
yt=f2(f1(xt,ht−1;θ);φ)
RNN的技术描述
上面得到了近似函数:
h
t
=
f
1
(
x
t
,
h
t
−
1
;
θ
)
h_t={{f}_{1}}({{x}_{t}},{{h}_{t-1}};\theta )
ht=f1(xt,ht−1;θ)
y
t
=
f
2
(
h
t
;
φ
)
y_t={{f}_{2}}({{h}_{t}};\varphi )
yt=f2(ht;φ)
神经网络由一组权重和偏置以及一些非线性激活函数组成。可以将上面的关系写成如下:
h
t
=
t
a
n
h
(
U
x
t
+
W
h
t
−
1
)
h_t =tanh(Ux_t+Wh_{t-1})
ht=tanh(Uxt+Wht−1)
y
t
=
s
o
f
t
m
a
x
(
V
h
t
)
y_t=softmax(Vh_t)
yt=softmax(Vht)
基于时间的反向传播(BPTT)
反向传播的工作原理
反向传播是用于训练前馈神经网络的技术。反向传播进行以下操作:
- 计算给定输入的预测结果。
- 计算预测误差E(均方误差和交叉熵误差)。
- 通过在所有 w i j w_{ij} wij的梯度 ∂ E ∂ w i j \frac{\partial E}{\partial {{w}_{ij}}} ∂wij∂E的相反方向上前进一小步,更新前馈网络的权值,以便最小化步骤2中计算的损失 w i j w_{ij} wij是第 i i i层第 j j j个权重。
为什么RNN不能直接使用反向传播
当使用链式法则计算 ∂ E ∂ w 3 \frac{\partial E}{\partial {{w}_{3}}} ∂w3∂E时:
∂
E
∂
w
3
=
∂
L
∂
w
y
∂
y
∂
w
h
∂
h
∂
w
3
\frac{\partial E}{\partial {{w}_{3}}}=\frac{\partial L}{\partial {{w}_{y}}}\frac{\partial y}{\partial {{w}_{h}}}\frac{\partial h}{\partial {{w}_{3}}}
∂w3∂E=∂wy∂L∂wh∂y∂w3∂h
可以将上式变为:
∂
E
∂
w
3
=
∂
(
y
−
l
)
2
∂
y
∂
(
w
2
h
)
∂
h
(
∂
(
w
1
x
)
∂
w
3
+
∂
w
3
h
∂
w
3
)
\frac{\partial E}{\partial {{w}_{3}}}=\frac{\partial {{(y-l)}^{2}}}{\partial y}\frac{\partial ({{w}_{2}}h)}{\partial h}(\frac{\partial ({{w}_{1}}x)}{\partial {{w}_{3}}}+\frac{\partial {{w}_{3}}h}{\partial {{w}_{3}}})
∂w3∂E=∂y∂(y−l)2∂h∂(w2h)(∂w3∂(w1x)+∂w3∂w3h)
其中
∂
w
3
h
∂
w
3
\frac{\partial {{w}_{3}}h}{\partial {{w}_{3}}}
∂w3∂w3h会出现问题,因为这是递归变量。会得到无穷多的导数项。要解决这一问题,可以将输入序列随时间展开,为每个输入
x
t
x_t
xt创建RNN的副本,并分别计算每个副本的导数,通过计算梯度的总和将他们回滚,以计算需要更新的权重大小。
基于时间序列的反向传播:训练RNN
计算RNN不考虑单个输入,而是考虑完整的输入序列。例如计算第4时间步的
∂
E
∂
w
3
\frac{\partial E}{\partial {{w}_{3}}}
∂w3∂E,可以得到:
∂
E
∂
w
3
=
∑
j
=
1
3
∂
L
∂
y
4
∂
y
4
∂
h
4
∂
h
4
∂
h
j
∂
h
j
∂
w
3
\frac{\partial E}{\partial {{w}_{3}}}=\sum\limits_{j=1}^{3}{\frac{\partial L}{\partial {{y}_{4}}}\frac{\partial {{y}_{4}}}{\partial {{h}_{4}}}}\frac{\partial {{h}_{4}}}{\partial {{h}_{j}}}\frac{\partial {{h}_{j}}}{\partial {{w}_{3}}}
∂w3∂E=j=1∑3∂y4∂L∂h4∂y4∂hj∂h4∂w3∂hj
这意味着需要计算直到第4个时间点的所有时间步的梯度之和,首先展开序列,对每个时间步
j
j
j计算
∂
h
4
∂
h
j
\frac{\partial {{h}_{4}}}{\partial {{h}_{j}}}
∂hj∂h4和
∂
h
j
∂
w
3
\frac{\partial {{h}_{j}}}{\partial {{w}_{3}}}
∂w3∂hj,通过创建4份RNN的副本完成的。为了计算
∂
h
t
∂
h
j
\frac{\partial {{h}_{t}}}{\partial {{h}_{j}}}
∂hj∂ht,需要
t
−
j
+
1
t-j+1
t−j+1个RNN副本。然后将副本汇总到单个RNN,求所有先前时间步长的梯度和得到一个梯度,并用
∂
E
∂
w
3
\frac{\partial E}{\partial {{w}_{3}}}
∂w3∂E更新RNN。
为了获得更高的计算效率,可以使用BPTT的近似,即截断的基于时间的反向传播(TBPTT),来优化递归模型。
截断的BPTT:更有效地训练RNN
在TBPTT中仅计算固定数量T个时间步长的梯度,当计算时间步长t的
∂
E
∂
w
3
\frac{\partial E}{\partial {{w}_{3}}}
∂w3∂E时,只计算到
t
−
T
t-T
t−T:
∂
E
∂
w
3
=
∑
j
=
t
−
T
t
−
1
∂
L
∂
y
t
∂
y
t
∂
h
t
∂
h
t
∂
h
j
∂
h
j
∂
w
3
\frac{\partial E}{\partial {{w}_{3}}}=\sum\limits_{j=t-T}^{t-1}{\frac{\partial L}{\partial {{y}_{t}}}\frac{\partial {{y}_{t}}}{\partial {{h}_{t}}}}\frac{\partial {{h}_{t}}}{\partial {{h}_{j}}}\frac{\partial {{h}_{j}}}{\partial {{w}_{3}}}
∂w3∂E=j=t−T∑t−1∂yt∂L∂ht∂yt∂hj∂ht∂w3∂hj
在标准BPTT中,对于每个时间步长
t
t
t,我们计算直到序列最开始的导数。在序列长度很大时,在计算上变得不可行。在截断BPTT中,仅向后计算固定数量的导数,随着序列变大,计算成本不会改变。
BPTT的限制:梯度消失和梯度爆炸
展开
∂
E
∂
w
3
\frac{\partial E}{\partial {{w}_{3}}}
∂w3∂E中单独的一项,如下所示:
∂
L
∂
y
4
∂
y
4
∂
h
4
∂
h
4
∂
h
j
∂
h
j
∂
w
3
=
∂
L
∂
y
4
∂
y
4
∂
h
4
∂
(
w
1
x
+
w
3
h
3
)
∂
h
1
∂
(
w
1
x
+
w
3
h
0
)
∂
w
3
{\frac{\partial L}{\partial {{y}_{4}}}\frac{\partial {{y}_{4}}}{\partial {{h}_{4}}}}\frac{\partial {{h}_{4}}}{\partial {{h}_{j}}}\frac{\partial {{h}_{j}}}{\partial {{w}_{3}}}={\frac{\partial L}{\partial {{y}_{4}}}\frac{\partial {{y}_{4}}}{\partial {{h}_{4}}}}\frac{\partial( {{w}_{1}x+w_3h_3})}{\partial {{h}_{1}}}\frac{\partial( {{w}_{1}x+w_3h_0})}{\partial {{w}_{3}}}
∂y4∂L∂h4∂y4∂hj∂h4∂w3∂hj=∂y4∂L∂h4∂y4∂h1∂(w1x+w3h3)∂w3∂(w1x+w3h0)由于循环连接导致了反向传播的问题,因此忽略
w
1
x
w_1x
w1x,考虑如下:
∂
L
∂
y
4
∂
y
4
∂
h
4
∂
h
4
∂
h
j
∂
h
j
∂
w
3
=
∂
L
∂
y
4
∂
y
4
∂
h
4
∂
(
w
3
h
3
)
∂
h
1
∂
(
w
3
h
0
)
∂
w
3
{\frac{\partial L}{\partial {{y}_{4}}}\frac{\partial {{y}_{4}}}{\partial {{h}_{4}}}}\frac{\partial {{h}_{4}}}{\partial {{h}_{j}}}\frac{\partial {{h}_{j}}}{\partial {{w}_{3}}}={\frac{\partial L}{\partial {{y}_{4}}}\frac{\partial {{y}_{4}}}{\partial {{h}_{4}}}}\frac{\partial( {w_3h_3})}{\partial {{h}_{1}}}\frac{\partial( {w_3h_0})}{\partial {{w}_{3}}}
∂y4∂L∂h4∂y4∂hj∂h4∂w3∂hj=∂y4∂L∂h4∂y4∂h1∂(w3h3)∂w3∂(w3h0)通过简单的算数运算,可以得到:
∂
L
∂
y
4
∂
y
4
∂
h
4
∂
(
w
3
h
3
)
∂
h
1
∂
(
w
3
h
0
)
∂
w
3
=
∂
L
∂
y
4
∂
y
4
∂
h
4
h
0
w
3
3
{\frac{\partial L}{\partial {{y}_{4}}}\frac{\partial {{y}_{4}}}{\partial {{h}_{4}}}}\frac{\partial( {w_3h_3})}{\partial {{h}_{1}}}\frac{\partial( {w_3h_0})}{\partial {{w}_{3}}}={\frac{\partial L}{\partial {{y}_{4}}}\frac{\partial {{y}_{4}}}{\partial {{h}_{4}}}}h_0w_3^3
∂y4∂L∂h4∂y4∂h1∂(w3h3)∂w3∂(w3h0)=∂y4∂L∂h4∂y4h0w33
当只有4个时间步时,有一项
w
3
3
w_3^3
w33。在第n个时间步,它将变为
w
3
n
−
1
w_3^{n-1}
w3n−1如果
w
3
w_3
w3的初始化值很小(0.00001),那么在
n
=
100
n=100
n=100时,梯度将是无穷小。由于计算机在表示数字方面精度有限,因此将忽略这次更新(即算术下溢),这就叫做梯度消失。能在一定程度上解决梯度消失问题的集中技术是在初始化权重的时候格外小心,或使用基于动量的优化方法。
另一方面,假设我们将
w
3
w_3
w3初始化为一个很大值,比如1000.00,在
n
=
100
n=100
n=100时间步常。梯度将是巨大的。内存会溢出,导致梯度爆炸。
另外,面对复杂的非凸损失面,非常高的曲率会形成墙,在进行优化时,梯度将爆炸或过冲。这可能导致损失最小化很差或数值不稳定性。在这种情况下避免梯度爆炸的简单解决方案是在梯度大于某个阈值时,将梯度剪裁为合理小的值。