从0开始机器学习-神经网络反向bp算法!(代码片段)

dlonng dlonng     2022-11-29     125

关键词:

最近一个月项目好忙,终于挤出时间把这篇 BP 算法基本思想写完了,公式的推导放到下一篇讲吧。

一、神经网络的代价函数

神经网络可以看做是复杂逻辑回归的组合,因此与其类似,我们训练神经网络也要定义代价函数,之后再使用梯度下降法来最小化代价函数,以此来训练最优的权重矩阵。

1.1 从逻辑回归出发

我们从经典的逻辑回归代价函数引出,先来复习下:

[J( heta) = frac1msumlimits_i = 1^m[-y^(i)log (h_ heta(x^(i)))-( 1-y^(i))log ( 1 - h_ heta(x^(i)))] + fraclambda2m sumlimits_j=1^n heta_j^2 ]

逻辑回归代价函数计算每个样本的输入与输出的误差,然后累加起来除以样本数,再加上正则化项,这个我之前的博客已经写过了:

这里补充一点对单变量逻辑回归代价函数的理解,虽然这一行代价公式很长:

[cost(i) = -y^(i)log (h_ heta(x^(i)))-( 1-y^(i))log ( 1 - h_ heta(x^(i))) ]

但是其实可以把它简单的理解为输出与输入的方差,虽然形式上差别很大,但是可以帮助我们理解上面这个公式到底在计算什么,就是计算输出与输入的方差,这样理解就可以:

[cost(i) = h_ heta(x^(i) - y^(i))^2 ]

1.2 一步步写出神经网络代价函数

前面讲的简单逻辑回归的只有一个输出变量,但是在神经网络中输出层可以有多个神经元,所以可以有很多种的输出,比如 K 分类问题,神经元的输出是一个 K 维的向量:

技术图片

因此我们需要对每个维度计算预测输出与真实标签值的误差,即对 K 个维度的误差做一次求和:

[sumlimits_i = 1^k[-y_k^(i)log (h_ heta(x^(i)))_k-( 1-y_k^(i))log ( 1 - h_ heta(x^(i))_k)] ]

然后累加训练集的 m 个样本:

[-frac1m[sumlimits_i = 1^msumlimits_k = 1^k[-y_k^(i)log (h_ heta(x^(i)))_k-( 1-y_k^(i))log ( 1 - h_ heta(x^(i))_k)]] ]

再加上所有权重矩阵元素的正则化项,注意 (i, j) 都是从 1 开始的,因为每一层的 ( heta_0) 是偏置单元,不需要对其进行正则化:

[fraclambda2msumlimits_i = l^L - 1sumlimits_i = 1^S_lsumlimits_j = 1^S_l + 1( heta_ji^(l))^2 ]

  • 最内层求和:循环一个权重矩阵所有的行,行数是 (S_l + 1) 层激活单元数
  • 中间层求和:循环一个权重矩阵所有的列,列数是 (S_l) 层激活单元数
  • 最外层求和:循环所有的权重矩阵

这就得到了输出层为 K 个单元神经网络最终的代价函数:

[J( heta) = -frac1m[sumlimits_i = 1^msumlimits_k = 1^k[-y_k^(i)log (h_ heta(x^(i)))_k-( 1-y_k^(i))log ( 1 - h_ heta(x^(i))_k)]] + fraclambda2msumlimits_i = l^L - 1sumlimits_i = 1^S_lsumlimits_j = 1^S_l + 1( heta_ji^(l))^2 ]

有了代价函数后,就可以通过反向传播算法来训练一个神经网络啦!

二、神经网络反向 BP(Back Propagation) 算法

2.1 BP 算法简介

之前写神经网络基础的时候,跟大家分享了如何用训练好的神经网络来预测手写字符:从 0 开始机器学习 - 神经网络识别手写字符!,只不过当时我们没有训练网络,而是使用已经训练好的神经网络的权重矩阵来进行前馈预测,那么我们如何自己训练神经网络呢?

这就需要学习反向 BP 算法,这个算法可以帮助我们求出神经网络权重矩阵中每个元素的偏导数,进而利用梯度下降法来最小化上面的代价函数,你可以联想简单的线性回归算法:从 0 开始机器学习 - 一文入门多维特征梯度下降法!,也是先求每个参数的偏导数,然后在梯度下降算法中使用求出的偏导数来迭代下降。

因此训练神经网络的关键就是:如何求出每个权重系数的偏导数?,反向 BP 就可以解决这个问题!这里强烈建议你学习的时候完全搞懂 BP 算法的原理,最好自己独立推导一遍公式,因为你以后学习深度学习那些复杂的网络,不管是哪种,最终都要使用反向 BP 来训练,这个 BP 算法是最核心的东西,面试也逃不过的,所以既然要学,就要学懂,不然就是在浪费时间。

2.2 BP 算法基本原理

我先用个例子简单介绍下 BP 算法的基本原理和步骤,公式的推导放到下一节,反向 BP 算法顾名思义,与前馈预测方向相反:

  • 计算最后一层输出与实际标签值的误差,反向传播到倒数第二层
  • 计算倒数第二层的传播误差,反向传播到倒数第三层
  • 以此类推,一层一层地求出各层的误差
  • 直到第二层结束,因为第一层是输入特征,不是我们计算的,所以不需要求误差

以下面这个 4 层的神经网络为例:

技术图片

假如我们的训练集只有 1 个样本 ((x^(1), y^(1))),每层所有激活单元的输出用 (a^(i)) 向量表示,每层所有激活单元的误差用 (delta^(i)) 向量表示,来看下反向传播的计算步骤(公式的原理下一节讲):

  1. 输出层的误差为预测值减去真实值:(delta^(4) = a^(4) - y^(1))
  2. 倒数第二层的误差为:(delta^(3) = (W^(3))^T delta^(4) * g‘(z^(3)))
  3. 倒数第三层的误差为:(delta^(2) = (W^(2))^T delta^(3) * g‘(z^(2)))
  4. 第一层是输入变量,不需要计算误差

有了每层所有激活单元的误差后,就可以计算代价函数对每个权重参数的偏导数,即每个激活单元的输出乘以对应的误差,这里不考虑正则化:

[frac partialpartial W_ij^(l) J (W) = a_j^(l) delta_i^(l+1) ]

解释下这个偏导数的计算:

  • (l) 表示目前计算的是第几层
  • (j) 表示当前层中正在计算的激活单元下标((j) 作为列)
  • (i) 表示下一层误差单元的下标((i) 作为行)

这个计算过程是对一个样本进行的,网络的输入是一个特征向量,所以每层计算的误差也是向量,但是我们的网络输入是特征矩阵的话,就不能用一个个向量来表示误差了,而是应该也将误差向量组成误差矩阵,因为特征矩阵就是多个样本,每个样本都做一个反向传播,就会计算误差,所以我们每次都把一个样本计算的误差累加到误差矩阵中:

[Delta_ij^(l) = Delta_ij^(l) + a_j^(l) delta_i^(l+1) ]

然后,我们需要除以样本总数 (m),因为上面的误差是累加了所有 (m) 个训练样本得到的,并且我们还需要考虑加上正则化防止过拟合,注意对偏置单元不需要正则化,这点已经提过好多次了:

  • 非偏置单元正则化后的偏导数 (j eq 0)

[D_ij^(l) = frac 1mDelta_ij^(l)+lambda W_ij^(l) ]

  • 偏置单元正则化后的偏导数 (j = 0)

[D_ij^(l) = frac1mDelta_ij^(l) ]

最后计算的所有偏导数就放在误差矩阵中:

[frac partialpartial W_ij^(l) J (W) = D_ij^(l) ]

这样我们就求出了每个权重参数的偏导数,再回想之前的梯度下降法,我们有了偏导数计算方法后,直接送到梯度下降法中进行迭代就可以最小化代价函数了,比如我在 Python 中把上面的逻辑写成一个正则化梯度计算的函数 regularized_gradient,然后再用 scipy.optimize 等优化库直接最小化文章开头提出的神经网络代价函数,以此来使用反向 BP 算法训练一个神经网络:

import scipy.optimize as opt

res = opt.minimize(fun = 神经网络代价函数,
                       x0 = init_theta,
                       args = (X, y, 1),
                       method = ‘TNC‘,
                       jac = regularized_gradient,
                       options = ‘maxiter‘: 400)

所以神经网络反向 BP 算法关键就是理解每个权重参数偏导数的计算步骤和方法!关于偏导数计算公式的详细推导过程,我打算在下一篇文章中单独分享,本次就不带大家一步步推导了,否则内容太多,先把基本步骤搞清楚,后面推导公式就容易理解。

2.3 反向 BP 算法的直观理解

之前学习前馈预测时,我们知道一个激活单元是输入是上一层所有激活单元的输出与权重的加权和(包含偏置),计算方向从左到右,计算的是每个激活单元的输出,看图:

技术图片

其实反向 BP 算法也是做类似的计算,一个激活单元误差的输入是后一层所有误差与权重的加权和(可能不包含偏置),只不过这里计算的反向是从右向左,计算的是每个激活单元的误差,对比看图:

技术图片

你只需要把单个神经元的前馈预测和反向 BP 的计算步骤搞清楚就可以基本理解反向 BP 的基本过程,因为所有的参数都是这样做的。

三、神经网络编程细节

3.1 随机初始化

每种优化算法都需要初始化参数,之前的线性回归初始化参数为 0 是没问题的,但是如果把神经网络的初始参数都设置为 0,就会有问题,因为第二层的输入是要用到权重与激活单元输出的乘积:

  • 如果权重都是 0,则每层网络的输出都是 0
  • 如果权重都是相同的常数 (a),则每层网络的输出也都相同,只是不为 0

技术图片

所以为了在神经网络中避免以上的问题,我们采用随机初始化,把所有的参数初始化为 ([-epsilon, epsilon]) 之间的随机值,比如初始化一个 10 X 11 的权重参数矩阵:

[initheta = rand(10, 11) * (2 * epsilon) - epsilon ]

3.2 矩阵 <-> 向量

注意上面优化库的输入 X0 = init_theta 是一个向量,而我们的神经网络每 2 层之间就有一个权重矩阵,所以为了把权重矩阵作为优化库的输入,我们必须要把所有的权重参数都组合到一个向量中,也就是实现一个把矩阵组合到向量的功能,但是优化库的输出也是一个包含所有权重参数的向量,我们拿到向量后还需要把它转换为每 2 层之间的权重矩阵,这样才能进行前馈预测:

  • 训练前:初始多个权重矩阵 -> 一个初始向量
  • 训练后:一个最优向量 -> 多个最优权重矩阵

技术图片

3.3 梯度校验

梯度校验是用来检验我们的 BP 算法计算的偏导数是否和真实的偏导数存在较大误差,计算以下 2 个偏导数向量的误差:

  • 反向 BP 算法计算的偏导数
  • 利用导数定义计算的偏导数

对于单个参数,在一点 ( heta) 处的导数可由 ([ heta - epsilon, heta + epsilon]) 表示,这也是导数定义的一种:

[grad = fracJ( heta + epsilon) - J( heta - epsilon)2 epsilon ]

如图:

技术图片

但是我们的神经网络代价函数有很多参数,当我们把参数矩阵转为向量后,可以对向量里的每个参数进行梯度检验,只需要分别用定义求偏导数即可,比如检验 ( heta_1)

[frac partial Jpartial heta_1 = frac J ( heta_1 + varepsilon_1, heta_2, heta_3 ... heta_n ) - J( heta_1 - varepsilon_1, heta_2, heta_3 ... heta_n)2 varepsilon ]

以此类推,检验 ( heta_n)

[frac partial Jpartial heta_n = frac J ( heta_1, heta_2, heta_3 ... heta_n + varepsilon_n) - J( heta_1, heta_2, heta_3 ... heta_n - varepsilon_n)2 varepsilon ]

求出导数定义的偏导数后,与 BP 算法计算的偏导数计算误差,在误差范围内认为 BP 算法计算的偏导数(D_vec)是正确的,梯度检验的伪代码如下:

for i = 1 : n
  theta_plus = theta
  theta_plus[i] = theta_plus + epsilon
  
  theta_minu = theta
  theta_minu[i] = theta_minu - epsilon
  
  grad = (J(theta_plus) - J(theta_minu)) / (2 * epsilon)
end

check 误差: grad 是否约等于 D_vec

注意一点:梯度检验通常速度很慢,在训练神经网络前先别进行检验!

今天就到这,溜了溜了,下篇文章见:)

技术图片

机器学习-反向传播算法(bp)代码实现(matlab)(代码片段)

%%MachineLearningOnlineClass-Exercise4NeuralNetworkLearning%Instructions%------------%%Thisfilecontainscodethathelpsyougetstartedonthe%linearexercise.Youwillneedtocompletethefollowingfunctions%inthise 查看详情

简单易学的机器学习算法——神经网络之bp神经网络

一、BP神经网络的概念  BP神经网络是一种多层的前馈神经网络,其基本的特点是:信号是前向传播的,而误差是反向传播的。详细来说。对于例如以下的仅仅含一个隐层的神经网络模型:(三层BP神经网络模型)BP神经网络... 查看详情

反向传播神经网络(bp)(代码片段)

...取整,可得输出矢量T为: 该问题可描述为通过训练BP神经网络实现模糊控制规则T=int((e+ec)/2),并达到网络输出与期望值误差小于0.001。选取较好的BP神经网络参数,包括隐含层节点个数、学习速率等。同时对不同的学习训练... 查看详情

视觉机器学习读书笔记--------bp学习

...m)即BP学习属于监督式学习算法,是非常重要的一种人工神经网络学习方法,常被用来训练前馈型多层感知器神经网络。一、BP学习原理1、前馈型神经网络   是指网络在处理信息时,信息只能由输入层进入网络,随后... 查看详情

bp神经网络公式推导及实现mnist(代码片段)

BP神经网络的基础介绍见:http://blog.csdn.net/fengbingchun/article/details/50274471,这里主要以公式推导为主。BP神经网络又称为误差反向传播网络,其结构如下图。这种网络实质是一种前向无反馈网络,具有结构清晰、易实现、计算功能... 查看详情

机器学习算法神经网络与深度学习-3bp神经网络

目录BP神经网络(Backpropagation)反向传播神经网络,也被叫做多层感知机。输入字段节点个数如何确定BP神经网络的特点:隐藏层个数如何确定BP神经网络如何传递信息BP神经网络如何修正权重值及常数值梯度下降... 查看详情

ai-深度学习之美十四章-概念摘要(8~14)(代码片段)

.../yq.aliyun.com/topic/11108反向传播(BackPropagation,简称BP)算法在神经网络(甚至深度学习)参数训练中,BP算法占据举足轻重的地位。实际上BP算法是一个典型的双向算法,但通常强调的是反向传播。工作流程分两大步:正向传播输入... 查看详情

手推机器学习吴恩达神经网络bp反向传播矩阵推导(上篇)

前言在吴恩达斯坦福机器学习中关于BP算法(BackpropagationAlgorithm)只给出了最后的BP矩阵的推导结果,略去了中间的推导过程,初学者理解起来相当困难。本文给出了BP推导常遇到两种推导形式,并给出了详细... 查看详情

机器学习的两次浪潮——浅层学习和深度学习

...习是机器学习的第一次浪潮20世纪80年代末期,用于人工神经网络的反向传播算法(也叫BackPropagation算法或者BP算法)的发明,给机器学习带来了希望,掀起了基于统计模型的机器学习热潮。这个热潮一直持续到今天。人们发现,... 查看详情

机器学习算法(代码片段)

...支持向量机(SVM)1.基本概念2.代码实现五全连接神经网络DNN1.基本概念全连接神经网络前向传播全连接神经网络反向传播2.代码实现知识补充损失函数回归分析总结一、线性回归1.基本概念线性回归是回归问题中的一种... 查看详情

实现二:bp算法实践|机器学习(代码片段)

目录BP算法(分步)源代码(全部)测试数据集一(鸢尾花集)源代码(全部)测试数据集二(手写数字集)源代码(全部)实验内容:实现BP算法类,并使用两个数据集进行... 查看详情

深度学习基础--神经网络--bp反向传播算法

...函数关系叫做激励函数。)  (假如不使用激励函数,神经网络中的每层都只是做简单的线性变换,多层输入叠加后也还是线性变换。因为线性模型的表达能力不够,激励函数可以引入非线性因素)    下面两幅图分别为... 查看详情

机器学习——bp神经网络详细介绍及案例python代码实现(代码片段)

...m4、m5,最后我的总收益为: 那么问题来了,神经网络可以这么表示(如下图):(二)、反向传播学过Java想必大家都会编写猜数小游戏,你设定一个数,限制猜这个数的次数,比如... 查看详情

机器学习术语表

FFNN  FeedForwardNeuralNetwork  前馈神经网络,神经网络中一般输入向前传递BP  Backpropagation  反向传播,一般专指误差反向传播算法,RBM  RestrictedBoltzmannMachine  限制波兹曼机  受限波兹曼机监督学习  给出data与lab... 查看详情

bp算法基本原理推导----《机器学习》笔记

...rorBackPropagation)算法就是成功的代表,它是迄今最成功的神经网络学习算法。今天就来探讨下BP算法的原理以及公式推导吧。神经网络先来简单介绍一下神经网络,引入基本的计算公式,方便后面推导使用图1神经网络神经元模型... 查看详情

0机器学习算法分类

...on)和回归(Regression),典型的算法有LogisticsRegression、BP神经网络算法和相性回归算法。 监督学习流程:  无监督学习 与监督学习不同的是,无监督学习(UnsupervisedLearning)的训练数据中不包含任何 查看详情

stanfordcoursera机器学习编程作业exercise4--使用bp算法训练神经网络以识别阿拉伯数字(0-9)

在这篇文章中,会实现一个BP(backpropagation)算法,并将之应用到手写的阿拉伯数字(0-9)的自动识别上。训练数据集(trainingset)如下:一共有5000个训练实例(traininginstance),每个训练实例是一个400维特征的列向量(20*20pixelimage)。用X矩阵... 查看详情

反向传播算法

...Werbos[1]首次给出了如何训练一般网络的学习算法,而人工神经网络只是其中的特例。不巧的,在当时整个人工神经网络社群中却无人知晓Paul所提出的学习算法。直到80年代中期,BP算法才重新被DavidRumelhart、GeoffreyHinton 查看详情