基础:链式法则
神经网络反向传播的求导基于链式法则。以两个复合的函数为例:
d
f
(
g
(
x
)
)
d
x
=
d
f
(
g
(
x
)
)
d
g
(
x
)
⋅
d
g
(
x
)
d
x
\frac{\mathrm{d}f(g(x))}{\mathrm{d}x}=\frac{\mathrm{d}f(g(x))}{\mathrm{d}g(x)}\cdot \frac{\mathrm{d}g(x)}{\mathrm{d}x}
dxdf(g(x))=dg(x)df(g(x))⋅dxdg(x)
神经网络的每层相当于一个简单的函数,整个神经网络就相当于这些函数的复合。可以发现,链式法可以看成是前一层传下的梯度
σ
l
−
1
\sigma_{l-1}
σl−1乘以当前层的梯度。例如上式就可以写成:
σ
l
=
σ
l
−
1
⋅
d
g
(
x
)
d
x
\sigma_{l}=\sigma_{l-1} \cdot \frac{\mathrm{d}g(x)}{\mathrm{d}x}
σl=σl−1⋅dxdg(x)
下面逐层推导反向传播公式。为简单计,只讨论单个样本的情况。
损失层
以著名的交叉熵损失函数为例,其前向推断产生的损失函数为
l
=
−
(
y
t
r
u
e
⋅
log
y
+
(
1
−
y
t
r
u
e
)
log
(
1
−
y
)
)
l=-(y_{true}\cdot \log y+(1-y_{true})\log (1-y))
l=−(ytrue⋅logy+(1−ytrue)log(1−y))
其中真实标签
y
t
r
u
e
y_{true}
ytrue只有两个取值:0或1。实际应用中对数函数用
ln
\ln
ln函数。因此求导公式为
∂
l
∂
y
=
{
−
1
y
,
y
t
r
u
e
=
1
1
1
−
y
,
y
t
r
u
e
=
0
\frac{\partial l}{\partial y}=\left\{ \begin{aligned} & -\frac{1}{y},y_{true}=1 \\ & \frac{1}{1-y},y_{true}=0 \end{aligned} \right.
∂y∂l=⎩⎪⎪⎨⎪⎪⎧−y1,ytrue=11−y1,ytrue=0
softmax层
softmax前向推断公式:
y
i
=
e
x
p
(
x
i
)
∑
k
e
x
p
(
x
k
)
y_i=\frac{exp(x_i)}{\sum_k exp(x_k)}
yi=∑kexp(xk)exp(xi)
求导时需要分
i
=
j
i=j
i=j和
i
≠
j
i\ne j
i=j两种情况讨论。
当
i
=
j
i=j
i=j时,
∂
y
i
∂
x
j
=
e
x
p
(
x
i
)
∑
k
e
x
p
(
x
k
)
−
e
x
p
(
x
i
)
e
x
p
(
x
i
)
(
∑
k
e
x
p
(
x
k
)
)
2
=
e
x
p
(
x
i
)
∑
k
e
x
p
(
x
k
)
−
e
x
p
2
(
x
i
)
(
∑
k
e
x
p
(
x
k
)
)
2
=
y
i
−
y
i
2
\begin{aligned} \frac{\partial y_i}{\partial x_j}&=\frac{exp(x_i)\sum_k exp(x_k)-exp(x_i)exp(x_i)}{(\sum_k exp(x_k))^2} \\ &=\frac{exp(x_i)}{\sum_k exp(x_k)}-\frac{exp^2(x_i)}{(\sum_k exp(x_k))^2} \\ & =y_i-y_i^2 \end{aligned}
∂xj∂yi=(∑kexp(xk))2exp(xi)∑kexp(xk)−exp(xi)exp(xi)=∑kexp(xk)exp(xi)−(∑kexp(xk))2exp2(xi)=yi−yi2
当
i
≠
j
i\ne j
i=j时,
∂
y
i
∂
x
j
=
−
e
x
p
(
x
i
)
e
x
p
(
x
j
)
(
∑
k
e
x
p
(
x
k
)
)
2
=
−
y
i
⋅
y
j
\begin{aligned} \frac{\partial y_i}{\partial x_j}&=\frac{-exp(x_i)exp(x_j)}{(\sum_k exp(x_k))^2} \\ & =-y_i\cdot y_j \end{aligned}
∂xj∂yi=(∑kexp(xk))2−exp(xi)exp(xj)=−yi⋅yj
综上:
∂
y
i
∂
x
j
=
{
y
i
−
y
i
2
,
i
=
j
−
y
i
⋅
y
j
,
i
≠
j
\frac{\partial y_i}{\partial x_j}=\left\{ \begin{aligned} & y_i-y_i^2,i=j \\ & -y_i\cdot y_j,i\ne j \end{aligned} \right.
∂xj∂yi={yi−yi2,i=j−yi⋅yj,i=j
实际应用中将前向输出
y
y
y保存起来,这样反向时就可以直接用,避免重复计算。
激活函数层
以Relu 为例,其前向推断公式:
y
=
{
x
,
x
>
0
0
,
x
≤
0
y=\left\{ \begin{aligned} & x,x>0 \\ & 0,x\le 0 \end{aligned} \right.
y={x,x>00,x≤0
求导公式为
∂
y
∂
x
=
{
1
,
y
>
0
0
,
y
≤
0
\frac{\partial y}{\partial x}=\left\{ \begin{aligned} & 1,y>0 \\ & 0,y\le 0 \end{aligned} \right.
∂x∂y={1,y>00,y≤0
由于反向传播需要根据y的大小判断导数,所以仍需保存
y
y
y。
全连接层
在前向过程中,设输入矩阵
X
X
X维度为
(
b
×
c
1
)
(b\times c_1)
(b×c1),输出矩阵
Y
Y
Y维度为
(
b
×
c
2
)
(b\times c_2)
(b×c2), 权重矩阵
W
W
W 维度为
(
c
1
×
c
2
)
(c_1\times c_2)
(c1×c2),偏置矩阵维度为
(
c
2
)
(c_2)
(c2),其中
b
b
b表示batch,
c
1
c_1
c1表示输入神经元个数,
c
2
c_2
c2表示输出神经元个数。则前向传播公式为
Y
=
X
⋅
W
+
b
Y=X\cdot W+b
Y=X⋅W+b
在反向传播过程中,假设已经获得前一层的梯度
d
Y
dY
dY,维度和
Y
Y
Y一样为
(
b
×
c
2
)
(b\times c_2)
(b×c2),则根据矩阵求导公式,依次可获得:
d
X
=
d
Y
⋅
W
T
dX=dY\cdot W^T
dX=dY⋅WT
d
W
=
X
T
⋅
d
Y
dW=X^T\cdot dY
dW=XT⋅dY
d
b
=
1
T
⋅
d
Y
db=1^T\cdot dY
db=1T⋅dY
其中
d
X
dX
dX传播到前一层网络,
d
W
dW
dW和
d
b
db
db用于更新权重。可以发现更新梯度时需要保存
X
X
X
池化层
最常用的池化操作包括最大池化和平均池化。平均池化可以看作是一种特殊的卷积,其权值固定且与核大小有关,而卷积将在下面介绍,故不赘述。这将介绍最大池化。
最大池化将一块区域内的最大值作为输出,其实也可以看作一种卷积,只不过卷积核的权重是由输入的统计量决定的,即最大的输入对应的权重为1,其余对应的权重为0。
在训练时需要记录最大值在输入特征图中的索引,以便在反向传播时将梯度恢复到对应位置。非最大值处梯度为0。