Processing math: 100%

BP网络权值更新公式

BP网络又叫做误差反向传播网络,说这么复杂,从控制理论的角度来说,这玩意儿不就是一个负反馈回路么,无非是在负反馈回路中加入了一些自适应参数调整,不得不说有些时候还是控制科学与工程的名词叫起来更顺耳一些。BP这个负反馈过程实际上就是对权值进行更新的一个方法。本文参考了斯坦福大学的CNN for visual recognition课程,国外的这些个课程设计的简直碾压国内高校课程,看看配套的网站支持就知道了。斯坦福CNN for visual recognition课程

预备知识

  1. 梯度:f=[fx,fy],即偏导数组成的向量。(在感叹一句,这课程简直太详细了,完全把学生当作一张白纸,从最基本的梯度概念开始讲起)。
  2. 链式法则:fx=fqqx

了解了这两个基本的知识后,我们来搭建一个简单的神经网络,设f(x,y,z)=(x+y)z,令q=x+y,则f=qz,令x=2,y=5,z=4,相应的几个函数输出及偏导数分别为:

f=12q=3fx=z=4fy=z=4fz=(x+y)=3fq=z=4qx=1qy=1

用门电路的方式表示一下,下图中绿色的部分,就是网络计算的输出,它是前馈的,而红色就是f对各个分量进行求导得到的数值,它的方向正好是反馈过来的,所以也叫反向传播

通过上面的电路,我们发现每个门可以独立(即局部地)完成两件事:

  1. 前向输出的计算
  2. 反向传播即局部偏导数的计算(注意是局部)

一旦网络前向输出过程完成,那么最终f对各个分量的偏导数也就可知了,即全局偏导数就已知了。

链式规则在这里的作用就像是齿轮一样,将每一个部分连接在一起。

现在假设我们想要让输出f变大,那么由于我们的q导数为负,因此我们希望q尽可能小一些,根据链式法则继续往前推,我们知道q对于x,y的导数为1,而输出f对于x,y的导数为4,那么我们的目标就达到了,如果我们减小x,y,由于x,yf导数为负,此时乘法门的输出会增大,也就是说我们的输出会增大。

模块化:sigmoid函数

任何可微函数都可以充当门,同时我们也可以将多个门组合成一个大门来使用,例如我们的sigmoid函数,就组合了七种门。

f(w,x)=11+e(w0x0+w1x1+w2)

除了加法门、乘法门和最大门,还有下面四种:

倒数门、偏移门、指数门以及倍数门。

f(x)=1xdfdx=1/x2fc(x)=c+xdfdx=1f(x)=exdfdx=exfa(x)=axdfdx=a

组合起来就是这个样子:

sigmoid函数会把输入向量轻柔地转换至0-1之间的一个数。

BP过程推导

那么我们现在进入重头戏,反向传播算法的推导。

1
`<iframe width="854" height="480" src="https://www.youtube.com/embed/xqf2DJgucsU" frameborder="0" allowfullscreen></iframe>`

多层单节点

考虑一个最简单的三层神经网络,它是下面这个样子:

输入、隐含和输出层每一个神经元包含权重w和偏置b,所以这个神经网络的cost function可以描述为:

C(w1,b1,w2,b2,w3,b3)

我们需要知道cost function对各个参数的敏感程度,这样我们就能知道调节那个参数可以最有效果地降低cost function。我们先考虑后两层神经元,即隐含层和输出层,同时令期望输出为1。这里的L上标代表层位置

那么我们输出层的代价函数就是:

C0(...)=(a(L)y)2

a(L)是多少呢:

a(L)=σ(w(L)a(L1)+b(L))=σ(z(L))z(L)=w(L)a(L1)+b(L)

σ代表某种非线性函数,这里是上面提到的sigmoid函数。那么我们的计算关系树就如下图所示:

我们想要找到的是C0w(L)之间的关系,就是求C0w(L)。那么怎么搞呢?用我们前面提到的链式法则。

C0w(L)=z(L)w(L)a(L)z(L)C0a(L)C0a(L)=2(a(L)y)a(L)z(L)=σ(z(L))z(L)w(L)=a(L1)

代入化简我们可以得到下面的式子:

C0w(L)=2(a(L)y)σ(z(L))a(L1)

对于所有输入的训练样本:

Cw(L)=1nn1k=0Ckw(L)

其中n为样本数量,可以看到代价函数对w的导数是每一个样本输出值的均值。那么我们的整个网络的代价函数梯度可以写为:

C=[Cw(1)Cb(1)Cw(L)Cb(L)]

多层多节点

上面讨论了多层神经网络,每层只有一个神经元,这一节咱们讨论一下多层多节点的复杂神经网络,实际上就是公式变得复杂了一些,道理是一样的。

这里引入了下标,代表第i个神经元,我们的代价函数变为:

C0=nL1j=0(a(L)jyj)2

我们令从第k个神经元到第j个神经元的权值为w(L)kj,那么我们的zj则表示为:

z(L)j=nL1k=0w(L)kja(L1)k+b(L)j

对应的,我们要激活第L层第j个神经元,其输出为σ(z(L)j)。最终我们的代价函数对每一个权值的偏导数可以写为:

C0w(L)jk=z(L)jw(L)jka(L)jz(L)jC0a(L)j

可以看出对每个权值的偏导数是没有变化的,多神经元与单神经元的区别是对上层输出的偏导数会发生变化:

C0a(L)k=nL1j=0z(L)ja(L1)ka(L)jz(L)jC0a(L)j

讲到这里,基本上就可以算是把反向传播算法的基本原理写完了。后面有什么再接着补充。

0%