在之前对多层感知机的实现过程中,只考虑了感知机在进行前向传播时所进行的计算,对于涉及梯度计算的反向传播并未进行过多赘述,仅调用深度学习框架所提供的反向传播函数进行自动梯度计算。因此在本节内容中,针对深度学习模型在训练时的前向传播以及反向传播过程进行了介绍。
一、前向传播
前向传播过程主要是指按输入层 -> 隐藏层 -> 输出层顺序传递数值进行计算并存储结果的过程。
以上述图中多层感知机结构为例:
从输入层到隐藏层的计算为:
z
i
=
w
1
x
+
b
1
h
i
=
R
e
L
U
(
z
)
z_i = w_1 x +b_1 \\ h_i = ReLU(z)
zi=w1x+b1hi=ReLU(z)
从隐藏层到输出层的计算为:
o
i
=
y
^
i
=
w
2
h
i
+
b
2
o_i =\hat{y}_i = w_2 h_i + b_2
oi=y^i=w2hi+b2
通过该过程,神经网络可以得到一个输出值
y
^
\hat{y}
y^,用于计算与训练集中真实值
y
y
y的误差,该误差会在反向传播过程中用到,来实现对参数
[
w
,
b
]
[w,b]
[w,b]的修正,输出预测值与真实值的误差损失可用
L
L
L表示:
l
=
l
l
o
s
s
_
f
u
n
c
t
i
o
n
(
y
^
,
y
)
l = l_{loss\_function}(\hat{y},y)
l=lloss_function(y^,y)
同时根据之前学到的
L
2
L2
L2正则定义,对于参数
[
w
1
,
b
1
]
,
[
w
2
,
b
2
]
[w_1,b_1],[w_2,b_2]
[w1,b1],[w2,b2],将其视作拓展后的矩阵
W
1
′
,
W
2
′
W'_1,W'_2
W1′,W2′,存在给定超参数
λ
\lambda
λ,使得正则化项为:
s
=
λ
2
(
∣
∣
W
1
′
∣
∣
2
+
∣
∣
W
2
′
∣
∣
2
)
s=\frac{\lambda}{2}(||W'_1||^2+||W'_2||^2)
s=2λ(∣∣W1′∣∣2+∣∣W2′∣∣2)
综合损失项和正则化项后,施加在模型上的最终损失为:
L
l
o
s
s
=
l
+
s
L_{loss} = l + s
Lloss=l+s
这个从输入层到输出层的计算过程,就是多层感知机的前向传播过程。绘制前向传播的计算图,可以有助于对计算中操作符和变量关系的可视化,多层感知机的计算图可用下图表示:
二、反向传播
如果说前向传播是从输入层到输出层的过程,那顾名思义,反向传播就是从输出层反向向输入层传递计算值的过程,该方法根据微积分中的链式规则,按相反的顺序从输出层到输入层遍历网络。本质上,反向传播是一种求梯度的高效方法,可以理解为模型的 “学习” 过程。
前面在前向传播中提到,前向传播中产生的误差损失会在反向传播中使用。具体如下:
-
针对损失项和正则项分别计算损失函数 L = l + s L=l+s L=l+s的梯度
∂ L ∂ l = 1 , ∂ L ∂ s = 1 \frac{\partial L}{\partial l} = 1,\frac{\partial L}{\partial s} = 1 ∂l∂L=1,∂s∂L=1
-
根据链式法则,计算目标函数关于输出变量 y ^ \hat{y} y^的梯度,以及关于权重参数 W 2 ′ W'_2 W2′的梯度
∂ L ∂ y ^ = ∂ L ∂ l ∂ l ∂ y ^ = ∂ l ∂ y ^ \frac{\partial L}{\partial \hat{y}} = \frac{\partial L}{\partial l}\frac{\partial l}{\partial \hat{y}} = \frac{\partial l}{\partial \hat{y}} ∂y^∂L=∂l∂L∂y^∂l=∂y^∂l
∂ y ^ ∂ W 2 ′ = h ∂ s ∂ W 2 ′ = λ W 2 ′ \frac{\partial \hat{y}}{\partial W'_2}=h \quad \frac{\partial s}{\partial W'_2}=\lambda W'_2 ∂W2′∂y^=h∂W2′∂s=λW2′
∂ L ∂ W 2 ′ = ∂ L ∂ l ∂ l ∂ y ^ ∂ y ^ ∂ W 2 ′ + ∂ L ∂ s ∂ s ∂ W 2 ′ = ∂ l ∂ y ^ ⋅ h + λ W 2 ′ \frac{\partial L}{\partial W'_2} = \frac{\partial L}{\partial l}\frac{\partial l}{\partial \hat{y}} \frac{\partial \hat{y}}{\partial W'_2}+ \frac{\partial L}{\partial s}\frac{\partial s}{\partial W'_2} = \frac{\partial l}{\partial \hat{y}} \cdot h+\lambda W'_2 ∂W2′∂L=∂l∂L∂y^∂l∂W2′∂y^+∂s∂L∂W2′∂s=∂y^∂l⋅h+λW2′ -
继续沿梯度图向输入层方向移动,获得关于 W 1 ′ W'_1 W1′的梯度
∂ L ∂ h = ∂ L ∂ l ∂ l ∂ y ^ ∂ y ^ ∂ h = ∂ l ∂ y ^ ⋅ W 2 ′ \frac{\partial L}{\partial h}=\frac{\partial L}{\partial l}\frac{\partial l}{\partial \hat{y}}\frac{\partial \hat{y}}{\partial h} = \frac{\partial l}{\partial \hat{y}} \cdot W'_2 ∂h∂L=∂l∂L∂y^∂l∂h∂y^=∂y^∂l⋅W2′
∂ s ∂ W 1 ′ = λ W 1 ′ \frac{\partial s}{\partial W'_1}=\lambda W'_1 ∂W1′∂s=λW1′
由于激活函数ReLU在计算时按元素对应进行计算,因此计算中间变量 z z z时使用元素乘法 ⊙ \odot ⊙
∂ L ∂ z = ∂ L ∂ h ∂ h ∂ z = ∂ L ∂ h ⊙ φ ′ ( z ) \frac{\partial L}{\partial z}=\frac{\partial L}{\partial h} \frac{\partial h}{\partial z}=\frac{\partial L}{\partial h} \odot \varphi'(z) ∂z∂L=∂h∂L∂z∂h=∂h∂L⊙φ′(z)
最终得到关于 W 1 ′ W'_1 W1′的梯度:
∂ L ∂ W 1 ′ = ∂ L ∂ z ∂ z ∂ W 1 ′ + ∂ L ∂ s ∂ s ∂ W 1 ′ = ∂ L ∂ z ⋅ x + λ W 1 ′ \frac{\partial L}{\partial W'_1}=\frac{\partial L}{\partial z} \frac{\partial z}{\partial W'_1}+\frac{\partial L}{\partial s}\frac{\partial s}{\partial W'_1}=\frac{\partial L}{\partial z}\cdot x+\lambda W'_1 ∂W1′∂L=∂z∂L∂W1′∂z+∂s∂L∂W1′∂s=∂z∂L⋅x+λW1′ -
根据得到的梯度值对 [ W 1 ′ , W 2 ′ ] [W'_1,W'_2] [W1′,W2′]进行更新,得到最新的权重矩阵 W ′ ^ \hat{W'} W′^
W ′ ^ = W ′ − η ∂ L ∂ W ′ \hat{W'}=W'-\eta \frac{\partial L}{\partial W'} W′^=W′−η∂W′∂L
总结: 归根到底,正向传播与反向传播是一个学习参数,计算误差,然后求导对参数更新的过程。可以理解为一次作业的完成过程:写作业(前向传播)-> 老师审阅(计算误差)-> 打回修改(反向传播) -> 完成作业(训练完成)