《深度学习系列》反向传播算法的公式推导

反向传播算法及其梯度扩散

前言

最近开始认真学习了下反向传播算法和梯度传递的问题,其本质是导数的链式法则的应用,由此可以分析出为什么sigmoid激活函数不适合用于做多层网络的激活函数,可以考虑联系我的另一篇关于激活函数的文章。如有谬误,请联系指正。转载请注明出处。
联系方式:
e-mail: FesianXu@163.com
QQ: 973926198
github: https://github.com/FesianXu
完整代码开源: click me || 其中的sigmoid_base_BP.py


神经网络

要知道什么是反向传播算法,我们还是要从神经网络开始将起。神经网络如图所示。
network

图中所示的是一个具有一个输入层(input layer),一个隐藏层(hidden layer),一个输出层(output layer)的三层神经网络。我们都知道,在神经网络的训练过程中,其权值是通过梯度的变化大小来更新的,我们这里先进行符号规定,以便于接下来的分析。
wjklw^l_{jk}l-1层的第k个神经元与l层的第j个神经元的连接权值

bjlb^l_{j}l层的第j个神经元的偏置。

zjlz^l_{j}l层的第j神经元的输入。

ajla^l_{j}l层的第j神经元的激活输出。

用公式表达即是:
(1.1)zjl=k(wjklakl1+bjl)z^l_{j} = \sum_{k} (w^l_{jk}*a^{l-1}_{k}+b^l_j) \tag{1.1}

(1.2)ajl=σ(zjl)=σ(k(wjklakl1+bjl))a^l_j = \sigma(z^l_j) = \sigma(\sum_k (w^l_{jk}*a^{l-1}_k+b^l_j) ) \tag{1.2}

其中的σ(x)\sigma(x)为激活函数。多采用sigmoid,ReLU,tanh等。
C=12nxyaL2C = \frac{1}{2n}*\sum_x||y-a^L||^2 代价函数,其中L是神经网络的层数。


我们知道,进行权值更新的时候,我们采用的是梯度下降法更新(Gradient Descent), 公式如下:
(1.3)wjkl:=wjklηCwjkl w^l_{jk} := w^l_{jk}-\eta*\frac{\partial{C}}{\partial{w^l_{jk}}} \tag{1.3}
这里最重要的便是需要求得Cwjkl\frac{\partial{C}}{\partial{w^l_{jk}}},为了求得这个导数,我们现在有几个公式需要推导,这些公式大多都有链式法则推导而出。


δL=aCσ(zL)\delta^L = \nabla_a{C}\bigodot \sigma^\prime(z^L) (对L层的误差)

其中我们要注意的是,对于某层的误差δl\delta^l定义为δl=Czl\delta^l = \frac{\partial{C}}{\partial{z^l}},其中具体到某一个神经元j的误差为δjl=Czjl\delta^l_j = \frac{\partial{C}}{\partial{z^l_j}}

推导:
(2.1)δjL=CzjL=CajLajLzjL=CajLσ(zjL) \delta^L_j = \frac{\partial{C}}{\partial{z^L_j}} = \frac{\partial{C}}{\partial{a^L_j}}*\frac{\partial{a^L_j}}{\partial{z^L_j}} = \frac{\partial{C}}{\partial{a^L_j}}*\sigma^\prime(z^L_j) \tag{2.1}

所以当扩展到对于所有的第L层的神经元时,我们为了方便用一个矩阵去代表我们的结果:
(2.2)δL=(δ1Lδ2L) \delta^L = \left(\begin{array}{c} \delta^L_1 \\ \delta^L_2 \end{array}\right) \tag{2.2}
需要注意的是,所有的误差矩阵都可以这样定义,如:

(2.3)δl=(δ1l,δ2l, ,δnl)T \delta^l = (\delta^l_1, \delta^l_2, \cdots,\delta^l_n)^T \tag{2.3}
其中n是l层神经元的数量,类似的,可以得出:

(2.4)σ(zl)=(σ(z1l),σ(z2l), ,σ(znl)) \sigma^\prime(z^l) = (\sigma^\prime(z^l_1),\sigma^\prime(z^l_2),\cdots,\sigma^\prime(z^l_n)) \tag{2.4}
其中n是第l层的神经元数量
由此可以得出结论:
(2.5)δL=aCσ(zL) \delta^L = \nabla_a{C}\bigodot \sigma^\prime(z^L) \tag{2.5}
其中,()\nabla(·)算子代表了梯度,具体为xf(x)\nabla_xf(x)代表f(x)f(x)xx的所有偏导数的矩阵,类似于:
(2.6)xf(x)=(f(x)x1,f(x)x2, ,f(x)xn),xRn \nabla_xf(x) = (\frac{\partial{f(x)}}{\partial{x_1}}, \frac{\partial{f(x)}}{\partial{x_2}}, \cdots, \frac{\partial{f(x)}}{\partial{x_n}}), x \in R^n \tag{2.6}
\bigodot点乘,表示了两个操作数的各个元素的分别相乘,前提是两个操作数的维度统一。


δjl=k(δkl+1wkjl+1σ(zjl))\delta^l_j = \sum_k(\delta^{l+1}_k*w^{l+1}_{kj}*\sigma^\prime(z^l_j)) 第l层第j个神经元的误差

(3.1)δjl=Czjl=kCzkl+1zkl+1ajlajlzjl=kδkl+1(wkjl+1ajl+bkl+1)ajlσ(zjl)=k(δkl+1wkjl+1σ(zjl)) \delta^l_j = \frac{\partial{C}}{\partial{z^l_j}} = \sum_k \frac{\partial C}{ \partial z^{l+1}_k} * \frac{ \partial{z^{l+1}_k} }{ \partial{a^l_j} } * \frac{ \partial{a^l_j} }{ \partial{z^l_j} } \\ = \sum_k \delta^{l+1}_k * \frac{ \partial({w^{l+1}_{kj}} * a^l_j+b^{l+1}_k )}{ \partial{a^l_j} } * \sigma^\prime(z^l_j) = \sum_k(\delta^{l+1}_k*w^{l+1}_{kj}*\sigma^\prime(z^l_j)) \tag{3.1}

同样的,为了表示方便,也多用矩阵形式表示,有:

(3.2)δ1l=δ1l+1w11l+1σ(z1l)+δ2l+1w21l+1σ(z1l) \delta^l_1 = \delta^{l+1}_1*w^{l+1}_{11}*\sigma^\prime(z^l_1)+ \delta^{l+1}_2*w^{l+1}_{21}*\sigma^\prime(z^l_1) \tag{3.2}

(3.3)δ2l=δ1l+1w12l+1σ(z2l)+δ2l+1w22l+1σ(z2l) \delta^l_2 = \delta^{l+1}_1*w^{l+1}_{12}*\sigma^\prime(z^l_2)+ \delta^{l+1}_2*w^{l+1}_{22}*\sigma^\prime(z^l_2) \tag{3.3}

(3.4)δ3l=δ1l+1w13l+1σ(z3l)+δ2l+1w23l+1σ(z3l) \delta^l_3 = \delta^{l+1}_1*w^{l+1}_{13}*\sigma^\prime(z^l_3)+ \delta^{l+1}_2*w^{l+1}_{23}*\sigma^\prime(z^l_3) \tag{3.4}

(3.5)δ4l=δ1l+1w14l+1σ(z4l)+δ2l+1w24l+1σ(z4l) \delta^l_4 = \delta^{l+1}_1*w^{l+1}_{14}*\sigma^\prime(z^l_4)+ \delta^{l+1}_2*w^{l+1}_{24}*\sigma^\prime(z^l_4) \tag{3.5}

(3.6)Wl+1=(w11l+1w12l+1w13l+1w14l+1w21l+1w22l+1w23l+1w24l+1) W^{l+1} = \left(\begin{array}{ccc} w^{l+1}_{11} & w^{l+1}_{12} & w^{l+1}_{13} & w^{l+1}_{14}\\ w^{l+1}_{21} & w^{l+1}_{22} & w^{l+1}_{23} & w^{l+1}_{24} \end{array}\right) \tag{3.6}

所以,有:
(3.7)δl=((Wl+1)Tδl+1)σ(zl) \delta^l = ((W^{l+1})^T * \delta^{l+1}) \bigodot \sigma^\prime(z^l) \tag{3.7}


Cwjkl=akl1δjl\frac{\partial{C}}{\partial{w^l_{jk}}} = a^{l-1}_k*\delta^l_j 误差具体到对某个边权重的偏导数

(4.1)Cwjkl=Czjlzjlwjkl=akl1δjl=akl1k(δkl+1wkjl+1σ(zjl)) \frac{\partial{C}}{\partial{w^l_{jk}}} = \frac{\partial{C}}{\partial{z^l_{j}}} * \frac{\partial{z^l_j}}{\partial{w^l_{jk}}} = a^{l-1}_k*\delta^l_j=a^{l-1}_k * \sum_k(\delta^{l+1}_k*w^{l+1}_{kj}*\sigma^\prime(z^l_j)) \tag{4.1}

由此可以看出,Cwjkl\frac{\partial{C}}{\partial{w^l_{jk}}}σ(zjl)\sigma^\prime(z^l_j)呈正相关的关系,当激活函数采用了sigmoid函数时,由于x越大,其导数呈现指数衰减,所以在层数太大而且输出值范围太大的时候,Cwjkl\frac{\partial{C}}{\partial{w^l_{jk}}}就会变得很小,从而使得参数的更新速率变得很慢,因此会出现梯度消散的问题(The problem of gradient vanishing)。
此时,可以考虑替换代价函数或者激活函数,对于更换激活函数,可以更换为ReLU(Rectified Linear Units)函数,ReLU=max(0,x)ReLU = max(0, x)其导数为分段导数,在激活区x>0x > 0时,其导数恒为1,不会存在梯度消散的问题。


Cbjl=δjl\frac{\partial{C}}{\partial{b^l_j}} = \delta^l_j 误差对偏置的导数

(5.1)Cbjl=Czjlzjlbjl=δjl1=δjl \frac{\partial{C}}{\partial{b^l_j}} = \frac{\partial{C}}{\partial{z^l_j}} * \frac{\partial{z^l_j}}{\partial{b^l_j}} = \delta^l_j*1 = \delta^l_j \tag{5.1}


总的更新公式

(6.1)wl:=wlηδl(al1)T w^l := w^l-\eta*\delta^l*(a^{l-1})^T \tag{6.1}

(6.2)bl:=blηδl b^l := b^l-\eta*\delta^l \tag{6.2}


我们在这篇文章中推导了BP算法的公式,我们接下来将在下一篇文章《基于numpy和python的反向传播算法的实现与分析》中利用numpy和python实现BP算法,有兴趣的朋友请移步。

引用

  1. 《基于numpy和python的反向传播算法的实现与分析》
posted @ 2017-09-26 10:38  FesianXu  阅读(180)  评论(0编辑  收藏  举报