反向传播神经网络(BP网络)介绍及Java实现
来源:互联网 发布:java中classpath和path 编辑:程序博客网 时间:2024/06/06 10:07
在之前的文章中我简单展望过人工智能。并提出过神经网络是一个核心技术,今天我就要介绍神经网络的经典算法反向传播神经网络(Backpropagation Neural Network)。
BP网络由DE Rumelhart, GE Hinton等于1986年提出(值得注意的是GE Hinton也是深度学习的奠基人),它是最经典的一个神经网络算法。神经网络是一组连接的输入/输出神经元,每个连接都有相对应的权重。如图,是一个典型的多层前馈(multilayer feed-forward)神经网络结构。它由一个输入层、一个输出层和多个隐藏层组成。在给出输入后,经过层层网络,最后得到一个输出。而神经网络算法本质就是找为各连接找出合适的权值。
网络计算过程
在讨论BP算法前,还是先明确一下,在上面的网络中得到权值后,具体的计算过程到底是怎么回事。首先明确,上图中的输入层其实是我们要分类的样本的各特征,而隐藏层和输出层每个圆圈都代表了一个sigmoid单元。如下图所示,sigmoid的计算过程为:首先得到各输入与常数1的和
算法过程
下面先给出BP神经网络的算法过程
算法中的终止条件可以是到达一定的迭代次数或到达一定的准确度。可以看出算法本身并不复杂,后面要讲的推导也不会比高等数学的题难推,就是几个数学公式比较复杂。可是算法却有十分神奇的能力,所以有机会一定把数学学好。
算法推导
梯度下降
可以从上面的算法过程看出,BP算法其实就是不断根据输出与实际值的误差来更新各连接权值。那么什么样的权值是最好的,我们中学应该都学过最小二乘法,即每一个输出与实际值差值的平方的和最小,即误差函数最小。在BP网络中,误差这样定义:
所以我们的目的是使误差值最小。那么如何使该误差函数取的最小值,通过计算E关于w的导数,列方程使所有导数都为零?显然是不可行的。所以我们要利用计算机的计算能力去一步步逼近最小值,这里用的方法就是梯度下降(Gradient descend),即朝着梯度下降的方向逐步偏移。
迭代方法推导
在正式推导前我先说明:其实BP算法有两中形式:标准形和随机梯度下降方法。这一点刚开始也让我疑惑了很久:为什么上面每一个样例都要迭代一次?不是应该一次扫一遍数据库,计算出总误差再迭代吗?后面那种其实就是标准形式的梯度下降方法,可是这样计算量大,收敛的速度慢。而每一个样例都迭代速度快,而且还可以避免陷入局部最优。下面我介绍的就是随机梯度下降方式的推导过程。可以看出这种方式的误差函数和上面那个有区别。但后面推导过程其实非常相似。
误差函数:
正式推导前先明确几个标记,可以使后面推导更简洁:
输出单元的误差:
隐藏单元的误差:
可以看出误差更新的过程是从后往前传播,所以算法的名字为反向传播算法
Java实现
算法理解起来可能比较困难,但是整体过程并不复杂,用Java实现,总代码不会超过100行即可实现,但是代码也比较绕,理解起来也会费点劲。下面给出我的实现,或者可以下载我的整个工程,我这个项目是用BPNN做手写体识别,最后效果并不好,不过算法本身是正确的,我用它做过习题。
public double layer[][];//store the output of every unit public double layerErr[][];//store the error of every unit public double layerWeight[][][];//store weights public double layerWeightDelta[][][];//store number of weights adjust public double mobp;// momentum rate public double rate;// adjust steps length /** * initialize the BPNN * @param layernum units number of every layer * @param rate adjust steps length * @param mobp momentum rate */ public BpNN(int[] layernum,double rate,double mobp){ this.rate=rate; this.mobp=mobp; layer=new double[layernum.length][]; layerErr=new double[layernum.length][]; layerWeight=new double[layernum.length][][]; layerWeightDelta=new double[layernum.length][][]; for(int l=0;l<layernum.length;l++){ layer[l]=new double[layernum[l]]; layerErr[l]=new double[layernum[l]];// layerWeight[l]=new double[layernum[l]+1][];// layerWeightDelta[l]=new double[layernum[l]+1][]; if(l+1<layernum.length){ layerWeight[l]=new double[layernum[l]+1][layernum[l+1]]; layerWeightDelta[l]=new double[layernum[l]+1][layernum[l+1]]; for(int x=0;x<layernum[l]+1;x++){ for(int y=0;y<layernum[l+1];y++){ layerWeight[l][x][y]=0.1; } } } } } /** * compute the output from front to back * @param in input vector * @return output vector * */ public double[] compute(double[] in){ for(int l=1;l<layer.length;l++){ for(int j=0;j<layer[l].length;j++){ double z=layerWeight[l-1][layer[l-1].length][j];//constant multiply weights for(int x=0;x<layer[l-1].length;x++){ layer[l-1][x]=l==1?in[x]:layer[l-1][x]; z+=layerWeight[l-1][x][j]*layer[l-1][x]; } layer[l][j]=1/(1+Math.exp(-z)); } } return layer[layer.length-1]; } /** * update weight from back to front * @param tar target values (instances) */ public void updateWeight(double[] tar){ int l=layer.length-1; for(int y=0;y<layer[l].length;y++){ layerErr[l][y]=layer[l][y]*(1-layer[l][y])*(tar[y]-layer[l][y]); } while(l-->0){ for(int j=0;j<layerErr[l].length;j++){ double z=0; for(int i=0;i<layerErr[l+1].length;i++){ z+=l>0?layerErr[l+1][i]*layerWeight[l][j][i]:0;//0 layer is input layer, need not calculate error layerWeightDelta[l][j][i]=mobp*layerWeightDelta[l][j][i]+rate*layerErr[l+1][i]*layer[l][j];//delta weight with momentum layerWeight[l][j][i]+=layerWeightDelta[l][j][i];//update weight of units if(j==layerErr[l].length-1){//update weights of constant layerWeightDelta[l][j+1][i]=mobp*layerWeightDelta[l][j+1][i]+rate*layerErr[l+1][i]; layerWeight[l][j+1][i]+=layerWeightDelta[l][j+1][i]; } } layerErr[l][j]=z*layer[l][j]*(1-layer[l][j]);//compute error } } } public void train(double[] in, double[] tar) { compute(in); updateWeight(tar); } public double[][][] getWeight(){ return layerWeight; } public void setWeight(double[][][] weight){ layerWeight=weight; }
- 反向传播神经网络(BP网络)介绍及Java实现
- 神经网络及反向传播(bp)算法详解
- 反向传播BP模型(属于神经网络)
- 神经网络 反向传播算法(BP)
- 反向传播网络(BP 网络)
- BP 神经网络 反向传播算法
- AI简单介绍(一)反向传播算法、损失函数、CNN、bp神经网络
- 深度神经网络(DNN)反向传播算法(BP)
- 深度神经网络(DNN)反向传播算法(BP)
- 深度神经网络(DNN)反向传播算法(BP)
- 深度神经网络(DNN)反向传播算法(BP)
- 深度神经网络(DNN)反向传播算法(BP)
- 深度神经网络(DNN)反向传播算法(BP)
- 深度神经网络(DNN)反向传播算法(BP)
- Matlab之BP神经网络反向传播算法
- 神经网络的反向传播BP算法
- 神经网络BP反向传播算法Error Backpropagation
- 深度学习|反向传播算法(BP)原理推导及代码实现
- J2EE项目系列(四)--SSM框架构建积分系统和基本商品检索系统(Spring+SpringMVC+MyBatis+Lucene+Redis+MAVEN)(2)建立商品数据库和Lucene的搭建
- scrapy学习记录0401
- 安卓反编译记录
- Wolf从零学编程-用Python打造简单加密程序(五)
- JZOJ1282.【USACO题库】3.2.1 Factorials阶乘
- 反向传播神经网络(BP网络)介绍及Java实现
- android:configChanges
- C语言中隐藏输入的代码
- 欢迎使用CSDN-markdown编辑器
- adb 坑之第三方手机管家如腾讯统一360 刷机助手导致开发出现严重问题解决方案
- Byte[],Stream,Ibuffer,IRandomAccessStream等之间的互相转换(rt,8.1可用,部分Sliverlight 8.1可用)
- 递归算法之汉诺塔问题
- windows错误:microsoft runtime dll 安装程序未能安装
- 使用Android studio的使用心得