编程语言应用

首页 » 常识 » 诊断 » 详解BP神经网络基本原理及C语言
TUhjnbcbe - 2021/1/11 4:14:00
儿童会得白癜风吗         http://baidianfeng.39.net/a_zjwd/190603/7189464.html

BP(BackPropagation)即反向传播,指的是一种按照误差反向传播来训练神经网络的方法。而BP神经网络即为一种按照误差反向传播的方法训练的神经网络,是一种应用十分广泛的神经网络。

BP神经网络主要可以解决以下两种问题:

分类问题:用给定的输入向量和标签训练网络,实现网络对输入向量的合理分类。

函数逼近问题:用给定的输入向量和输出向量训练网络,实现对函数的逼近。

本文主要介绍BP神经网络的基本结构,而后简单介绍用C语言实现神经网络必需要用到的语法知识(老手请放心跳过),最后一步一步从构建单个神经元开始到完成整个神经网络的构建和训练。

VS安装及新建工程安装过程

由于本文主要还是面向初学者,考虑到有些小白朋友的需求,所以还是简单介绍下软件安装和使用,此部分可选择性跳过。

先给出软件的百度云下载链接:VS。

下载完成后如下图。

解压后,如下图所示。

双击运行如下的exe文件。

出现下图所示的界面,在此可以修改安装位置,建议设置成全英文路径。

之后按照默认设置一路下一步到安装完成即可。但安装完成后默认不会生成桌面快捷方式,需要从开始菜单栏运行,也可以从开始菜单栏创建桌面快捷方式。

新建工程

首先运行VS,得到如下界面。

点击左上角的“文件"-"新建”-"项目"。在下图所示的界面上可以修改保存名称和路径。

选择“visualc++”-“Win2控制台应用程序"后点击“确定”,出现如下界面。

单击下一步,如下图所示。

勾选“空项目”后单击“完成”后,出现如下界面,此处重点是观察右侧的工程结构。

我们在右边的“解决方案管理器”选择“源文件”,右键选择“添加”-“新建项”,如下图所示。

在出现的新界面的下方重命名为main.cpp,如下图所示。

按照相同的方法在源文件中再添加一个neuralnetwork.cpp,在头文件中添加neuralnetwork.h。

最后完成的工程结构非常简单,如下图所示。

我们写点简单的代码,测试下整个工程能否编译通过,三部分的代码如下。

main.cpp

#includestdio.h#include"neural_network.h"intmain(){printf("HelloWork\n");}

neural_network.cpp:

#include"neural_network.h"

neural_network.h:

#ifndef__NEURAL_NETWORK_H#define__NEURAL_NETWORK_H#endif

这是个简单的测试程序,如果一切正常就会输出HelloWorld,至此软件安装和工程新建就结束了。

BP神经网络原理人工神经元模型

人工神经元模型如下图所示。

一般神经元模型包含这样几个要素:

输入:X1、X2、X......Xn(可以有多个)。

权重:W1、W2、W......Wn。

偏置:Bias。

激活函数:f(x)。

输出:y(仅一个)。

这里需要重点说明的是激活函数。如果不加入激活函数,只是简单的对输入进行加权求和,那么整个模型就是个线性模型,而线性模型的表示能力是非常有限的,因此通过加入激活函数的方式给模型引入非线性因素,以提高模型的表示能力,所以一般情况下会采用非线性函数作为激活函数。常见的激活函数有Sigmoid、Tanh、Step、ReLU、Softmax等。

本文只用Sigmoid函数,下图给出了Sigmoid函数图像。

现在神经元模型的结构比较清楚了,下面看看如何计算模型的输出。通过给定的权重对输入进行加权求和后(默认加上偏置Bias),再将得到的和作为参数输入一个激活函数,得到的激活函数的输出值即为神经元的输出。

对应的数学公式如下:

下面举个例子来说明一下计算输出的过程。

设X1=1,X2=0,X=0,W1=0.1,W2=0.2,W=0.,Bias=0.1,f(x)=x。

由上面给出的计算公式可得:

z=X1W1+X2W2+X*W+Bias=0.1+0+0+0.1=0.2

y=f(z)=z=0.2

学过初高中生物的朋友应该可以看出,人工神经元模型的X1、X2、X作为输入,和生物神经元的树突是非常相似的。而模型的y作为唯一的输出,和生物神经元的轴突也是非常相似。仔细观察对比还能发现更多的相似之处,此处不做更多讨论。

下面简单介绍一下人工神经元模型的训练方法。为了减少不必要的演示计算步骤,这里我们用只有两个输入一个输出(只有X1、X2)的模型进行演示,方法如下。

先给模型一个任意权值和偏置,设W1=0,W2=0,Bias=0,再设激活函数为:

再给定两组训练用的数据,模拟一个简单的二分类问题:

第一组:data1=1,data2=1,期望输出aim_output1=1

第二组:data=-1,data=-1,期望输出aim_output2=0

然后我们先把第一组data代入模型根据前面所说的计算神经元输出的方法进行计算,得到实际输出real_output1=f(data1W1+data2W2+Bias)=f(0)=0。

实际输出realoutput1和期望输出aimoutput1之间就存在一个差值err1=aimoutput1-realoutput1=1。

根据这个差值,可以通过如下公式来修正我们随机给定的权值和偏置:

W1=W1+etaerr1data1

W2=W2+etaerr1data2

Bias=Bias+eta*err1

这里的eta表示学习率,一般取0~1之间的值。eta值越大学习速率也越快,也就是每一次训练,权值和偏置的变动越大,但也并不是越大越好。如果eta过大容易产生震荡而不能稳定到目标值,若eta值越小,则效果相反。这里我们简单的取eta=1,带入计算式可得经过一次修正过后的权值和偏置:

W1=1,W2=1,Bias=1

注意,这里第一次训练还没结束,还要继续代入第二组的data,并且要记住W1、W2、Bias已经改变,通过相同的方法计算输出:

real_output2=f(dataW1+dataW2+Bias)=f(-1-1+1)=0

计算差值为:

err2=aimoutput2-realoutput2=0

由于实际输出和期望输出没有误差,所以不用修正权值和偏置(也可以看做变化量为0)。

这样第一次训练结束,继续下一次训练。

还是先把第一组data代入模型进行计算得到实际输出:

real_output1=f(data1W1+data2W2+Bias)=f(11+11+1)=1

计算差值:

err1=aimoutput1-realoutput1=0

由于实际输出和期望输出没有误差,所以不修正权值和偏置。

再把第二组data代入模型得输出:

real_output2=f(dataW1+dataW2+Bias)=f(-1-1+1)=0

计算差值:

err2=aimoutput2-realoutput2=0

由于实际输出和期望输出没有误差,所以不修正权值和偏置。

至此训练完成,这个模型已经能对输入的两组数据准确分类,现在给出解决这个二分类问题的C语言代码。

#includestdio.h#includestdlib.h//定义训练用的数据doubledata1[2]={1,1};doubledata2[2]={-1,-1};//定义数据的标准分类doubledata1_class=1;//假设data1的类型为1doubledata2_class=0;//假设data2的类型为0//定义权重和偏置doublew[2]={0,0};//这里用任意值初始化即可,训练的目的就是自动调整这个值的大小doubleb=0;//加权求和doublesumfun(double*data,double*weight,doublebias){return(data[0]*weight[0]+data[1]*weight[1]+bias);}//这里采用阶跃函数作为激活函数doublestep(doublesum){if(sum0)return1;elsereturn0;}intmain(){doublesum=0;//存放加权求和的值doubleoutput1=0,output2=0;//把加权求和的值代入激活函数而得到的输出值intcount=0;//训练次数的计数变量doubleerr=0;//计算的误差,用于对权值和偏置的修正intflag1=0,flag2=0;//训练完成的标志,如果某组数据训练结果达标,则把标志置1,否则置0while(1){sum=sumfun(data1,w,b);//代入第一组data进行计算output1=step(sum);if(output1==data1_class)//判断输出是否达标,若达标则把标志置1,否则修正权值和偏置flag1=1;else{flag1=0;err=data1_class-output1;w[0]=w[0]+err*data1[0];w[1]=w[1]+err*data1[1];b=b+err;}sum=sumfun(data2,w,b);//代入第二组data进行计算output2=step(sum);if(output2==data2_class)//判断输出是否达标,若达标则把标志置1,否则修正权值和偏置flag2=1;else{flag2=0;err=data2_class-output2;w[0]=w[0]+err*data2[0];w[1]=w[1]+err*data2[1];b=b+err;}printf("第%d次训练的输出如下:\n",count+=1);//输出训练结果printf("第一组data属于%1.0f类\n",output1);printf("第一组data属于%1.0f类\n",output2);if(flag1==1flag2==1)//如果所有数据都训练达标,则直接跳出循环{break;}}printf("\n\n模型训练完成!!\n\n");return0;}

运行结果如下图所示。

和我们的计算结果一致,也是第二次训练得出正确的分类。

阅读全文请扫描

下方

1
查看完整版本: 详解BP神经网络基本原理及C语言