反向传播算法

                                                                                                                                                     点击此处返回总目录

 

 

今天要讲得是Backpropagation,实际上如果你要用Gradient Descent的方法来训练一个神经网络的时候,你应该要怎么做。

我们上次已经讲过神经网络的基本架构。我们来讲一下反向传播算法怎么让神经网络的训练变得有效的。

 

梯度下降法:是用来更新参数的。

BP算法:是用来更快地求偏微分的。

 

--------------------------------------------------------------------------------------------------------------------------------------

在Gradient Descent里面,假设Network有一大堆参数,有一大堆w和b。

                                     

首先选一个初试的参数

                                                              

然后计算对Loss function的gradient,也就是计算每一个w和b对Loss function的偏微分。这个gradient实际上是一个向量。

                                                           

                                                             

计算出来以后呢,就可以更新参数:

                                                

再算梯度,更新参数:

                                     

这个过程持续下去,就可以找到最好的参数了。

                              

--------------------------------------------------------------------------------------------------------------------------------------

所以在神经网络里面呢,用Gradient descent的方法的时候,跟我们在做Logistic Regression、linear Regression等等是没有太多差别的。但是最大的差别就是在神经网络里面,我们有非常非常多的参数。比如做声音识别,网络通常比如说有七八层,每层有1000个神经元,这样共有上百万个参数。所以gradient这个向量是非常长的,是一个上百万维的向量。

                                   

现在最大的困难是,你要如何有效地把这个有百万维的向量计算出来。这个就是反向传播算法在做的事情。

                                   

反向传播算法并不是一个和gradient descent不同的方法,它就是gradient descent。它只是一个比较有效率的演算法,让你在计算梯度这个向量的时候,比较有效率。

--------------------------------------------------------------------------------------------------------------------------------------

其实,反向梯度算法中并没有特别高深的数学。你唯一要记得的就是链式法则。这个没啥好讲的,不懂的童鞋可以回去翻一下微积分或者高数。等一下会用到这个东西。

                                             

--------------------------------------------------------------------------------------------------------------------------------------

在上一节中讲了,total  Loss为所有data的loss之和:     

                                        

其中网络结构为:

                            

把这个式子,两边对某一个w求偏微分的话,就得到:

                                 

只所以写这个式子,是要说接下来我们就不用计算,而是只考虑对某一个data的。能够把一个data的偏微分求出来,再把所有的求和,就可以算出total Loss对w的偏微分了。

所以等一下,我们就只focus在对于某一个data,它的损失对w的偏微分就行了,即:

                                                                       

--------------------------------------------------------------------------------------------------------------------------------------

那怎么做呢?我们先考虑某一个神经元。我们从下面的神经网络里面拿一个神经元出来。

                             

 

这个神经元是第一个Layer的神经元。它前面的input就是x1,x2(假设有两个输入)。x1,x2分别乘上w1,w2,再加上b,会得到z。得到z以后再经过激活函数,再经过非常非常多的事情以后,会得到最终的output y1,y2。

                             

现在的问题是,怎么来计算某一个weight对某一个data的Cost的偏微分(b也是一样,可以以此类推算出来,我们用w来举例)。

                                                                   

按照链式法则,可以拆成两项:

                                     

这两项,我们就可以分别计算出来。前面一项是很简单的,后面一项是比较复杂的。计算前面这一项,我们称之为Forward pass,待会就会知道为什么这么叫。计算后面这一项我们称之为Backward pass,待会将为什么这么叫。

 

                                         

--------------------------------------------------------------------------------------------------------------------------------------

那么就先来看一下怎么计算

                           

这个秒算,因为已经知道了z长什么样子。就是x1,就是x2。

 

                            

它的规律就是看w前面接的什么。接的是什么微分以后就是什么。

所以假如给你一个神经网络,它里面有一大堆参数,你要计算这里面每一个参数对z的偏微分。这件事情非常容易,因为规律就是看w前面接的是什么。所以当问第一个红圈圈的w对它的z的偏微分,就是-1,因为这个1接的是-1。第2个红圈圈的w对它的z的偏微分是0.12,这个0.12是什么呢,是上一层的某一个神经元的output。第3个红圈圈的w对它的z的偏微分是0.11。

 

                              

所以,你要计算这个神经网络里面每一个weight对它的estimater function z 的偏微分,你就把input丢进去,然后计算每一个神经元的输出(黄色方框内的数字),就结束了。这个步骤叫做,Forward pass,它是非常容易理解的。

 

--------------------------------------------------------------------------------------------------------------------------------------

再来,我们要讲的是Backward pass,也就是

                         

 

这就比较困难了。因为这个z要经过激活函数得到a,后面还有非常复杂的过程,才得到C。

                             

 

不过我们可以用链式法则把这一项做一下拆分。假设这个激活函数是sigmoid()函数。,神经元的输出是a。接下来,a会乘上某一个weight,再加一堆东西得到z'。a还会乘上另外一weight,再加上一堆东西得到z''。z',z''之后可能还会发生一大堆事情,我们就先只考虑一步。

                       

通过链式法则,得到:

                                     

我们知道,所以就是sigmoid的微分。sigmoid()函数长这个样子,微分长这个样子,我们之前看过。

                       

接下来的问题是,应该长什么样子呢?a通过z'和z''影响C,所以根据链式法则有:

                          

又有:

                        

所以最后的问题就是,z对C的偏微分没法算。因为我们不知道z与C是什么关系,后面的还有发生许多事情。一下子不知道怎么算。

                           

那怎么办呢?假设我们知道。假设这两个值,我们已经通过某种方法算出来了。

                                  

 

这样,我们就可以算了。

                                                       (1)

 

我们发现:(1)式子是一个递推式!只要求出后一层全部的z对C的偏微分,就可以分别求出本层的z对C的偏微分了!!

--------------------------------------------------------------------------------------------------------------------------------------

我们从另外一个角度来看待这个式子。

你可以想象说,现在有另外一个神经元,这个神经元并不在我们原来的网络里面。这个神经元,我把它画成三角形的。这个神经元的输入就是。而输出。这个神经元所做的运算跟前面的式子是一样的。其中,其实是一个常数,不是一个函数,因为z在计算forward pass的时候就被决定好了,z我们已经知道它是多少,是一个固定的值。所以这个神经元跟之前学的神经元的运算不一样,没有进行非线性变换,而是直接乘上一个常数。

 

                     

--------------------------------------------------------------------------------------------------------------------------------------

刚才说,根据递推式(1),只要求出后一层全部的z对C的偏微分,就可以分别求出本层的z对C的偏微分了。

因此,求z对C的偏微分,分为两种情况:

 

第一种情况,假设现在红色的两个神经元的output就已经是整个网络的output了。

 

                         

这时候要算z'对C的偏微分,很简单,根据链式法则,就是。其中,这一项没什么问题,只要知道激活函数长什么样子就能轻而易举地算出来。这一项的话,要看你的Coss function 是怎么定义的,你可以用交叉熵损失,可以用均方误差,不同的定义会不一样,但总之是一个比较简单的东西,可以把它算出来。

同样可以算出z''对C的偏微分。

 

 

 

第二种情况,假设现在红色的神经元的输出并不是整个网络的output。

当然是通过递推式(1)来算。

            

--------------------------------------------------------------------------------------------------------------------------------------

有的人会说,要算第一层的,需要知道第二层的;要算第二层的,需要知道第三层的;...这样一层层的往后展开,感觉会是一个很可怕的式子。但是,实际上,并不是这样做的。实际上在做的时候,只要换一个方向,从后往前做,就会发现它的运算量跟Forward pass其实是一样的。

假设我们现在有6个神经元。要计算这些z对C的偏微分。本来呢,想要知道z1的偏微分,就要知道z3和z4的偏微分;要算z3的偏微分,就要知道z5和z6的偏微分;要算z4的偏微分,也要知道z5和z6的偏微分。如果是从z1,z2开始算,那就很没有效率。但是,如果返回来,先算z5和z6的偏微分的话,这个过程就变得有效率起来了。

 

                          

 

计算的时候,最后一层直接求,其他层就用递推式(1)来做:

                            

这整个过程叫backward pass。就是建立一个反向的网络。

 

--------------------------------------------------------------------------------------------------------------------------------------

最后总结一下,反向传播算法是怎么做的。

首先做一个Forward pass,要求出每一个神经元的输出a。a就是它所连接的weight的

然后做一个Backward pass,在这里面,要把原来的神经网络的方向反过来,反过来的神经网络中,每个神经元的output就是

最后把乘起来,就是了。

                                   

 

BP算法,就算不懂也没什么关系,大部分人都不懂,反正有工具~~不过懂了最好,也不难~~

 

 

 

 

 

 

 

  • 6
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值