反向传播算法及其梯度扩散
前言
最近开始认真学习了下反向传播算法和梯度传递的问题,其本质是导数的链式法则的应用,由此可以分析出为什么sigmoid**函数不适合用于做多层网络的**函数,可以考虑联系我的另一篇关于**函数的文章。如有谬误,请联系指正。转载请注明出处。
联系方式:
e-mail: [email protected]
QQ: 973926198
github: https://github.com/FesianXu
完整代码开源: click me || 其中的sigmoid_base_BP.py
神经网络
要知道什么是反向传播算法,我们还是要从神经网络开始将起。神经网络如图所示。

图中所示的是一个具有一个输入层(input layer),一个隐藏层(hidden layer),一个输出层(output layer)的三层神经网络。我们都知道,在神经网络的训练过程中,其权值是通过梯度的变化大小来更新的,我们这里先进行符号规定,以便于接下来的分析。
wjkl 是l-1层的第k个神经元与l层的第j个神经元的连接权值
bjl 是l层的第j个神经元的偏置。
zjl 是l层的第j神经元的输入。
ajl 是l层的第j神经元的**输出。
用公式表达即是:
zjl=k∑(wjkl∗akl−1+bjl)(1.1)
ajl=σ(zjl)=σ(k∑(wjkl∗akl−1+bjl))(1.2)
其中的σ(x)为**函数。多采用sigmoid,ReLU,tanh等。
C=2n1∗∑x∣∣y−aL∣∣2 代价函数,其中L是神经网络的层数。
我们知道,进行权值更新的时候,我们采用的是梯度下降法更新(Gradient Descent), 公式如下:
wjkl:=wjkl−η∗∂wjkl∂C(1.3)
这里最重要的便是需要求得∂wjkl∂C,为了求得这个导数,我们现在有几个公式需要推导,这些公式大多都有链式法则推导而出。
δL=∇aC⨀σ′(zL) (对L层的误差)
其中我们要注意的是,对于某层的误差δl定义为δl=∂zl∂C,其中具体到某一个神经元j的误差为δjl=∂zjl∂C。
推导:
δjL=∂zjL∂C=∂ajL∂C∗∂zjL∂ajL=∂ajL∂C∗σ′(zjL)(2.1)
所以当扩展到对于所有的第L层的神经元时,我们为了方便用一个矩阵去代表我们的结果:
δL=(δ1Lδ2L)(2.2)
需要注意的是,所有的误差矩阵都可以这样定义,如:
δl=(δ1l,δ2l,⋯,δnl)T(2.3)
其中n是l层神经元的数量,类似的,可以得出:
σ′(zl)=(σ′(z1l),σ′(z2l),⋯,σ′(znl))(2.4)
其中n是第l层的神经元数量
由此可以得出结论:
δL=∇aC⨀σ′(zL)(2.5)
其中,∇(⋅)算子代表了梯度,具体为∇xf(x)代表f(x)对x的所有偏导数的矩阵,类似于:
∇xf(x)=(∂x1∂f(x),∂x2∂f(x),⋯,∂xn∂f(x)),x∈Rn(2.6)
而⨀是点乘,表示了两个操作数的各个元素的分别相乘,前提是两个操作数的维度统一。
δjl=∑k(δkl+1∗wkjl+1∗σ′(zjl)) 第l层第j个神经元的误差
δjl=∂zjl∂C=k∑∂zkl+1∂C∗∂ajl∂zkl+1∗∂zjl∂ajl=k∑δkl+1∗∂ajl∂(wkjl+1∗ajl+bkl+1)∗σ′(zjl)=k∑(δkl+1∗wkjl+1∗σ′(zjl))(3.1)
同样的,为了表示方便,也多用矩阵形式表示,有:
δ1l=δ1l+1∗w11l+1∗σ′(z1l)+δ2l+1∗w21l+1∗σ′(z1l)(3.2)
δ2l=δ1l+1∗w12l+1∗σ′(z2l)+δ2l+1∗w22l+1∗σ′(z2l)(3.3)
δ3l=δ1l+1∗w13l+1∗σ′(z3l)+δ2l+1∗w23l+1∗σ′(z3l)(3.4)
δ4l=δ1l+1∗w14l+1∗σ′(z4l)+δ2l+1∗w24l+1∗σ′(z4l)(3.5)
Wl+1=(w11l+1w21l+1w12l+1w22l+1w13l+1w23l+1w14l+1w24l+1)(3.6)
所以,有:
δl=((Wl+1)T∗δl+1)⨀σ′(zl)(3.7)
∂wjkl∂C=akl−1∗δjl 误差具体到对某个边权重的偏导数
∂wjkl∂C=∂zjl∂C∗∂wjkl∂zjl=akl−1∗δjl=akl−1∗k∑(δkl+1∗wkjl+1∗σ′(zjl))(4.1)
由此可以看出,∂wjkl∂C与σ′(zjl)呈正相关的关系,当**函数采用了sigmoid函数时,由于x越大,其导数呈现指数衰减,所以在层数太大而且输出值范围太大的时候,∂wjkl∂C就会变得很小,从而使得参数的更新速率变得很慢,因此会出现梯度消散的问题(The problem of gradient vanishing)。
此时,可以考虑替换代价函数或者**函数,对于更换**函数,可以更换为ReLU(Rectified Linear Units)函数,ReLU=max(0,x)其导数为分段导数,在**区x>0时,其导数恒为1,不会存在梯度消散的问题。
∂bjl∂C=δjl 误差对偏置的导数
∂bjl∂C=∂zjl∂C∗∂bjl∂zjl=δjl∗1=δjl(5.1)
总的更新公式
wl:=wl−η∗δl∗(al−1)T(6.1)
bl:=bl−η∗δl(6.2)
我们在这篇文章中推导了BP算法的公式,我们接下来将在下一篇文章《基于numpy和python的反向传播算法的实现与分析》中利用numpy和python实现BP算法,有兴趣的朋友请移步。
引用
- 《基于numpy和python的反向传播算法的实现与分析》