误差反向传播法
数值微分的运算速度
如果使用中心差分法求梯度,对每个权重参数求导时就需要进行两次Loss函数的运算,而这涉及了数百上千个神经元的多次重复运算,所以使用数值微分方法求梯度的效率很低。
从求导的链式法则说起
求导的链式法则 (Chain Rule)是微积分中一个非常重要的法则,用于求解复合函数的导数。如果一个函数是由两个或更多函数复合而成的,那么这个函数的导数可以通过链式法则来计算。
假设我们有两个函数
f
f
f和
g
g
g,它们都是可导的。如果我们定义一个复合函数
h
(
x
)
=
f
(
g
(
x
)
)
h(x)=f(g(x))
h(x)=f(g(x)),那么
h
h
h的导数
h
′
(
x
)
h^{\prime}(x)
h′(x)可以通过以下链式法则求得
h
′
(
x
)
=
f
′
(
g
(
x
)
)
⋅
g
′
(
x
)
h'(x)=f'(g(x))\cdot g'(x)
h′(x)=f′(g(x))⋅g′(x)
这里的
f
′
(
g
(
x
)
)
f^{\prime}(g(x))
f′(g(x))是外函数
f
f
f在
g
(
x
)
g(x)
g(x)处的导数,而
g
′
(
x
)
g^{\prime}(x)
g′(x)是内函数
g
g
g在
x
x
x处的导数。
链式法则的直观理解是:当我们对复合函数求导时,我们首先对内函数
g
g
g求导,得到
g
′
(
x
)
g^{\prime}(x)
g′(x),这可以看作是“局部变化率”。然后,我们考虑外函数
f
f
f在
g
(
x
)
g(x)
g(x)处的导数
f
′
(
g
(
x
)
)
f^{\prime}(g(x))
f′(g(x)),这代表了
g
g
g的输出值每变化一个单位,
f
f
f的输出值会如何变化。链式法则告诉我们,复合函数的导数就是这两个变化率的乘积。链式法则可以扩展到多个函数的复合情况。如果有多个函数
f
,
g
,
h
,
…
f,g,h,\ldots
f,g,h,…复合成
k
(
x
)
=
k(x)=
k(x)=
f
(
g
(
h
(
…
(
x
)
)
)
)
f(g(h(\ldots(x))))
f(g(h(…(x)))),那么
k
k
k的导数
k
′
(
x
)
k^{\prime}(x)
k′(x)可以按照以下方式求得:
k
′
(
x
)
=
f
′
(
g
(
h
(
…
(
x
)
)
)
)
⋅
g
′
(
h
(
…
(
x
)
)
)
⋅
h
′
(
…
(
x
)
)
k'(x)=f'(g(h(\ldots(x))))\cdot g'(h(\ldots(x)))\cdot h'(\ldots(x))
k′(x)=f′(g(h(…(x))))⋅g′(h(…(x)))⋅h′(…(x))
这里,每个函数的导数都是针对它前面的函数的输出值来计算的。
使用计算图理解误差反向传播法
f f f是计算图中的一个计算节点,它将输入的 x x x进行转换为 y , y = f ( x ) y,y=f(x) y,y=f(x),这一步称为正向传播。反之,从计算节点右侧输入值 E E E,那么计算节点将输出将信号 E E E乘以该计算节点的局部导数 ∂ y ∂ x \frac{\partial y}{\partial x} ∂x∂y,这一操作称为反向传播。
如果反向输入的 E E E变化了 △ E \triangle E △E则反向传播计算结果则变化了 △ E ⋅ ∂ y ∂ x \triangle E \cdot \frac{\partial y}{\partial x} △E⋅∂x∂y
对于基本的运算过程:加减乘除
如图,对于加法节点,
z
=
x
+
y
z=x+y
z=x+y,由于
∂
z
∂
x
=
1
∂
z
∂
y
=
1
\begin{aligned}\frac{\partial z}{\partial x}&=1\\\\\frac{\partial z}{\partial y}&=1\end{aligned}
∂x∂z∂y∂z=1=1
反向输入值为
∂
L
∂
z
\frac{\partial L}{\partial z}
∂z∂L,那么输出到各个支路的值则为
∂
L
∂
z
⋅
1
\frac{\partial L}{\partial z}\cdot1
∂z∂L⋅1。
如图,对于乘法节点,
z
=
x
y
z=xy
z=xy,由于
∂
z
∂
x
=
y
∂
z
∂
y
=
x
\begin{aligned}\frac{\partial z}{\partial x}&=y\\\\\frac{\partial z}{\partial y}&=x\end{aligned}
∂x∂z∂y∂z=y=x
那么输出到各个支路的值则为
∂
L
∂
z
⋅
x
\frac{\partial L}{\partial z}\cdot x
∂z∂L⋅x,
∂
L
∂
z
⋅
y
\frac{\partial L}{\partial z}\cdot y
∂z∂L⋅y。
对于稍微复杂一点的计算过程
比如Affine层的计算图(矩阵乘法)
以矩阵为对象的反向传播, 按矩阵的各个元素进行计算时,步骤和以标量为对象的计算图相同。实际写一下的话,可以得到下式
∂
L
∂
X
=
∂
L
∂
Y
⋅
W
T
\frac{\partial L}{\partial X}=\frac{\partial L}{\partial Y}\cdot W^\mathrm{T}
∂X∂L=∂Y∂L⋅WT
∂
L
∂
W
=
X
T
⋅
∂
L
∂
Y
\frac{\partial L}{\partial\boldsymbol{W}}=\boldsymbol{X}^\mathrm{T}\cdot\frac{\partial L}{\partial\boldsymbol{Y}}
∂W∂L=XT⋅∂Y∂L
在实际计算中,需注意矩阵的形状, X X X和 ∂ L ∂ X \frac{\partial L}{\partial X} ∂X∂L形状相同, W W W和 ∂ L ∂ W \frac{\partial L}{\partial W} ∂W∂L形状相同。
比如sigmoid函数,
h
(
x
)
=
1
1
+
exp
(
−
x
)
h(x)=\frac{1}{1+\exp(-x)}
h(x)=1+exp(−x)1
它的计算图如下,包括了乘法,加法,除法以及指数函数
它的反向传播如下
- 右侧输入 ∂ L ∂ y \frac{\partial L}{\partial y} ∂y∂L
- “/”节点表示
y
=
1
x
y=\frac1x
y=x1,它的导数可以解析性地表示为下式。
∂ y ∂ x = − 1 x 2 = − y 2 \begin{aligned}\frac{\partial y}{\partial x}&=-\frac1{x^2}\\&=-y^2\end{aligned} ∂x∂y=−x21=−y2 - “exp”节点表示
y
=
exp
(
x
)
y=\exp(x)
y=exp(x),它的导数由下式表示。
∂ y ∂ x = exp ( x ) \frac{\partial y}{\partial x}=\exp(x) ∂x∂y=exp(x) - “×”节点将正向传播时的值翻转后做乘法运算。因此,这里要乘以−1。
最终,根据计算图的结果,我们获得了sigmoid函数反向传播的结果
∂ L ∂ y y 2 exp ( − x ) = ∂ L ∂ y 1 ( 1 + exp ( − x ) ) 2 exp ( − x ) = ∂ L ∂ y 1 1 + exp ( − x ) exp ( − x ) 1 + exp ( − x ) = ∂ L ∂ y y ( 1 − y ) \begin{aligned} \begin{aligned}\frac{\partial L}{\partial y}y^2\exp(-x)\end{aligned}& \begin{aligned}&=\frac{\partial L}{\partial y}\frac{1}{(1+\exp(-x))^2}\exp(-x)\end{aligned} \\ &=\frac{\partial L}{\partial y}\frac1{1+\exp(-x)}\frac{\exp(-x)}{1+\exp(-x)} \\ &=\frac{\partial L}{\partial y}y(1-y) \end{aligned} ∂y∂Ly2exp(−x)=∂y∂L(1+exp(−x))21exp(−x)=∂y∂L1+exp(−x)11+exp(−x)exp(−x)=∂y∂Ly(1−y)
y ( 1 − y ) = e − x ( 1 + e − x ) 2 y(1-y)=\frac{e^{-x}}{\left(1+e^{-x}\right)^2} y(1−y)=(1+e−x)2e−x即sigmoid函数的导数。
所以对于损失函数 L o s s = f ( w ) Loss = f(w) Loss=f(w), 可以根据反向传播计算结果为 F ( w ) F(w) F(w),求得损失函数对参数的梯度,相比于数值微分而言这大大简化了求梯度计算量。
其余参考书籍《深度学习入门——基于Python的理论与实现》