课程内容概述
- 反向传播的四种解释
- 课程项目介绍
为什么要理解这些求导过程
- 能够帮你真正地去理解深度学习背后的数学原理。
- 反向传播有时候并不会是一个完美的抽象过程,比如我们可能会遇到梯度消失的等一些优化问题。
- 你可以对模型进行debug,可以思考并使用一些还没有被那些深度学习框架支持的全新的模型。
- 简言之,如果你想真正地研究深度学习,而不只是想做一个调包侠,那就必须理解这些过程中的数学原理。
反向传播的第一种解释
这个解释是最晦涩的一种,但理解当中的数学过程是必须的。
上节课的内容回顾:基于窗口的神经网络
目标:使用一个3层的神经网络来计算一个窗口的分数
比如在命名实体识别中,以一个实体为中心词的窗口分数可能会高一些,其他的窗口分数低一些,所以我们要计算每个窗口的分数,也就是使用一个神经网络来实现这样一个过程:
s
=
s
c
o
r
e
(
m
u
s
e
u
m
s
i
n
P
a
r
i
s
a
r
e
a
m
a
z
i
n
g
)
s=score(museums\ in\ Paris\ are\ amazing)
s=score(museums in Paris are amazing)其中,s代表最后的分数,score代表整个神经网络的计算过程,括号内的内容代表一个窗口,每个窗口中包含5个单词,即:
x
=
x
w
i
n
d
o
w
=
[
x
m
u
s
e
u
m
s
,
x
i
n
,
x
P
a
r
i
s
,
x
a
r
e
,
x
a
m
a
z
i
n
g
]
x=x_{window}=[x_{museums},x_{in},x_{Paris},x_{are},x_{amazing}]
x=xwindow=[xmuseums,xin,xParis,xare,xamazing]
这里面的每个单词假设用一个4维的列向量来表示,然后将窗口中的每个词纵向拼接,可以得到最后的窗口向量
x
x
x是一个
20
20
20维的列向量,也就是
x
∈
R
20
×
1
x\in \R^{20\times1}
x∈R20×1。
单隐藏层的神经网络
前向传播过程
单层神经网络的前向传播过程用公式表示为:
s
=
U
T
f
(
W
x
+
b
)
s=U^Tf(Wx+b)
s=UTf(Wx+b)这个过程可以分步表示为:
z
=
W
x
+
b
z=Wx+b
z=Wx+b
a
=
f
(
z
)
a=f(z)
a=f(z)
s
=
U
T
a
s=U^Ta
s=UTa
其中
x
∈
R
20
×
1
x\in \R^{20\times1}
x∈R20×1 ,,如果我们假设隐藏层得到的向量维数为8,那么矩阵
W
W
W 的维度就应该是
8
×
20
8\times20
8×20 ,即
W
∈
R
8
×
20
W\in \R^{8\times20}
W∈R8×20,并且偏置
b
∈
R
8
×
1
b\in \R^{8\times1}
b∈R8×1 。
f
(
∗
)
f(*)
f(∗) 是隐藏层的激活函数,得到的隐藏层输出结果
a
a
a 再乘一个
1
×
8
1\times8
1×8 权重矩阵
U
T
U^T
UT 就得到了最后的
s
s
s 。
要注意这里面所有的 z z z 都只是经过线性变换的结果,也就是 W x + b Wx+b Wx+b 的结果,这个结果再经过激活函数就是 a a a,下面也是一样的。
反向传播过程
整体的目标函数:
J
=
m
a
x
(
0
,
1
−
s
+
s
c
)
J=max(0,1-s+s_c)
J=max(0,1−s+sc)
其中,
s
s
s 代表正确分类样本的得分,
s
c
s_c
sc 表示误分类样本的得分。
由上面的前向传播过程可得:
s
=
U
T
f
(
W
x
+
b
)
s=U^Tf(Wx+b)
s=UTf(Wx+b)
s
c
=
U
T
f
(
W
x
c
+
b
)
s_c=U^Tf(Wx_c+b)
sc=UTf(Wxc+b)
那么模型的参数比如
U
U
U 的梯度就可以表示为:
∂
J
∂
U
=
1
{
1
−
s
+
s
c
>
0
}
(
−
f
(
W
x
+
b
)
+
f
(
W
x
c
+
b
)
)
\frac{\partial J}{\partial U}=1\left\{ 1-s+s_c>0 \right\}(-f(Wx+b)+f(Wx_c+b))
∂U∂J=1{1−s+sc>0}(−f(Wx+b)+f(Wxc+b))
当然我们可以直接用前向传播保存的中间结果,不需要每次都再计算一遍,也就是
∂
J
∂
U
=
1
{
1
−
s
+
s
c
>
0
}
(
−
a
+
a
c
)
\frac{\partial J}{\partial U}=1\left\{ 1-s+s_c>0 \right\}(-a+a_c)
∂U∂J=1{1−s+sc>0}(−a+ac)
双隐藏层的神经网络
参数数量变多,注意每个参数的上标
前向传播过程
由于有了两个隐藏层,因此参数矩阵有
W
(
1
)
W^{(1)}
W(1) 和
W
(
2
)
W^{(2)}
W(2),整个前馈过程为:
x
=
z
(
1
)
=
a
(
1
)
x=z^{(1)}=a^{(1)}
x=z(1)=a(1)
z
(
2
)
=
W
(
1
)
x
+
b
(
1
)
z^{(2)}=W^{(1)}x+b^{(1)}
z(2)=W(1)x+b(1)
a
(
2
)
=
f
(
z
(
2
)
)
a^{(2)}=f(z^{(2)})
a(2)=f(z(2))
z
(
3
)
=
W
(
2
)
a
(
2
)
+
b
(
2
)
z^{(3)}=W^{(2)}a^{(2)}+b^{(2)}
z(3)=W(2)a(2)+b(2)
a
(
3
)
=
f
(
z
(
3
)
)
a^{(3)}=f(z^{(3)})
a(3)=f(z(3))
s
=
U
T
a
(
3
)
s=U^Ta^{(3)}
s=UTa(3)
所以如果写成一个整体,那么就是
s
=
U
T
f
(
W
(
2
)
f
(
W
(
1
)
x
+
b
(
1
)
)
+
b
(
2
)
)
s=U^Tf(W^{(2)}f(W^{(1)}x+b^{(1)})+b^{(2)})
s=UTf(W(2)f(W(1)x+b(1))+b(2))
反向传播过程
第二层参数的偏导数
根据上面的定义,对于第二层参数矩阵的每个元素:
∂
s
∂
W
i
j
(
2
)
=
U
i
f
′
(
z
i
(
3
)
)
a
j
(
2
)
\frac{\partial s}{\partial W_{ij}^{(2)}}=U_if^{'}(z_i^{(3)})a_j^{(2)}
∂Wij(2)∂s=Uif′(zi(3))aj(2)其实公式当中的
W
i
j
(
2
)
W^{(2)}_{ij}
Wij(2) 就是表示第一个隐藏层的第
j
j
j 个神经元到第二个隐藏层的第
i
i
i 个神经元之间的权重,所以这个过程可以拿出矩阵中的某些元素自己走一遍对应的前向传播和反向的链式求导。
如果以矩阵形式来表示的话,就是 ∂ s ∂ W ( 2 ) = U ∘ f ′ ( z ( 3 ) ) a ( 2 ) T \frac{\partial s}{\partial W^{(2)}}=U\circ f^{'}(z^{(3)}){a^{(2)}}^T ∂W(2)∂s=U∘f′(z(3))a(2)T我们可以令 δ ( 3 ) = U ∘ f ′ ( z ( 3 ) ) \delta^{(3)}=U\circ f^{'}(z^{(3)}) δ(3)=U∘f′(z(3)) (在这个例子中是一个8维列向量), ∘ \circ ∘ 表示Hadamard积(也可以表示为 ⊗ \otimes ⊗、 ⊙ \odot ⊙),也就是将向量或矩阵对应元素相乘,也就是说 δ i ( 3 ) = U i f ′ ( z i ( 3 ) ) \delta^{(3)}_{i}=U_if^{'}(z^{(3)}_i) δi(3)=Uif′(zi(3))。要注意这里出现的 δ \delta δ,它表示了链式求导中上一项的全局偏导,如果再乘上上一项对当前项的局部偏导,那么就得到了当前项的全局偏导,也就是我们要求的东西。 所以引入 δ \delta δ 就是为了体现链式求导的性质。
比如
∂
s
∂
W
(
2
)
=
∂
s
∂
(
W
(
2
)
a
(
2
)
+
b
(
2
)
)
∂
(
W
(
2
)
a
(
2
)
+
b
(
2
)
)
∂
W
(
2
)
\frac{\partial s}{\partial W^{(2)}}=\frac{\partial s}{\partial (W^{(2)}a^{(2)}+b^{(2)})}\frac{\partial (W^{(2)}a^{(2)}+b^{(2)})}{\partial W^{(2)}}
∂W(2)∂s=∂(W(2)a(2)+b(2))∂s∂W(2)∂(W(2)a(2)+b(2))
那么前面一部分就是
δ
(
3
)
\delta^{(3)}
δ(3),后面一部分就是
a
(
2
)
T
{a^{(2)}}^T
a(2)T,所以
∂
s
∂
W
(
2
)
=
δ
(
3
)
a
(
2
)
T
\frac{\partial s}{\partial W^{(2)}}=\delta^{(3)}{a^{(2)}}^T
∂W(2)∂s=δ(3)a(2)T
为了便于理解整个求导过程,也可以试着把公式中所有的矩阵和向量都看作标量。
第一层参数的偏导数
第二层的参数偏导解决后,第一层的参数的偏导数也是同样的道理,我们可以先求
δ
(
2
)
\delta^{(2)}
δ(2) (在这个例子里是一个10维列向量):
δ
(
2
)
=
(
W
(
2
)
T
δ
(
3
)
)
∘
f
′
(
z
i
(
2
)
)
\delta^{(2)}=({W^{(2)}}^T\delta^{(3)})\circ f^{'}(z_i^{(2)})
δ(2)=(W(2)Tδ(3))∘f′(zi(2)) 那么有
∂
s
∂
W
(
1
)
=
δ
(
2
)
x
T
\frac{\partial s}{\partial W^{(1)}}=\delta^{(2)}x^T
∂W(1)∂s=δ(2)xT
我们可以推广到网络中间的任意第
l
l
l 层,对于其中的参数矩阵
W
(
l
)
W^{(l)}
W(l),一个带有正则化的损失对其的偏导数可以这样表示:
δ
(
l
)
=
(
W
(
l
)
T
δ
(
l
+
1
)
)
∘
f
′
(
z
i
(
l
)
)
\delta^{(l)}=({W^{(l)}}^T\delta^{(l+1)})\circ f^{'}(z_i^{(l)})
δ(l)=(W(l)Tδ(l+1))∘f′(zi(l))
∂
E
R
∂
W
(
l
)
=
δ
(
l
+
1
)
(
a
(
l
)
)
T
+
λ
W
(
l
)
\frac{\partial E_R}{\partial W^{(l)}}=\delta^{(l+1)}{(a^{(l)})}^T+\lambda W^{(l)}
∂W(l)∂ER=δ(l+1)(a(l))T+λW(l)
反向传播的第二种解释——计算线路
第二种解释就很简单了,老师直接用计算线路来表示一个简单的前向传播以及链式求导的过程,不涉及到很复杂的矩阵,只用了一些简单的标量来举例。
这种方法把一个前向传播的过程看作一个路线,前向计算和反向的求导都根据这个路线上前一项的结果计算。
另一个例子:
这两个例子都说明了链式求导法就是通过当前层的局部导数乘上之前上一层的全局导数来得到当前层的全局导数。
反向传播的第三种解释——流图
这种方法和第二种方法很像,就是通过一个描述数据流动的有向图来表示整个过程,对于下面这个多路的流图,它很类似于一个单隐藏层的神经网络。
这个例子就更像一个神经网络了:
一个分类过程的流图:
反向传播的第四种解释——真实神经网络中 δ \delta δ 的传播过程
这种解释其实就是再把第一种解释所谈到的复杂的神经网络通过流图的形式来表示出来,再计算每一层的计算过程所涉及的偏导,把之前的解释方法相结合,从一个更宏观的角度来看第一种解释。
δ
\delta
δ 反向经过
W
(
2
)
W^{(2)}
W(2) 就乘上一个
W
(
2
)
W^{(2)}
W(2) 的转置。
δ
\delta
δ 经过一个激活函数就和这个激活函数的结果做Hadamard积。
可以看到
δ
\delta
δ 在各层之间流动时的计算方法,以及每层的参数
W
W
W 的梯度。
总之这几种方法都是在说明在神经网络中链式求导的性质,即:
∂
J
∂
x
=
∂
J
∂
y
∂
y
∂
x
\frac{\partial J}{\partial x}=\frac{\partial J}{\partial y}\frac{\partial y}{\partial x}
∂x∂J=∂y∂J∂x∂y
以上就是本节课的重难点——对于反向传播过程的4种解释方法,后面的有关课程项目的内容就不总结了。