BP算法到底是如何进行误差反向传播的?

By | 2016年12月25日

上一篇介绍BP算法的文章主要是针对觉得数学公式太麻烦,只要把BP当做一个黑盒子去用的同学,比如之前的我。。。觉得这个什么梯度啊、求导啊,一看就好麻烦啊,我只要会用它就行了嘛。但其实如果不深层次地搞懂BP其中的数学原理,对BP的了解就还只是很浅的层面,在使用的过程中也许会产生很多困惑。

所以接下来,让我们一步一步地去弄懂BP算法到底是如何进行误差的反向传播的。

  1. 用矩阵的形式来表示神经网络
  2. 关于损失函数的两个假设
  3. Hadamard乘积
  4. BP算法的四个基本公式
  5. BP算法的步骤
  6. BP算法的正向思考

1.用矩阵的形式来表示神经网络

1.1 以神经元的观点

首先,我们用qq%e6%88%aa%e5%9b%be20161225114338来表示 第(l-1)层的第 k 个神经元 到 第(l)层的第  j 个神经元的权值。可能你会有和我一样的困惑:为什么不用 j 表示前一层的神经元,k 表示后一层的神经元呢,这样按顺序表示多好?接下来会介绍为什么要这样表示~

qq%e6%88%aa%e5%9b%be20161225114208

接下来,我们使用同样的形式来表示网络的偏差 b 和激活值 a。

qq%e6%88%aa%e5%9b%be20161225115037表示第 l 层的第 j 个神经元的偏差,qq%e6%88%aa%e5%9b%be20161225115005表示第 l 层的第 j 个神经元的激活值(也就是输出)。

qq%e6%88%aa%e5%9b%be20161225115218

那么,第 l 层的第 j 个神经元的激活值和第 (l-1)层的第 k 个神经元的激活值之间的关系就可以用下式表示出来:

qq%e6%88%aa%e5%9b%be20161225115520

1.2 以矩阵的观点

为了用矩阵的形式表示神经网络,我们定义每一层的权值矩阵 qq%e6%88%aa%e5%9b%be20161225125908,矩阵的 j 行 k 列 就是第(l-1)层的第 k 个神经元 到 第(l)层的第  j 个神经元的权值qq%e6%88%aa%e5%9b%be20161225114338

同理,定义每一层的偏差向量qq%e6%88%aa%e5%9b%be20161225130106,矩阵的第 j 个元素就是第 l 层的第 j 个神经元的偏差qq%e6%88%aa%e5%9b%be20161225115037。定义每一层的激活值向量qq%e6%88%aa%e5%9b%be20161225130331,矩阵的第 j 个元素就是第 l 层的第 j 个神经元的激活值qq%e6%88%aa%e5%9b%be20161225115005

最后,若有一函数qq%e6%88%aa%e5%9b%be20161225130557,我们假设 激活函数 σ 拥有以下特性:即函数可以作用于向量的任一元素。

qq%e6%88%aa%e5%9b%be20161225130621

那么,(23)式表示成矩阵的形式如下:

qq%e6%88%aa%e5%9b%be20161225130508

这种形式可以让我们以全局的眼光来看 某一层的激活值和其前一层的激活值 之间的关系:将前一层的激活值乘以一个权值矩阵,再加上一个偏差向量,最后再运用一个 σ 函数。

这种形式比一个神经元一个神经元地去看要简便很多,也更容易理解。

另外就是,现在很多库都提供相当高效的矩阵运算、向量运算,这样表示也便于程序计算。

1.3 加权输入z

当计算 qq%e6%88%aa%e5%9b%be20161225130331时,我们会得到一个中间值qq%e6%88%aa%e5%9b%be20161225131613 ,我们称qq%e6%88%aa%e5%9b%be20161225131640为 l 层神经元的加权输入(weighted input)。

其中,qq%e6%88%aa%e5%9b%be20161225131640中的第 j 个元素 qq%e6%88%aa%e5%9b%be20161225132011,表示第 l 层的第 j 个神经元的加权输入。

那么,公式(25)有时候也可以写成qq%e6%88%aa%e5%9b%be20161225131929

2.关于损失函数的两个假设

BP算法的目的就是计算损失函数C对于权值w和偏差b的偏导数qq%e6%88%aa%e5%9b%be20161226202322 、qq%e6%88%aa%e5%9b%be20161226202331。为了BP算法能够有效地进行,我们需要对损失函数作出两个重要的假设。

2.1 网络的损失函数可以写成所有样本的损失函数的平均值

在神经网络中,我们一般选择二次损失函数:

qq%e6%88%aa%e5%9b%be20161226202620

其中,n是训练样本的总数,y(x)是期望输出,L是网络的层数,qq%e6%88%aa%e5%9b%be20161226203315是网络的实际输出。

第一个假设就是:网络的损失函数可以写成多个样本的损失函数的平均值

qq%e6%88%aa%e5%9b%be20161226203442

其中,Cx是单个样本的损失函数,其公式如下:

qq%e6%88%aa%e5%9b%be20161226203108

其中,y是期望输出,qq%e6%88%aa%e5%9b%be20161225130331是实际输出。

这样假设的原因是:BP算法实际上要做的是计算每个样本关于w和b的偏导数qq%e6%88%aa%e5%9b%be20161226203832,现在我们可以通过平均所有样本得到qq%e6%88%aa%e5%9b%be20161226202322 和qq%e6%88%aa%e5%9b%be20161226202331

所以,基于这一假设,我们认为训练样本x已经固定了,然后将qq%e6%88%aa%e5%9b%be20161226204315的下标拿掉,简化成 C。

2.2 损失函数是关于网络输出的函数

第二个假设就是损失函数可以看做是关于网络输出的函数

qq%e6%88%aa%e5%9b%be20161226204532

比如说,当二次损失函数写成下面形式时,它就是关于qq%e6%88%aa%e5%9b%be20161226204746的函数:

qq%e6%88%aa%e5%9b%be20161226204823

这样看起来,好像C还是关于y的一个函数呀,其实不是的。当我们的输入x固定时,我们的期望输出y也是固定了的。

换句话说,我们可以通过改变w和b来改变网络的输出qq%e6%88%aa%e5%9b%be20161226204746,但不能改变期望输出y。也就是说,y不是网络可以学习到的东西。

3.Hadamard乘积

BP算法是基于常见的线性代数运算——向量加法、向量和矩阵相乘等等。但有一个运算并不常见。

假设 s 和 t 是维度相同的两个向量,我们用qq%e6%88%aa%e5%9b%be20161226210054表示这两个向量中元素与元素的相乘,举个例子:

qq%e6%88%aa%e5%9b%be20161226210152

也就是说,同一位置的元素相乘。这种运算有时候也称为 Hadamard product 或者 Schur product。

许多矩阵运算库都提供这种计算,而且这个运算在实现BP时会派上用场的。

4.BP算法的四个基本公式

BP主要衡量了改变网络的权值和偏差时,是如何改变损失函数的。也就转化成了,计算偏导数qq%e6%88%aa%e5%9b%be20161226210821qq%e6%88%aa%e5%9b%be20161226210830

不过,在计算偏导数之前,我们先介绍一个中间量qq%e6%88%aa%e5%9b%be20161226211104,它指的是第 l 层第 j 个神经元的误差(error)。BP算法给出了计算qq%e6%88%aa%e5%9b%be20161226211104的步骤,然后推导出qq%e6%88%aa%e5%9b%be20161226210821qq%e6%88%aa%e5%9b%be20161226210830

qq%e6%88%aa%e5%9b%be20161226211427

假设网络的第 l 层第 j 个神经元上有一个小恶魔,当网络的输入进来之后,这个恶魔就会产生一些干扰:在该神经元的加权输入上加入一点点改变qq%e6%88%aa%e5%9b%be20161226211632

本来这个神经元的输出应该是qq%e6%88%aa%e5%9b%be20161226211639,但是变成了 qq%e6%88%aa%e5%9b%be20161226211647,经过不断地向前传播,最终导致了整个网络最后的输出和我们的期望输出不一样,改变量为qq%e6%88%aa%e5%9b%be20161226212022

但是呢,这个恶魔还算有点良心,它想帮我们找出这个qq%e6%88%aa%e5%9b%be20161226211632,从而减少损失。

假设qq%e6%88%aa%e5%9b%be20161226212931的值很大(要么为正要么为负),那么恶魔就可以选择一个和qq%e6%88%aa%e5%9b%be20161226212931方向相反的qq%e6%88%aa%e5%9b%be20161226211632来有效地减少损失函数的值。

但是,如果qq%e6%88%aa%e5%9b%be20161226212931的值接近于0,恶魔几乎不能通过改变加权输入Z的值来减少损失函数的值了。说明此时的神经元已经是最优的了。

所以说,qq%e6%88%aa%e5%9b%be20161226212931是神经元的误差的一个衡量指标。我们可以定义qq%e6%88%aa%e5%9b%be20161226211104如下:

qq%e6%88%aa%e5%9b%be20161226213712

那么,按照前面的方式,我们定义qq%e6%88%aa%e5%9b%be20161226213805为 l 层的误差向量。BP算法会计算出每层的 qq%e6%88%aa%e5%9b%be20161226213805,然后计算我们实际感兴趣的值qq%e6%88%aa%e5%9b%be20161226210821qq%e6%88%aa%e5%9b%be20161226210830

你可能会想为什么是改变加权输入,而不是直接改变激活值。是因为用qq%e6%88%aa%e5%9b%be20161226212931会让代数式更加简洁明了,不至于很复杂。下面你就会明白的。

4.1 输出层的误差方程

qq%e6%88%aa%e5%9b%be20161226215052

关于(BP1)的证明如下:

img_170020161226-221734

以上各项都比较好计算,假设我们使用二次损失函数,就可以求得:

qq%e6%88%aa%e5%9b%be20161226215607

qq%e6%88%aa%e5%9b%be20161226215650

以上只是qq%e6%88%aa%e5%9b%be20161226215823的第 j 个分量,要写成矩阵的形式:

qq%e6%88%aa%e5%9b%be20161226215911

其中,qq%e6%88%aa%e5%9b%be20161226220018是一个向量,并且有qq%e6%88%aa%e5%9b%be20161226220215,其分量就是qq%e6%88%aa%e5%9b%be20161226220114

所以,最终的矩阵形式如下:

qq%e6%88%aa%e5%9b%be20161226220320

4.2 由后一层的误差求前一层的误差

qq%e6%88%aa%e5%9b%be20161226222144

关于(BP2)的证明如下:

img_170120161226-223359

这样,我们就通过 l  层的激活函数,将误差进行反向传播了。

所以,通过公式(BP1)和(BP2),我们就可以计算任一层的误差了。首先,通过(BP1)计算输出层(即L层)的误差,然后通过(BP2)计算 L-1 层的误差,再通过(BP2)计算 L-2 层的误差,以此类推。

4.3 关于偏差 b 的损失率

qq%e6%88%aa%e5%9b%be20161226224119

4.4 关于权值 w 的损失率

qq%e6%88%aa%e5%9b%be20161226224131

其中,qq%e6%88%aa%e5%9b%be20161227190254是第 (l-1) 层第 k 个神经元的激活值,也就是第 l 层第  j  个神经元的输入,所以,(BP4)又可以写成如下形式:

qq%e6%88%aa%e5%9b%be20161227190531

更形象的图示如下:

qq%e6%88%aa%e5%9b%be20161227190619

由公式(32)可知,当qq%e6%88%aa%e5%9b%be20161227190732时,梯度qq%e6%88%aa%e5%9b%be20161226202322也会很小。这时候我们就会说,权值w学习得很慢,说明在梯度下降的时候,w并没有改变很多。用一句话概括就是:激活值很低的神经元的权值学习速度很慢

关于(BP3)和(BP4)的证明如下:

qq%e5%9b%be%e7%89%8720161227094309

最后总结一下,这4个基本公式如下:

4.5 从4个公式中得到的一些启发

qq%e6%88%aa%e5%9b%be20161227191852

4.5.1 神经元饱和

对于公式(BP1)和(BP2),我们先看输出层。

由sigmoid函数的分布曲线可知,当qq%e6%88%aa%e5%9b%be20161226211639趋向于0或1时,曲线变得非常平坦,这个时候qq%e6%88%aa%e5%9b%be20161227192245

所以说,当输出层的神经元激活值很低(≈0)或很高(≈1)时,输出层的权值会学习得非常慢

这个时候,我们可以说:如果输出层的神经元趋向于饱和,此时,qq%e6%88%aa%e5%9b%be20161226211104很小,权值会停止学习(或者说学习得很慢)。

对于偏差b,是同样的道理。

4.5.2 适用于任意激活函数

这4个公式适用于任何激活函数(即任何神经元),而不仅仅是sigmoid神经元。

所以说,我们可以利用这些公式,来设计具有特定功能的激活函数,而不用局限于目前已有的这些神经元类型。

5.BP算法的步骤

前面的几个公式告诉了我们如何计算损失函数的梯度,下面我们来具体看一下BP算法的步骤:

qq%e6%88%aa%e5%9b%be20161227214421

5.1 随机梯度下降法

我们前面提到,BP算法计算单个训练样本的损失函数的梯度qq%e6%88%aa%e5%9b%be20161226204315

在实际应用中,BP算法通常会结合随机梯度下降法等学习算法一起使用,从而可以同时计算多个样本的梯度( it computes the gradients for all training examples in a mini-batch simultaneously)。这个时候,输入不再只是一个 向量x,而是一个矩阵qq%e6%88%aa%e5%9b%be20161228113429,其中每个分量都是一个向量。这样会加快计算速度

比如说,计算一个包含 m 个训练样本的 mini-batch 的步骤如下:

qq%e6%88%aa%e5%9b%be20161227220223

其中,m为一个 mini-batch 中的样本个数,η 为学习率。

当然了,想要实现随机梯度下降法,你需要一个 产生 mini-batch的 外部循环(outer loop),以及一个训练 multiple epochs 的外部循环。

6.BP算法的正向思考

首先,假设我们对第 l 层的第 j 个神经元的权值作出了一点小小的改变:

qq%e6%88%aa%e5%9b%be20161228152356

那么该神经元的输出激活值就会相应地发生改变:

qq%e6%88%aa%e5%9b%be20161228152529

这样,就会引起下一层的所有神经元的激活值发生改变(全连接网络),然后下一层、下一层,直到输出层的损失函数也发生了改变:

qq%e6%88%aa%e5%9b%be20161228152709

那么,损失函数的改变量与该神经元的权值的改变量的关系可知:

qq%e6%88%aa%e5%9b%be20161228152912

因此,如果我们想要计算梯度qq%e6%88%aa%e5%9b%be20161226210821,那么就要知道 某一个神经元的权值的改变量 Δw 是如何引起损失函数的改变量 ΔC 的。

接下来让我们一层一层地去看。

首先,第 l 层的第 j 个神经元的权值的改变所导致的该神经元的激活值的改变量可知:

qq%e6%88%aa%e5%9b%be20161228153612

接着,该神经元的激活值的改变,又会引起第 (l+1) 层的所有神经元的激活值的改变。

qq%e6%88%aa%e5%9b%be20161228153956

但是我们先只看下一层的某一个神经元的改变量,即第 (l+1) 层的第 q 个神经元的改变量如下:

qq%e6%88%aa%e5%9b%be20161228153744

将公式(48)代入公式(49)中可得:

qq%e6%88%aa%e5%9b%be20161228153752

同理,第 (l+1) 层的第 q 个神经元的改变又会引起第 (l+2) 层的神经元的改变,以此类推。假设我们沿着一条路径qq%e6%88%aa%e5%9b%be20161228154614这样推下去,直到输出层 L 层,那么就可以得到 损失函数的改变量公式如下:

qq%e6%88%aa%e5%9b%be20161228154733

qq%e6%88%aa%e5%9b%be20161228155712

这个公式表示了 第 l 层的第 j 个神经元的权值的改变沿着这条特殊路径对损失函数所产生的改变量大小

当然,除了这条路径,还有很多条其它路径,都会对损失函数产生影响。所以,想要求损失函数 C 的最终的改变量大小,我们就必须考虑到所有路径,也就是说,我们必须对公式(51)进行求和运算:

qq%e6%88%aa%e5%9b%be20161228155211

qq%e6%88%aa%e5%9b%be20161228152912

与公式(47)进行比较,我们就可以得到:

qq%e6%88%aa%e5%9b%be20161228155228

所以说,当我们对某一个神经元的权值改变一点点时,就会引起一系列的改变,最终导致损失函数的改变。

从以上解读可以看出,误差是如何正向传播的。所以说,如果我们想要计算某一层的某一个神经元的误差,就可以从后往前推导,也就是 反向传播算法了!

 

参考文献:

  1. an online book《Neural Networks and Deep Learning》chap2
  2. 这里有一个具体的例子——Charlotte77 博客:一文弄懂神经网络中的反向传播法——BackPropagation

One thought on “BP算法到底是如何进行误差反向传播的?

  1. Pingback: BP神经网络概述——反向传播算法 – 安逸轩

发表评论

电子邮件地址不会被公开。 必填项已用*标注