误差反向传播算法浅解

来源:互联网 发布:收款收据打印软件 编辑:程序博客网 时间:2024/06/05 07:53

反向传播(英语:Backpropagation,缩写为BP)是“误差反向传播”的简称。由于多层前馈神经网络的训练经常采用误差反向传播算法,人们也常把多层前馈神经网络称为BP网络。


反向传播算法发明的历史请参考我的前文《神经网络简史》。


多层前馈神经网络是指通过按某种方式将神经元连接起来,就可构成相关神经网络。下图所示为一个熟知的前馈网络模型,该网络有L层,第1 层为输入层,第L层为网络输出层。在这个网络中,前一层神经元全连接到后一层神经元,同层的神经元之间没有任何连接


反向传播通常被认为是基于优化理论的一种监督式学习方法,虽然它也用在一些无监督网络(如自动编码器)中。


本文主要内容:

  • 神经网络应用梯度下降的直观理解

  • 反向传播算法的学习过程

  • 反向传播算法推导

  • 总结探讨

  • 本文灵感来源

  • 参考文献


直观理解


考虑一个有两个输入单元、一个输出单元、没有隐藏单元的简单神经网络。每个神经元都使用输入的加权和作为线性输出。


最初在训练之前,会随机分配权重。之后神经元根据训练实例进行学习,在此情况下包含元组 (x1,x2,t) 的集合,其中 x1与x2是网络的输入,t 为正确输出(在给定相同的输入时网络最终应当产生的输出)。网络在给定x1 和 x2时,会计算一个输出 y,很可能与t 不同(因为权重最初是随机的)。衡量期望输出t 与实际输出  y 之间的差异的一个常见方法是采用平方误差测度:

其中E为差异或误差。


为什么采用平方差?其数学背景是最小二乘法,也可以理解为空间两点的距离或者平方误差等。最小二乘法(又称最小平方法)是一种数学优化技术。它通过最小化误差的平方和寻找数据的最佳函数匹配。最重要的应用是在曲线拟合上。最小平方所涵义的最佳拟合,即残差(残差为:观测值与模型提供的拟合值之间的差距)平方总和的最小化。


举例来讲,考虑单一训练实例的网络:(1,1,0),输入x1 与x2均为1,正确输出t 为 0(网络只有一个输出)。现在若将实际输出 y 画在x轴,误差E画在y 轴,得出的是一条抛物线。抛物线的极小值对应输出y,最小化了误差E。对于单一训练实例,极小值还会接触到 x 轴,这意味着误差为零,网络可以产生与期望输出t 完全匹配的输出y。因此,把输入映射到输出的问题就化为了一个找到一个能产生最小误差的函数的最优化问题。

单一实例的神经网络的误差函数非常容易理解,可以通过解方程,直接找到最小值。这里给一个梯度表示,如下图,便于理解多实例神经网络的梯度表示。



反向传播算法的目的是找到一组能最大限度地减小误差的权重。寻找抛物线或任意维度中任何函数的极大值的方法有若干种。其中一种方法是通过求解方程组,但这依赖于网络是一个线性系统,而目标也需要可以训练多层非线性网络(因为多层线性网络与单层网络等价)。


如果考虑两个实例呢(依然是单层神经网络,不考虑非线性变换)?


考虑一个神经元的输出取决于其所有输入的加权总和:

其中w1和 w2是从输入单元到输出单元相连的权重。因此,误差取决于输入到该神经元的权重,也是网络要学习最终需要改变的。若每个权重都画在一个水平的轴上,而误差画在垂直轴上,得出的就是一个抛物面(若一个神经元有 k 个权重,则误差曲面的维度就会是k+1,因而就是二维抛物线的k+1维等价)。



抛物面的最小值需要通过梯度下降法求得。如下图所示。


如果是多个实例呢?并且是多层神经网络的非线性变换呢?从数学角度看,已经不能通过求解方程组得到最小值,也不能简单的描绘多维权重系数构成的函数所对应的几何形状(比如抛物面)。但是运用抽象推理,大概想象成这样子:


以上就是神经网络学习和误差函数原理的直观表示。


结合梯度的概念,这里先给出梯度下降的推导结果(公式所示),下面逐步解释为什么有这个推导结果



这个公式推导所带出的三个导数非常重要,是影响梯度的三个重要因素。我把上面三个偏导分成三部分来讨论,分别对应于误差函数激活函数神经元模型。假设我们要得到的是第i层到第j层的连接权重w_ij,用于梯度的偏导可以通俗的表达为:


下面分别从神经元模型误差函数激活函数的角度解释这个公式。


一个神经元的基本模型如下图所示。



通向一个神经元的输入net_j是之前神经元的输出o_i 的加权和。若该神经元输出层后的第一层,输入层的输出 o_i就是网络的输入 x_i。该神经元的输入数量是 n。变量 w_ij表示神经元 i 与 j 之间的权重。对于每一个神经元,其对应的输出为:

从数学的角度来看,神经元模型定义了两层的复合函数:内层是net_k,外层是φ函数。激活函数φ一般是非线性可微函数(反向传播要求人工神经元的激励函数可微)。常用作激活函数的是Sigmoid函数:

或者写成:

这个函数也被称为单极性Sigmoid函数。其导数形式很好:

其图像如何下:

双极性Sigmoid函数要比较常用。公式如下:

或者写成(把上式中分子分母同时除以e^z,令x=-2z就得到第二个式子):

其导数为:

其图像为:

从上图可以看出,对于Sigmoid函数,当z的取值越来越大后(饱和区),函数曲线变得越来越平缓,意味着此时的导数也越来越小。同样的,当z的取值越来越小时(饱和区),也有这个问题。仅仅在z取值为0附近时,导数的取值较大。在后文讲到的反向传播算法中,每一层向前递推都要乘以导数,得到梯度变化值。Sigmoid的这个曲线意味着在大多数时候,我们的梯度变化值很小,导致我们的W,b更新到极值的速度较慢,也就是我们的算法收敛速度较慢。


由于反向传播使用梯度下降法,需要计算平方误差函数对网络权重的导数。假设对于一个输出神经元,平方误差函数为:

其中

  • E 为平方误差,

  • t 为训练样本的目标输出,

  • y 为输出神经元的实际输出。

  • 加入系数1/2是为了抵消微分出来的指数。之后,该表达式会乘以一个任意的学习速率,因此在这里乘上一个常系数是没有关系的。


由梯度的定义,与方向导数有关联的一个概念是函数的梯度。多元函数的偏导向量构成了梯度,梯度的方向是函数在这点增长最快的方向,那么函数的偏导在这点的梯度方向也达到最大值。其中,要使用梯度下降法更新 w_ij,必须选择一个学习速率μ。要加在原本的权重上的变化,等于学习速率与梯度的乘积,乘以-1:

之所以要乘以-1 是因为要更新误差函数极小值而不是极大值的方向。


从数学的角度看,平方误差函数形成了对输出o_j的复合函数:

这个式子无论对于输出层的神经元,还是隐藏层的神经元,都是成立的。


综上所述,误差函数是关于权重的函数,为了在由权重系数构成的多维空间中寻找一个下降最快的梯度方向,我们需要对所有权重系数求偏导。根据复合函数的求导规则,其一般形式为:


反向传播算法的学习过程


学习过程由信号的正向传播与误差的反向传播两个过程组成。正向传播时,输入样本从输入层传入,经各隐层逐层处理后,传向输出层。若输出层的实际输出与期望的输出(教师信号) 不符,则转入误差的反向传播阶段。误差反传是将输出误差以某种形式通过隐层向输入层逐层反传,并将误差分摊给各层的所有单元,从而获得各层单元的误差信号,此误差信号作为修正各单元权值的依据。这种信号正向传播与误差反向传播的各层权值调整过程,是周而复始地进行的。权值不断调整的过程,也就是网络学习训练过程。此过程一直进行到网络输出的误差减少到可接受的程度,或进行到预先设定的学习次数为止。


学习过程的伪码描述如下:

输入:训练集和学习率

初始化网络权值(通常是小的随机值)

  do

     forEach 训练样本 ex

        prediction = neural-net-output(network, ex)  // 正向传递,得到当前样本的输出

        actual = teacher-output(ex)//从监督老师那里获得真实输出

        计算输出单元的误差 (prediction - actual)//获得残差

        计算    对于所有隐藏层到输出层的权值和阈值          // 反向传递

        计算    对于所有输入层到隐藏层的权值和阈值          // 继续反向传递

        更新网络权值和阈值 // 输入层不会被误差估计改变

  until 所有样本正确分类或满足其他停止条件

  return 权重与阈值确定的多层前馈神经网络


完整的误差反向传播算法包括前向计算和反向传播两部分。


反向传播算法推导


为了最小化误差E,最终归结为优化问题。前面说过,反向传播算法的目的是找到一组能最大限度地减小误差的权重,在反向传播中使用的方法是梯度下降法。这样我们就需要计算误差函数E对权重的偏导。由上文,误差函数对权重w_ij的偏导数是三个偏导数的乘积:


我们的目标就是分别求得这三个偏导。


在右边的最后一项中(神经元模型),只有加权和 net_j取决于 w_ij,因此:

当对一个权重求导时,其他权重就视为常量。这里如有不确定,把加权和展开即可明白。


对于激活函数部分,神经元j 的输出对其输入的导数就是激活函数的偏导数(这里假定使用Sigmoid函数):

这就是为什么反向传播需要的激活函数是可微的。同时,前向传播时,很容易求得net_j(各层神经元计算得到的加权和),所以该偏导也容易求得。


对于误差函数部分的偏导,为了方便理解,分输出层和隐藏层来讨论。


如果神经元在输出层中,因为此时o_j=y以及

所以第一项可以直接算出。


但如果j 是网络中任一内层(隐藏层),就需要用到链式求导法则。


下面以一个神经网络的局部来说明。神经网络中相邻的两层构成一个计算单元,因此只需要理解第j层和第k(j+1) 层之间的结构和运算,便可以通晓整个网络的结构和运算(前面说过,层与层之间全连接,同层之间没有连接)。


注意到我们要求的是第i层到第j层的连接权重w_ij,考虑第j层中的某个神经元的输出o_j是第k层所有神经元{u,v,…,w}的输入,把误差(损失)函数E看作是{u,v,…,w}的函数(注意,这里的第k层可能是输出层,也可能是隐藏层;作为输出层时,既可能是多值输出,也可能是单值输出)。可以得到:


这里应用链式求导法则


最后一步做了两次替换:


对于上面推导结果,我们发现:


因此,若已知所有关于下一层(更接近输出神经元的一层)的输出关于o_k 的导数,则可以计算 o_j的导数。


现在把上述推导放在一起:

此时:

则:


综上,权重的调整只和以下因素有关:

  • 前向神经元的输出(和所调整权重有关的一个前向神经元的输出作为输入)

  • 当前神经元的激活函数

  • 所有后向神经元(误差函数导数,激活函数导数,并一直递归下去)及其前向传播时的权重(这些权重用来作为误差后向传播的权重)

  • 递归会终结在输出层,从而使用残差(y-t)。注意到递归的层数以及系数作用,这里有一大串连乘,如果连乘的数字小于1,则梯度越乘越小,导致梯度消散;如果连乘的数字大于1,则梯度越乘越大,导致梯度爆炸

  • 对于偏置来说,注意到偏置是没有权重,调整的是偏置本身


总结探讨


总结起来,BP的误差反向传播思想可以概括为:利用输出层的误差来估计出其直接前导层的误差,再借助于这个新的误差来计算更前一层的误差,按照这样的方式逐层反传下去便可以得到所有各层的误差估计。


BP算法的提出在一定程度上解决了多层网络参数训练难的问题,但是其自身也存在如下一些问题。


首先,误差在反向传播过程中会逐渐衰减/增大,经过多层的传递后将会变得消散/爆炸,这使得BP在深层网络中并不可行。对于梯度爆炸,则一般可以通过调整神经网络模型中的初始化参数得以解决。对于无法完美解决的梯度消失问题,目前有很多研究,一个可能部分解决梯度消失问题的办法是使用ReLU(Rectified Linear Unit)激活函数(σ(z)=max(0,z))。


其次,BP采用最速梯度下降的优化思想,而实际问题的误差函数通常不是凸的,存在众多局部极小值点,算法很难得到最优解。极小值问题,有多种解决方案,比如从多个不同的初始点开始搜索,模拟退火,随机梯度下降,遗传算法等。但这些都是启发式,理论上尚缺乏保障。


第三,由于训练过程中依靠于导数信息来进行权值的调整,当权值调节过大时会使大部分神经元的加权和过大,致使传递函数工作于S型函数的饱和区,所以权值的调整会出现停顿的情况。


第四,隐层神经元的个数设置是个未解决的问题,实际应用中通常靠试错法调整。


第五,BP神经网络的过拟合,常用的方法是早停和正则化。早停是指:将数据分成训练集和验证集,训练集用来计算梯度,更新连接权和阈值,验证集用来估计误差,如果训练集误差降低但是验证集误差升高,则停止训练,同时返回具有最小验证集误差的连接权和阈值。正则化是指:误差目标函数中增加一个用于描述网络复杂度的部分,例如连接权与阈值的平方和。


最后,对于一些复杂网络的优化问题,BP算法受到学习速率的限制需要花费几个小时,甚至更长的时间来完成训练任务。累积BP算法和标准BP算法各有优缺点。