天天看点

BP(反向传播)

    神经网络的反向传播算法,是基于SGD(梯度下降算法)的思想而来的,就是更新权重,一步步求解,所以也需要

损失函数的概念,利用误差求导的方法来改变权重,但是BP的效率在神经网络里面来看是比较高的。

以下内容转载自链接:https://blog.csdn.net/baozi__/article/details/78307479

计算过程

现在我们有这样一个神经网络: 

BP(反向传播)

输入层有两个神经元i1和i2,隐藏层有两个神经元h1和h2,偏差都为b1,输出层有两个神经元o1和o2,偏差都为b2,权重为w 

神经元的输入经过激活函数转变为输出,即带权输入net经过激活函数转变为输出激活值out,如图所示: 

BP(反向传播)

现在一步一步进行计算

前向传播

输入层 -> 隐藏层

  1. 计算隐藏层神经元h1与h2的带权输入: 

    neth1=ω1∗i1+ω2∗i2+b1neth1=ω1∗i1+ω2∗i2+b1

    neth2=ω3∗i1+ω4∗i2+b1neth2=ω3∗i1+ω4∗i2+b1

  2. 计算h1与h2的输出激活值(激活函数为sigmoid函数): 
    sigmoid函数:  S(x)=11+e−xS(x)=11+e−x

outh1=11+e−neth1outh1=11+e−neth1 outh2=11+e−neth2outh2=11+e−neth2

隐藏层 -> 输出层

  1. 计算输出层神经元o1与o2的带权输入: 

    neto1=ω5∗outh1+ω6∗outh2+b2neto1=ω5∗outh1+ω6∗outh2+b2

    neto2=ω7∗outh1+ω8∗outh2+b2neto2=ω7∗outh1+ω8∗outh2+b2

  2. 计算o1与o2的输出激活值: 

    outo1=11+e−neto1outo1=11+e−neto1

    outo2=11+e−neto2outo2=11+e−neto2

至此,我们就计算出了前向传播的输出,接下来进行反向传播

反向传播

计算误差(代价函数)

  1. 分别计算o1和o2的误差: 
    这里使用二次代价函数:E=12(target−output)2E=12(target−output)2

Eo1=12(targeto1−outputo1)2Eo1=12(targeto1−outputo1)2 Eo2=12(targeto2−outputo2)2Eo2=12(targeto2−outputo2)2 2. 计算总误差:

总误差为:Etotal=∑12(target−output)2Etotal=∑12(target−output)2

Etotal=Eo1+Eo2Etotal=Eo1+Eo2

权值更新

微分知识告诉我们,导数体现变化率,那么权值对于总误差的影响则体现在导数上 

要更新权值,就要计算总误差对权值的偏导数,即权值能对总误差产生多少影响,这里用到了链式法则

隐藏层 -> 输出层的权值更新
  1. 以w5为例: 

    ∂Etotal∂outo1∗∂outo1∂neto1∗∂neto1∂ω5=∂Etotal∂ω5∂Etotal∂outo1∗∂outo1∂neto1∗∂neto1∂ω5=∂Etotal∂ω5

    下图可以更直观的感受反向传播误差: 

    BP(反向传播)
  2. 分别计算等号左边的三个式子:
    • ∂Etotal∂outo1∂Etotal∂outo1: 

      Etotal=12(targeto1−outputo1)2+12(targeto2−outputo2)2Etotal=12(targeto1−outputo1)2+12(targeto2−outputo2)2

      ∂Etotal∂outo1=−(targeto1−outputo1)∂Etotal∂outo1=−(targeto1−outputo1)

    • ∂outo1∂neto1∂outo1∂neto1(即对sigmoid函数求导): 

      outo1=11+e−neto1outo1=11+e−neto1

      ∂outo1∂neto1=outo1(1−outo1)∂outo1∂neto1=outo1(1−outo1)

    • ∂neto1∂ω5∂neto1∂ω5: 

      neto1=ω5∗outh1+ω6∗outh2+b2neto1=ω5∗outh1+ω6∗outh2+b2

      ∂neto1∂ω5=outh1∂neto1∂ω5=outh1

  3. 然后乘起来即可: 

    ∂Etotal∂ω5=−(targeto1−outputo1)∗outo1(1−outo1)∗outh1∂Etotal∂ω5=−(targeto1−outputo1)∗outo1(1−outo1)∗outh1

    现在我们得到了整体误差E(total)对w5的偏导值,为了表达方便,在此我们定义:

    δδ为神经元的误差 

    (与上文提到的误差不同,上文着重最终结果的误差,此处更着重单个神经元的误差)

  4. 那么δo1即为神经元o1的误差,即: 

    δo1=∂Etotal∂outo1∗∂outo1∂neto1=∂Etotal∂neto1δo1=∂Etotal∂outo1∗∂outo1∂neto1=∂Etotal∂neto1

    δo1=−(targeto1−outputo1)∗outo1(1−outo1)δo1=−(targeto1−outputo1)∗outo1(1−outo1)

    所以,整体误差E(total)对w5的偏导为: 

    ∂Etotal∂ω5=δo1∗outh1∂Etotal∂ω5=δo1∗outh1

    最后,w5得到更新: 

    ω5→ω5−η∗∂Etotal∂ω5ω5→ω5−η∗∂Etotal∂ω5

    ηη是学习速率,也叫步长
输入层(隐藏层) -> 隐藏层的权值更新
  1. 以w1为例: 

    ∂Etotal∂outh1∗∂outh1∂neth1∗∂neth1∂ω1=∂Etotal∂ω1∂Etotal∂outh1∗∂outh1∂neth1∗∂neth1∂ω1=∂Etotal∂ω1

    计算方法与上面类似,但是有个地方需要变一下,在计算h1的误差时,out(h1)会接受来自o1和o2两个神经元的误差,所以在这两个都要计算 

    BP(反向传播)
  2. 分别计算等号左边的三个式子:
    • ∂Etotal∂outh1∂Etotal∂outh1: 

      ∂Etotal∂outh1=∂Eo1∂outh1+∂Eo2∂outh1∂Etotal∂outh1=∂Eo1∂outh1+∂Eo2∂outh1

      先计算∂Eo1∂outh1∂Eo1∂outh1: 

      ∂Eo1∂outh1=∂Eo1∂neto1∗∂neto1∂outh1∂Eo1∂outh1=∂Eo1∂neto1∗∂neto1∂outh1

      其中: 

      ∂Eo1∂neto1=∂Eo1∂outo1∗∂outo1∂neto1∂Eo1∂neto1=∂Eo1∂outo1∗∂outo1∂neto1

      neto1=ω5∗outh1+ω6∗outh2+b2neto1=ω5∗outh1+ω6∗outh2+b2

      ∂neto1∂outh1=ω5∂neto1∂outh1=ω5

      得到: 

      ∂Eo1∂outh1=∂Eo1∂outo1∗∂outo1∂neto1∗ω5∂Eo1∂outh1=∂Eo1∂outo1∗∂outo1∂neto1∗ω5

      代入上边计算出的结果可得: 

      ∂Eo1∂outh1=−(targeto1−outputo1)∗outo1(1−outo1)∗ω5∂Eo1∂outh1=−(targeto1−outputo1)∗outo1(1−outo1)∗ω5

      观察1,2两个式子,我们可以发现,等号右边的左边两项,其实就是δo1,所以上式可以化简为: 

      ∂Eo1∂outh1=δo1∗ω5∂Eo1∂outh1=δo1∗ω5

      同理可得另一项: 

      ∂Eo2∂outh1=δo2∗ω7∂Eo2∂outh1=δo2∗ω7

      然后加起来便得到第一项: 

      ∂Etotal∂outh1=δo1∗ω5+δo2∗ω7∂Etotal∂outh1=δo1∗ω5+δo2∗ω7

    • ∂outh1∂neth1∂outh1∂neth1(即对sigmoid函数求导): 

      outh1=11+e−neth1outh1=11+e−neth1

      ∂outh1∂neth1=outh1(1−outh1)∂outh1∂neth1=outh1(1−outh1)

    • ∂neth1∂ω1∂neth1∂ω1: 

      neth1=ω1∗i1+ω2∗i2+b1neth1=ω1∗i1+ω2∗i2+b1

      ∂neth1∂ω1=i1∂neth1∂ω1=i1

  3. 然后乘起来即可: 

    ∂Etotal∂ω1=(δo1∗ω5+δo2∗ω7)∗outh1(1−outh1)∗i1∂Etotal∂ω1=(δo1∗ω5+δo2∗ω7)∗outh1(1−outh1)∗i1

  4. 那么δh1即为神经元h1的误差,即: 

    δh1=∂Etotal∂outh1∗∂outh1∂neth1=∂Etotal∂neth1δh1=∂Etotal∂outh1∗∂outh1∂neth1=∂Etotal∂neth1

    δh1=(δo1∗ω5+δo2∗ω7)∗outh1(1−outh1)δh1=(δo1∗ω5+δo2∗ω7)∗outh1(1−outh1)

    所以,整体误差E(total)对w1的偏导为: 

    ∂Etotal∂ω1=δh1∗i1∂Etotal∂ω1=δh1∗i1

    最后,w5得到更新: 

    ω1→ω1−η∗∂Etotal∂ω1ω1→ω1−η∗∂Etotal∂ω1

结论公式

首先我们重新规定一下命名,z表示带权输入,a表示输出激活值,即为经过激活函数的带权输入,C表示代价函数,L表示神经网络的层数。

现在我们以sigmoid激活函数为例,用四个公式总结一下反向传播算法:

输出层误差的方程

L层第j个神经元的误差: 

δLj=∂C∂aLj∗σ′(zLj)δjL=∂C∂ajL∗σ′(zjL)

用微分算子表示的矩阵形式为: 

δL=∇aC⊙σ′(zL)δL=∇aC⊙σ′(zL)

使用下一层的误差表示当前层的误差

下一层的误差呈上下一层的权重值,再点乘上当前层的输出,即为当前层的误差: 

δl=(δl+1(ωl+1)T)⊙σ′(zl)δl=(δl+1(ωl+1)T)⊙σ′(zl)

偏置b在代价函数C中的改变率

仔细观察上述计算过程可以发现,偏置b是带权输入z中的一项,而且偏置b的系数为1,所以我们可以得出,代价函数C对某神经元的偏置b的偏导即为该神经元的误差: 

∂C∂b=δ∂C∂b=δ

权重ω在代价函数C中的改变率

根据带权输入的表达式(ain为输入该神经元的激活值): 

z=ω∗ain+bz=ω∗ain+b

可知,代价函数 C 对 ω 的偏导是在误差的基础上乘上了输入激活值: 

∂C∂ω=ain∗δout∂C∂ω=ain∗δout

总结

四个公式: 

δL=∇aC⊙σ′(zL)δL=∇aC⊙σ′(zL)

δl=(δl+1(ωl+1)T)⊙σ′(zl)δl=(δl+1(ωl+1)T)⊙σ′(zl)

∂C∂b=δ∂C∂b=δ

∂C∂ω=ain∗δout

ML

继续阅读