Press "Enter" to skip to content

Numpy编写BP传播过程全解

本站内容均来自兴趣收集,如不慎侵害的您的相关权益,请留言告知,我们将尽快删除.谢谢.

 

 

©PaperWeekly 原创 · 作者|孙裕道

 

学校|北京邮电大学博士生

 

研究方向|GAN图像生成、情绪对抗样本生成

 

 

引言

 

BP反向传播矩阵推导图示详解 一文中在矩阵视角下对 BP 的原理进行了详细的介绍, 神经网络中权重的梯度由前一层前向传播值与后一层的误差值整合计算得到 。该文中也对吴恩达的斯坦福机器学习的讲义中的相关部分进行了证明。

 

BP 的矩阵形式的推导的好处在于它的矩阵表示形式对编程非常有指导意义,当前有很多的热门的深度学习框架,例如 Pytorch 和 Tensorflow,像这种深度学习框架集成性很高,神经网络中 BP 更新参数的过程几行代码就搞定,这对于从代码中理解其原理造成了一定的困难。

 

Numpy 编写 BP 更新参数的过程则是一个好的方式去了解其原理, 代码链接如下:

 

https://github.com/guidao20/BP_Numpy

 

文件并不复杂,两个 py 文件加一个 mnist 数据集。本文会对该代码进行详细的介绍。

 

 

 

预备知识

 

一个 4 层的神经网络如下图所示,各个层的维度分别是 784,128,64,10;神经网络的权重分别为,,,具体的前向计算过程如下所示。

 

 

▲ 图1.神经网络前向计算过程

 

根据 BP 反向传播矩阵推导图示详解 中 Section 6 的推导过程可得到各层网络的权重梯度计算示意图(示意图中各字母代表的含义查阅 BP 反向传播矩阵推导图示详解 的 Section 6)。

 

 

▲ 图2.神经网络BP原理

 

BP 反向传播矩阵推导图示详解 中的 Section 8 是对吴恩达机器学习讲义中的关于BP 原理部分的等价证明,所以可以将上图 2 的示意图重新整理如下,其中反向传播的误差的计算公式在图中蓝色字体。本文的要介绍的 Numpy 代码就按照下图的形式进行编程。

 

 

▲ 图3.神经网络BP原理(吴)

 

 

代码详解

 

本文的代码结构非常简单如下图所示一共三个文件。data 文件夹下是 mnist 手写体数字集的压缩包 mnist.pkl.gz;mnist_loader.py 是用于加载 mnist 数据集的;BP_Numpy.py 是 BP 训练神经网络的程序,也是本文重点要讲的程序。

 

 

由图 4 可知程序中使用的激活函数为 Sigmoid 函数,其中 Sigmoid 函数的定义为:

 

 

Sigmoid 函数的导数定义为:

 

 

 

▲ 图4.Sigmoid函数及其导数

 

图 5 是类 NerualNetwork 的初始化,进而构建一个神经网络,分别对神经网络的尺寸(有几层,每一层的单元数是多少),每一层的权重和偏置进行初始化。

 

 

▲ 图5.类初始化

 

图 6 是神经网络的前向计算过程,先做线性变换,然后再进行激活。以 Section 2 预备知识中图 1 的神经网络为例(以便更清楚的交代出各个矩阵的维度)。假如一共有四层神经网络,各个层的单元数为 784,128,64,10,根据代码则前向计算过程可以归结为:

 

 

▲ 图6.前向计算过程

 

图 7 是 BP 反向传播求梯度的过程,图 7 中的 黄色框区域 是用列表存储前计算的激活值,最后求出损失函数,这里损失函数为。这里需要注意的是 反向传播求梯度并不是不需要前向计算值 。图 7 中的蓝色框区域是计算输出层的权重梯度,对应于图 3 中的计算过程:

 

 

图 7 中的绿色框区域是从后往前以此计算各个层的权重梯度,对应于图 3 中和的计算过程:

 

 

这里需要注意的是符号表示的是矩阵相乘,符号表示的是向量元素对应位置相乘。另外程序中有对偏置求梯度的操作,其原理跟求解权重的原理类似。

 

 

▲ 图7. BP反向传播

 

图 8 主要是对神经网络参数进行更新(图中红框所示),以上操作将各个层的权重和偏置的梯度求解出来,再利用梯度下降对各个层的权重和偏置的参数进行更新。

 

 

▲ 图8.权重和偏置更新

 

设置学习率的步长为 0.1,epoch 为 1000,batch_size 为 10,则可得到如下图程序结果,由结果可知,通过 BP 求解参数梯度,再利用梯度下降法,损失函数整体是减小的。

 

 

▲ 图9.权重和偏置更新

 

Be First to Comment

发表评论

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