深度学习之循环神经网络(3)梯度传播
通过循环神经网络的更新表达式可以看出输出对张量
W
x
h
\boldsymbol W_{xh}
Wxh、
W
h
h
\boldsymbol W_{hh}
Whh和偏置
b
\boldsymbol b
b均是可导的,可以利用自动梯度算法来求解网络的梯度。此处我们仅简单地推导一下RNN的梯度传播公式,并观察其特点。
考虑梯度
∂
L
∂
W
h
h
\frac{∂\mathcal L}{∂\boldsymbol W_{hh}}
∂Whh∂L,其中
L
\mathcal L
L为网络的误差,只考虑最后一个时刻
t
t
t的输出
o
t
\boldsymbol o_t
ot与真实值之间的差距。由于
W
h
h
\boldsymbol W_{hh}
Whh被每个时间戳i上权值共享,在计算
∂
L
∂
W
h
h
\frac{∂\mathcal L}{∂\boldsymbol W_{hh}}
∂Whh∂L时需要将每个中间时间戳
i
i
i上面的梯度求和,利用链式法则展开为
∂
L
∂
W
h
h
=
∑
i
=
1
t
∂
L
∂
o
t
∂
o
t
∂
h
t
∂
h
t
∂
h
i
∂
+
h
i
∂
W
h
h
\frac{∂\mathcal L}{∂\boldsymbol W_{hh}}=\sum_{i=1}^t\frac{∂\mathcal L}{∂\boldsymbol o_t} \frac{∂\boldsymbol o_t}{∂\boldsymbol h_t} \frac{∂\boldsymbol h_t}{∂\boldsymbol h_i} \frac{∂^+ \boldsymbol h_i}{∂\boldsymbol W_{hh}}
∂Whh∂L=i=1∑t∂ot∂L∂ht∂ot∂hi∂ht∂Whh∂+hi
其中
∂
L
∂
o
t
\frac{∂\mathcal L}{∂\boldsymbol o_t}
∂ot∂L可以基于损失函数直接求得,
∂
o
t
∂
h
t
\frac{∂\boldsymbol o_t}{∂\boldsymbol h_t}
∂ht∂ot 在
o
t
=
h
t
\boldsymbol o_t=\boldsymbol h_t
ot=ht的情况下:
∂
o
t
∂
h
t
=
1
\frac{∂\boldsymbol o_t}{∂\boldsymbol h_t}=1
∂ht∂ot=1
而
∂
+
h
i
∂
W
h
h
\frac{∂^+ \boldsymbol h_i}{∂\boldsymbol W_{hh}}
∂Whh∂+hi的梯度将
h
i
\boldsymbol h_i
hi展开后也可以求得:
∂
+
h
i
∂
W
h
h
=
∂
σ
(
W
x
h
x
t
+
W
h
h
h
t
−
1
+
b
)
∂
W
h
h
\frac{∂^+ \boldsymbol h_i}{∂\boldsymbol W_{hh}}=\frac{∂σ(\boldsymbol W_{xh} \boldsymbol x_t+\boldsymbol W_{hh} \boldsymbol h_{t-1}+\boldsymbol b)}{∂\boldsymbol W_{hh}}
∂Whh∂+hi=∂Whh∂σ(Wxhxt+Whhht−1+b)
其中
∂
+
h
i
∂
W
h
h
\frac{∂^+ \boldsymbol h_i}{∂\boldsymbol W_{hh}}
∂Whh∂+hi只考虑到一个时间戳的梯度传播,即“直接”偏导数,与
∂
L
∂
W
h
h
\frac{∂\mathcal L}{∂\boldsymbol W_{hh}}
∂Whh∂L考虑
i
=
1
,
…
,
t
i=1,…,t
i=1,…,t所有的时间戳的偏导数不同。
因此,只需要推导出
∂
h
t
∂
h
i
\frac{∂\boldsymbol h_t}{∂\boldsymbol h_i}
∂hi∂ht的表达式即可完成循环神经网络的梯度推导。利用链式法则,我们把
∂
h
t
∂
h
i
\frac{∂\boldsymbol h_t}{∂\boldsymbol h_i}
∂hi∂ht分拆分连续时间戳的梯度表达式:
∂
h
t
∂
h
i
=
∂
h
t
∂
h
t
−
1
∂
h
t
−
1
∂
2
…
∂
h
i
+
1
∂
h
i
=
∏
k
=
i
t
−
1
∂
h
k
+
1
∂
h
k
\frac{∂\boldsymbol h_t}{∂\boldsymbol h_i}=\frac{∂\boldsymbol h_t}{∂\boldsymbol h_{t-1}} \frac{∂\boldsymbol h_{t-1}}{∂2} … \frac{∂\boldsymbol h_{i+1}}{∂\boldsymbol h_i}=\prod_{k=i}^{t-1}{\frac{∂\boldsymbol h_{k+1}}{∂\boldsymbol h_k}}
∂hi∂ht=∂ht−1∂ht∂2∂ht−1…∂hi∂hi+1=k=i∏t−1∂hk∂hk+1
考虑
h
k
+
1
=
∂
σ
(
W
x
h
x
k
+
1
+
W
h
h
h
k
+
b
)
\boldsymbol h_{k+1}=∂σ(\boldsymbol W_{xh} \boldsymbol x_{k+1}+\boldsymbol W_{hh} \boldsymbol h_k+\boldsymbol b)
hk+1=∂σ(Wxhxk+1+Whhhk+b)
那么
∂
h
k
+
1
∂
h
k
=
W
h
h
T
d
i
a
g
(
σ
′
(
W
x
h
x
k
+
1
+
W
h
h
h
k
+
b
)
)
=
W
h
h
T
d
i
a
g
(
σ
′
(
h
k
+
1
)
)
\begin{aligned}\frac{∂\boldsymbol h_{k+1}}{∂\boldsymbol h_k}&=\boldsymbol W_{hh}^T diag(σ' (\boldsymbol W_{xh} \boldsymbol x_{k+1}+\boldsymbol W_{hh} \boldsymbol h_k+\boldsymbol b))\\ &=\boldsymbol W_{hh}^T diag(σ' (\boldsymbol h_{k+1}))\end{aligned}
∂hk∂hk+1=WhhTdiag(σ′(Wxhxk+1+Whhhk+b))=WhhTdiag(σ′(hk+1))
其中
d
i
a
g
(
x
)
diag(\boldsymbol x)
diag(x)把向量
x
\boldsymbol x
x的每个元素作为矩阵的对角元素,得到其它元素全为0的对角矩阵,例如:
d
i
a
g
(
[
3
,
2
,
1
]
)
=
[
3
0
0
0
2
0
0
0
1
]
diag([3,2,1])=\begin{bmatrix}3&0&0\\0&2&0\\0&0&1\end{bmatrix}
diag([3,2,1])=⎣⎡300020001⎦⎤
因此
∂
h
t
∂
h
i
=
∏
j
=
i
t
−
1
d
i
a
g
(
σ
′
(
W
x
h
x
k
+
1
+
W
h
h
h
k
+
b
)
)
W
h
h
\frac{∂\boldsymbol h_t}{∂\boldsymbol h_i}=\prod_{j=i}^{t-1}diag(σ' (\boldsymbol W_{xh} \boldsymbol x_{k+1}+\boldsymbol W_{hh} \boldsymbol h_k+\boldsymbol b)) \boldsymbol W_{hh}
∂hi∂ht=j=i∏t−1diag(σ′(Wxhxk+1+Whhhk+b))Whh
至此,
∂
L
∂
W
h
h
\frac{∂\mathcal L}{∂\boldsymbol W_{hh}}
∂Whh∂L的梯度推导完成。
由于深度学习框架可以帮助我们自动推导梯度,只需要简单地了解循环神经网络的梯度传播方式即可。我们在推导
∂
L
∂
W
h
h
\frac{∂\mathcal L}{∂\boldsymbol W_{hh}}
∂Whh∂L的过程中发现,
∂
h
t
∂
h
i
\frac{∂\boldsymbol h_t}{∂\boldsymbol h_i}
∂hi∂ht的梯度包含了
W
h
h
\boldsymbol W_{hh}
Whh的连乘运算,我们会在后面介绍,这是导致循环神经网络训练困难的根本原因。