反向传播算法是神经网络中的经典算法,算法本身并不复杂,通过理解反向传播能够更深入的理解神经网络的工作方式。本文从一个化简 ∂ C ∂ w \frac{\partial C}{\partial w} ∂w∂C微分方程的思路,循序渐进地引出反向传播算法公式,注意这不是十分严格的数学推导。
当使用梯度下降法时,我们需要计算 ∂ C ∂ w \frac{\partial C}{\partial w} ∂w∂C,再根据
w = w − η ∂ C ∂ w (1) w=w-\mathrm{\eta}\frac{\partial C}{\partial w}\tag{1} w=w−η∂w∂C(1)
更新权重,其中 η \mathrm{\eta} η为学习率。
而在反向传播算法中,更新 ∂ C ∂ w \frac{\partial C}{\partial w} ∂w∂C的计算复杂度为O(n),可以通过一次正向传播和一次反向传播更新全部权重。
这里推荐《深度学习之美》,在众多的资源中,我认为其是形象基础的,本文也多受其启发。
符号介绍
因为众多的文章书籍并没有统一的符号规范,这里先对本文使用的符号进行规范,以免发生混淆:
符号 | 意义 |
---|---|
L L L | 表示网络的总层数 |
𝑤 𝑗 , 𝑘 𝑙 𝑤_{𝑗,𝑘}^{𝑙} wj,kl | 表示第l-1层第k个神经元到第l层第j个神经元的权重 w w w |
b 𝑗 𝑙 b_{𝑗}^{𝑙} bjl | 表示第l层第j个神经元的偏置 b b b |
a 𝑗 𝑙 a_{𝑗}^{𝑙} ajl | 表示第l层第j个神经元的激活值 a a a |
z j l = 𝑤 𝑗 𝑙 a 𝑙 − 1 + b 𝑗 𝑙 z_{j}^{l}=𝑤_{𝑗}^{𝑙}a^{𝑙-1}+b_{𝑗}^{𝑙} zjl=wjlal−1+bjl | 表示第l层第j个神经元的带权输入 z z z |
a 𝑗 𝑙 = σ ( z j l ) a_{𝑗}^{𝑙}=\sigma(z_{j}^{l}) ajl=σ(zjl) | σ \sigma σ表示sigmiod激活函数 |
C C C | 代价函数 |
拆解直接计算
本文以如下图的一个多层感知机(MLP)为例,为了使公式更加简洁,我们省略偏置和激活函数。
正向传播
我们首先需要回顾一下正向传播的过程,对于本文网络,最后一层的神经元的激活值为:
a 4 = 𝑤 4 ⋅ ( 𝑤 3 ⋅ ( 𝑤 2 ⋅ a 1 ) ) (2) a^{4}=𝑤^{4}\cdot(𝑤^{3}\cdot(𝑤^{2}\cdot a^{1}))\tag{2} a4=w4⋅(w3⋅(w2⋅a1))(2)
其中 𝑤 4 𝑤^{4} w4, 𝑤 3 𝑤^{3} w3, 𝑤 2 𝑤^{2} w2分别为3-4层、2-3层、1-2层的权重矩阵(再次提醒已忽略偏置和激活函数)。以 𝑤 3 𝑤^{3} w3为例,其矩阵为:
𝑤 3 = [ 𝑤 1 , 1 3 𝑤 1 , 2 3 𝑤 2 , 1 3 𝑤 2 , 2 3 ] (3) 𝑤^{3}= \left[ \begin{matrix} 𝑤_{1,1}^{3} & 𝑤_{1,2}^{3} \\ 𝑤_{2,1}^{3} & 𝑤_{2,2}^{3} \\ \end{matrix} \right] \tag{3} w3=[w1,13w2,13w1,23w2,23](3)
当使用均方误差作为代价函数时:
C = 1 2 ∣ ∣ y − a 1 4 ∣ ∣ 2 (4) C=\frac{1}{2}||y-a_{1}^{4}||^{2}\tag{4} C=21∣∣y−a14∣∣2(4)
可以看到其本质就是一个复合函数。
直接计算梯度
在公式(2)中,矩阵乘法可以写为线性方程组,因此代价函数可表示为:
C = f ( 𝑤 1 , 1 1 , 𝑤 1 , 2 1 , . . . , 𝑤 1 , 2 4 , 𝑤 2 , 2 4 ) (5) C=f(𝑤_{1,1}^{1},𝑤_{1,2}^{1},...,𝑤_{1,2}^{4},𝑤_{2,2}^{4})\tag{5} C=f(w1,11,w1,21,...,w1,24,w2,24)(5)
即 C C C可以表示为自变量只包括各权重的函数,因此最简单的办法是将其公式全部分解再计算。很显然当网络较大时,这种办法是不可行的。本节的目的主要是为了熟悉正向传播过程。
使用链式法则计算梯度
复合函数求导
在大学高数微积分中针对复合函数可以使用链式法则快速求解,有时也可以利用中间变量方便求导。
其基本公式为:
∂ z ∂ x = ∂ z ∂ t ⋅ ∂ t ∂ x (6) \frac{\partial z}{\partial x}=\frac{\partial z}{\partial t}\cdot\frac{\partial t}{\partial x}\tag{6} ∂x∂z=∂t∂z⋅∂x∂t(6)
我们可以使用该方法计算出:
∂ C ∂ 𝑤 1 , 1 4 = ∂ C ∂ a 1 4 ∂ a 1 4 ∂ 𝑤 1 , 1 4 (7) \frac{\partial C}{\partial 𝑤_{1,1}^{4}}=\frac{\partial C}{\partial a_{1}^{4}}\frac{\partial a_{1}^{4}}{\partial 𝑤_{1,1}^{4}}\tag{7} ∂w1,14∂C=∂a14∂C∂w1,14∂a14(7)
∂ C ∂ 𝑤 1 , 1 3 = ∂ C ∂ a 1 4 ∂ a 1 4 ∂ a 1 3 ∂ a 1 3 ∂ 𝑤 1 , 1 3 (8) \frac{\partial C}{\partial 𝑤_{1,1}^{3}}=\frac{\partial C}{\partial a_{1}^{4}}\frac{\partial a_{1}^{4}}{\partial a_{1}^{3}}\frac{\partial a_{1}^{3}}{\partial 𝑤_{1,1}^{3}}\tag{8} ∂w1,13∂C=∂a14∂C∂a13∂a14∂w1,13∂a13(8)
∂ C ∂ 𝑤 2 , 1 3 = ∂ C ∂ a 1 4 ∂ a 1 4 ∂ a 2 3 ∂ a 2 3 ∂ 𝑤 1 , 1 3 (9) \frac{\partial C}{\partial 𝑤_{2,1}^{3}}=\frac{\partial C}{\partial a_{1}^{4}}\frac{\partial a_{1}^{4}}{\partial a_{2}^{3}}\frac{\partial a_{2}^{3}}{\partial 𝑤_{1,1}^{3}}\tag{9} ∂w2,13∂C=∂a14∂C∂a23∂a14∂w1,13∂a23(9)
∂ C ∂ 𝑤 1 , 2 3 = ∂ C ∂ a 1 4 ∂ a 1 4 ∂ a 1 3 ∂ a 1 3 ∂ 𝑤 1 , 2 3 (10) \frac{\partial C}{\partial 𝑤_{1,2}^{3}}=\frac{\partial C}{\partial a_{1}^{4}}\frac{\partial a_{1}^{4}}{\partial a_{1}^{3}}\frac{\partial a_{1}^{3}}{\partial 𝑤_{1,2}^{3}}\tag{10} ∂w1,23∂C=∂a14∂C∂a13∂a14∂w1,23∂a13(10)
这使得我们不用将公式(2)全部分解为公式(5)也能计算部分梯度。
链式法则
然而有的时候选择合适的一个 t t t是很难的,因为往往微分不是“单链的”,比如计算 ∂ C ∂ 𝑤 1 , 1 2 \frac{\partial C}{\partial 𝑤_{1,1}^{2}} ∂w1,12∂C:
∂ C ∂ 𝑤 1 , 1 2 = ∂ C ∂ a 1 4 ∂ a 1 4 ∂ z 1 4 . . . ∂ z 1 4 ∂ 𝑤 1 , 1 2 (11) \frac{\partial C}{\partial 𝑤_{1,1}^{2}}=\frac{\partial C}{\partial a_{1}^{4}}\frac{\partial a_{1}^{4}}{\partial z_{1}^{4}}...\frac{\partial z_{1}^{4}}{\partial 𝑤_{1,1}^{2}}\tag{11} ∂w1,12∂C=∂a14∂C∂z14∂a14...∂w1,12∂z14(11)
公式中的 . . . ... ...该如何填写?这里我们需要扩充复合函数求导,本节主要摘选自Christopher Olah的blog。
对于:
c = a + b d = b + 1 e = c × d (11) c=a+b\\ d=b+1\\ e=c\times d\\\tag{11} c=a+bd=b+1e=c×d(11)
我们可以生成如下图的图形化表示,该图称为计算图(Computational Graphs)。
对于求解 ∂ e ∂ a \frac{\partial e}{\partial a} ∂a∂e,我们可以看到a只通过影响c最终影响e的结果,即只有一条a->c->e一条路径。因此:
∂ e ∂ a = ∂ e ∂ c ∂ c ∂ a \frac{\partial e}{\partial a}=\frac{\partial e}{\partial c}\frac{\partial c}{\partial a} ∂a∂e=∂c∂e∂a∂c
使用“影响”这个词可能显得并不专业且较为抽象。
对于求解 ∂ e ∂ b \frac{\partial e}{\partial b} ∂b∂e,我们可以看到b通过影响c和d两条路径最终影响e的结果,即包括b->c->e、b->d->e两条路径,并不是“单链的”,因此:
∂ e ∂ b = ∂ c d ∂ b = d ∂ c ∂ b + c ∂ d ∂ b = ∂ e ∂ c ∂ c ∂ b + ∂ e ∂ d ∂ d ∂ b \frac{\partial e}{\partial b}=\frac{\partial cd}{\partial b}=d\frac{\partial c}{\partial b}+c\frac{\partial d}{\partial b}=\frac{\partial e}{\partial c}\frac{\partial c}{\partial b}+\frac{\partial e}{\partial d}\frac{\partial d}{\partial b} ∂b∂e=∂b∂cd=d∂b∂c+c∂b∂d=∂c∂e∂b∂c+∂d∂e∂b∂d
我们可以将此求微分的方法总结为同一条路径的节点相乘,最后将所有的路径相加。
注意结点之间相乘是因为复合函数求导公式(6),当使用中间变量时需要使用乘法。所有路径相加是依据全微分公式,当有多个中间变量时需要使用加法。
路径的加法和乘法与公式(11)中各子式中的运算符号是无关的,公式中的加法和乘法只影响如
∂
e
∂
c
\frac{\partial e}{\partial c}
∂c∂e、
∂
c
∂
a
\frac{\partial c}{\partial a}
∂a∂c的求解,请注意区分。
使用链式法则计算梯度
根据链式法则我们现在可以求出 ∂ C ∂ 𝑤 1 , 1 2 \frac{\partial C}{\partial 𝑤_{1,1}^{2}} ∂w1,12∂C,可以看到 𝑤 1 , 1 2 𝑤_{1,1}^{2} w1,12有 a 1 2 a_{1}^{2} a12-> a 1 3 a_{1}^{3} a13-> a 1 4 a_{1}^{4} a14和 a 1 2 a_{1}^{2} a12-> a 2 3 a_{2}^{3} a23-> a 1 4 a_{1}^{4} a14两条路径,因此:
∂ C ∂ 𝑤 1 , 1 2 = ∂ C ∂ a 1 4 ∂ a 1 4 ∂ a 1 3 ∂ a 1 3 ∂ a 1 2 ∂ a 1 2 ∂ 𝑤 1 , 1 2 + ∂ C ∂ a 1 4 ∂ a 1 4 ∂ a 2 3 ∂ a 2 3 ∂ a 1 2 ∂ a 1 2 ∂ 𝑤 1 , 1 2 = ( ∂ C ∂ a 1 4 ∂ a 1 4 ∂ a 1 3 ∂ a 1 3 ∂ a 1 2 + ∂ C ∂ a 1 4 ∂ a 1 4 ∂ a 2 3 ∂ a 2 3 ∂ a 1 2 ) ∂ a 1 2 ∂ 𝑤 1 , 1 2 (12) \frac{\partial C}{\partial 𝑤_{1,1}^{2}}= \frac{\partial C}{\partial a_{1}^{4}}\frac{\partial a_{1}^{4}}{\partial a_{1}^{3}}\frac{\partial a_{1}^{3}}{\partial a_{1}^{2}}\frac{\partial a_{1}^{2}}{\partial 𝑤_{1,1}^{2}}+ \frac{\partial C}{\partial a_{1}^{4}}\frac{\partial a_{1}^{4}}{\partial a_{2}^{3}}\frac{\partial a_{2}^{3}}{\partial a_{1}^{2}}\frac{\partial a_{1}^{2}}{\partial 𝑤_{1,1}^{2}}\\ =(\frac{\partial C}{\partial a_{1}^{4}}\frac{\partial a_{1}^{4}}{\partial a_{1}^{3}}\frac{\partial a_{1}^{3}}{\partial a_{1}^{2}}+\frac{\partial C}{\partial a_{1}^{4}}\frac{\partial a_{1}^{4}}{\partial a_{2}^{3}}\frac{\partial a_{2}^{3}}{\partial a_{1}^{2}})\frac{\partial a_{1}^{2}}{\partial 𝑤_{1,1}^{2}}\tag{12} ∂w1,12∂C=∂a14∂C∂a13∂a14∂a12∂a13∂w1,12∂a12+∂a14∂C∂a23∂a14∂a12∂a23∂w1,12∂a12=(∂a14∂C∂a13∂a14∂a12∂a13+∂a14∂C∂a23∂a14∂a12∂a23)∂w1,12∂a12(12)
反向传播二次简化梯度计算
到现在我们已经从简单粗暴的拆解直接计算,到使用链式法则简化计算。这距离反向传播只剩一步之遥了。
链式法则的问题
通过对比公式(7)、(8)、(9)、(10)、(11)我们可以发现,其中均有 ∂ C ∂ a 1 4 \frac{\partial C}{\partial a_{1}^{4}} ∂a14∂C一项,对比(8)、(10)、(11),其中均有 ∂ C ∂ a 1 4 ∂ a 1 4 ∂ a 1 3 \frac{\partial C}{\partial a_{1}^{4}}\frac{\partial a_{1}^{4}}{\partial a_{1}^{3}} ∂a14∂C∂a13∂a14一项,公式(11)甚至可以化简。如果你把全部梯度写出,你就能发现更多的重复项。反向传播算法的强大之一就是避免了这些重复计算。
引入误差
这里我们引入误差这一概念,我们规定神经元的误差为(这里我们仍然忽略偏置和激活函数):
δ j l = ∂ C ∂ a j l (13) \delta_{j}^{l}=\frac{\partial C}{\partial a_{j}^{l}}\tag{13} δjl=∂ajl∂C(13)
可得:
∂ C ∂ 𝑤 j , k l = ∂ C ∂ a j l ∂ a j l ∂ 𝑤 j , k l = δ j l ∂ a j l ∂ 𝑤 j , k l (14) \frac{\partial C}{\partial 𝑤_{j,k}^{l}}=\frac{\partial C}{\partial a_{j}^{l}}\frac{\partial a_{j}^{l}}{\partial 𝑤_{j,k}^{l}}=\delta_{j}^{l}\frac{\partial a_{j}^{l}}{\partial 𝑤_{j,k}^{l}}\tag{14} ∂wj,kl∂C=∂ajl∂C∂wj,kl∂ajl=δjl∂wj,kl∂ajl(14)
即我们可以把对 ∂ C ∂ 𝑤 j , k l \frac{\partial C}{\partial 𝑤_{j,k}^{l}} ∂wj,kl∂C的求解转化为对 δ j l \delta_{j}^{l} δjl的求解。那我们该如何求出所有 δ j l \delta_{j}^{l} δjl呢?我们先回到之前介绍的例子中。
首先,在神经网络中,根据 a j l = ∑ k w j , k l ⋅ a k l − 1 a_{j}^{l}=\sum_{k}w_{j,k}^{l}\cdot a_{k}^{l-1} ajl=∑kwj,kl⋅akl−1可得:
∂ a j l ∂ a k l − 1 = 𝑤 𝑗 , 𝑘 𝑙 (15) \frac{\partial a_{j}^{l}}{\partial a_{k}^{l-1}}=𝑤_{𝑗,𝑘}^{𝑙}\tag{15} ∂akl−1∂ajl=wj,kl(15)
从公式(7)中可得:
δ 1 4 = ∂ C ∂ a 1 4 (16) \delta_{1}^{4}=\frac{\partial C}{\partial a_{1}^{4}}\tag{16} δ14=∂a14∂C(16)
从公式(8)中可得:
δ 1 3 = ∂ C ∂ a 1 4 ∂ a 1 4 ∂ a 1 3 = δ 1 4 ∂ a 1 4 ∂ a 1 3 = δ 1 4 w 1 , 1 4 (17) \delta_{1}^{3}=\frac{\partial C}{\partial a_{1}^{4}}\frac{\partial a_{1}^{4}}{\partial a_{1}^{3}}=\delta_{1}^{4}\frac{\partial a_{1}^{4}}{\partial a_{1}^{3}}=\delta_{1}^{4}w_{1,1}^{4}\tag{17} δ13=∂a14∂C∂a13∂a14=δ14∂a13∂a14=δ14w1,14(17)
从公式(12)中可得:
δ 1 2 = ( ∂ C ∂ a 1 4 ∂ a 1 4 ∂ a 1 3 ) ∂ a 1 3 ∂ a 1 2 + ( ∂ C ∂ a 1 4 ∂ a 1 4 ∂ a 2 3 ) ∂ a 2 3 ∂ a 1 2 = δ 1 3 ∂ a 1 3 ∂ a 1 2 + δ 2 3 ∂ a 2 3 ∂ a 1 2 = δ 1 3 w 1 , 1 3 + δ 2 3 w 2 , 1 3 (18) \delta_{1}^{2}=(\frac{\partial C}{\partial a_{1}^{4}}\frac{\partial a_{1}^{4}}{\partial a_{1}^{3}})\frac{\partial a_{1}^{3}}{\partial a_{1}^{2}}+(\frac{\partial C}{\partial a_{1}^{4}}\frac{\partial a_{1}^{4}}{\partial a_{2}^{3}})\frac{\partial a_{2}^{3}}{\partial a_{1}^{2}}=\delta_{1}^{3}\frac{\partial a_{1}^{3}}{\partial a_{1}^{2}}+\delta_{2}^{3}\frac{\partial a_{2}^{3}}{\partial a_{1}^{2}} =\delta_{1}^{3}w_{1,1}^{3}+\delta_{2}^{3}w_{2,1}^{3}\tag{18} δ12=(∂a14∂C∂a13∂a14)∂a12∂a13+(∂a14∂C∂a23∂a14)∂a12∂a23=δ13∂a12∂a13+δ23∂a12∂a23=δ13w1,13+δ23w2,13(18)
我们可以粗略的归纳总结为,第l层的 δ l \delta^{l} δl都可以从第 l + 1 l+1 l+1层的 δ l + 1 \delta^{l+1} δl+1求得。因此我们可以从最后一层开始,从后往前求得所有 δ j l \delta_{j}^{l} δjl再最终求得 ∂ C ∂ 𝑤 j , k l \frac{\partial C}{\partial 𝑤_{j,k}^{l}} ∂wj,kl∂C,这便是反向传播算法的大致求解过程。
矩阵表示
我们对公式(18)拓展为矩阵表示
[ δ 1 2 δ 2 2 ] = [ ∂ a 1 3 ∂ a 1 2 ∂ a 2 3 ∂ a 1 2 ∂ a 1 3 ∂ a 2 2 ∂ a 2 3 ∂ a 2 2 ] [ δ 1 3 δ 2 3 ] = [ w 1 , 1 3 w 2 , 1 3 w 1 , 2 3 w 2 , 2 3 ] [ δ 1 3 δ 2 3 ] (19) \left[\begin{matrix}\delta_{1}^{2} \\\delta_{2}^{2} \\\end{matrix}\right] =\left[\begin{matrix}\frac{\partial a_{1}^{3}}{\partial a_{1}^{2}} &\frac{\partial a_{2}^{3}}{\partial a_{1}^{2}}\\\frac{\partial a_{1}^{3}}{\partial a_{2}^{2}} &\frac{\partial a_{2}^{3}}{\partial a_{2}^{2}}\\\end{matrix}\right]\left[\begin{matrix}\delta_{1}^{3} \\\delta_{2}^{3} \\\end{matrix}\right] =\left[\begin{matrix}w_{1,1}^{3} &w_{2,1}^{3}\\w_{1,2}^{3} &w_{2,2}^{3}\\\end{matrix}\right]\left[\begin{matrix}\delta_{1}^{3} \\\delta_{2}^{3} \\\end{matrix}\right]\tag{19} [δ12δ22]=⎣⎡∂a12∂a13∂a22∂a13∂a12∂a23∂a22∂a23⎦⎤[δ13δ23]=[w1,13w1,23w2,13w2,23][δ13δ23](19)
公式19中的2*2矩阵可以理解为向量
a
2
a^{2}
a2对向量
a
3
a^{3}
a3的一阶偏导,即雅可比矩阵的转置。因此只要计算每一层对应的雅可比矩阵(对于MLP来说,雅可比矩阵为每层的权重系数矩阵)。便可以使用矩阵快速计算每层误差
δ
j
l
\delta_{j}^{l}
δjl。
公式19可简化为:
δ 2 = ( w 3 ) T ⋅ δ 3 (20) \delta^{2}=(w^{3})^{T}\cdot\delta^{3}\tag{20} δ2=(w3)T⋅δ3(20)
反向传播算法介绍
这里我们加入偏置和激活函数,给出完整的反向传播算法(考虑偏置和激活函数,但未考虑正则项),该算法包括以下四个公式,摘自《Neural Networks and Deep Learning》:
δ L = ∇ a C ⊙ σ ′ ( z L ) (BP1) \delta^{L}=\nabla_{a}C\odot\sigma'(z^{L})\tag{BP1} δL=∇aC⊙σ′(zL)(BP1)
δ l = ( ( w l + 1 ) T δ l + 1 ) ⊙ σ ′ ( z l ) (BP2) \delta^{l}=((w^{l+1})^{T}\delta^{l+1})\odot\sigma'(z^{l})\tag{BP2} δl=((wl+1)Tδl+1)⊙σ′(zl)(BP2)
∂ C ∂ b j l = δ j l (BP3) \frac{\partial C}{\partial b_{j}^{l}}=\delta_{j}^{l}\tag{BP3} ∂bjl∂C=δjl(BP3)
∂ C ∂ 𝑤 j , k l = a k l − 1 δ j l (BP4) \frac{\partial C}{\partial 𝑤_{j,k}^{l}}=a_{k}^{l-1}\delta_{j}^{l}\tag{BP4} ∂wj,kl∂C=akl−1δjl(BP4)
BP1和BP2中涉及到向量的计算,其中 ⊙ \odot ⊙表示哈达玛积。 ∇ a C \nabla_{a}C ∇aC表示输出 a a a对损失 C C C的梯度。 σ ′ \sigma' σ′表示对激活函数求偏导。
反向传播算法的实现即首先计算BP1获得最后一层误差 δ L \delta^{L} δL,接下来从后往前根据BP2依次求出各层的 δ l \delta^{l} δl,最后根据公式BP3和BP4求出各层偏置和权重的梯度。
以下给出BP1和BP2两个公式的标量表示,便于理解:
δ j L = ∂ C ∂ a j L ∂ a j L ∂ z j L (BP1-2) \delta_{j}^{L}=\frac{\partial C}{\partial a_{j}^{L}}\frac{\partial a_{j}^{L}}{\partial z_{j}^{L}}\tag{BP1-2} δjL=∂ajL∂C∂zjL∂ajL(BP1-2)
δ j l = ∑ q ( w q , j l + 1 × δ q l + 1 ) ∂ a j l ∂ z j l (BP2-2) \delta_{j}^{l}=\sum_{q}(w_{q,j}^{l+1}\times\delta_{q}^{l+1})\frac{\partial a_{j}^{l}}{\partial z_{j}^{l}}\tag{BP2-2} δjl=q∑(wq,jl+1×δql+1)∂zjl∂ajl(BP2-2)
公式BP2-2中 q q q表示 l + 1 l+1 l+1层的 q q q个神经元。
总结
从链式法则到链式法则再到BP算法,可能这种理解方式如Michael Nielsen在《Neural Networks and Deep Learning》中所写是比较“无趣的”。但是翻阅网络上的资料,不是过于抽象就是过于简陋,相比之下,这种启发式的理解,往往更深刻。