Bp神经网络+C实现_第1页
Bp神经网络+C实现_第2页
Bp神经网络+C实现_第3页
Bp神经网络+C实现_第4页
Bp神经网络+C实现_第5页
已阅读5页,还剩21页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

Bp神经网络+C++实现

0前言

神经网络在我印象中一直比较神秘,正好最近学习了神经网络,

特别是对Bp神经网络有了比较深入的了解,因此,总结以下心得,希

望对后来者有所帮助。

神经网络在机器学习中应用比较广泛,比如函数逼近,模式识别,

分类,数据压缩,数据挖掘等领域。神经网络本身是一个比较庞大的

概念,从网络结构类别来划分,大概有:多层前馈神经网络、径向基

函数网络(RBF)、自适应谐振理论网络(ART)、自组织映射网络

(SOM)、级联相关网络、Elman网络、Boltzmann机、受限

Boltzmann机等等。

下面一张图是最近比较流行的网络结构:

Amostlycompletechartof

OBackfedInputCell

NeuralNetworksDeepFeedForward(OFF)

InputCell02016FjodorvanVeen-

△NoisyInputCell

Perceptron(P)FeedForward(FF)FadialBasisNetwork(RBF)

•HiddenCell

OProbablisticHiddenCell

△SpikingHiddenCell

GatedRecurrentUnit(GRU)

OutputCell

OMatchInputOutputCell

•RecurrentCell

OMemoryCell

AutoEncoder(AE)VariationalAE(VAE)DenoisingAE(DAE)SparseAE(SAE)

DifferentMemoryCell

Kernel

ConvolutionorPool

MarkovChain(MC)HopfieldNetwork(HN)BoltzmannMachine(BM)RestrictedBM(RBM)DeepBeliefNetwork(DBN)

DeepConvolutionalNetwork(DCN)DeconvolutionalNetwork(DN)DeepConvolutionalInverseGraphicsNetwork(OCIGN)

GenerativeAdversarialNetwork(GAN)liquidStateMachine(LSM)ExtremeLearningMachine(ELM)EchoStateNetwork(ESN)

DeepResidualNetwork(CRN)KohonenNetwork(KN)SupportVectorMachine(SVM)NeuralTuringMachine(NTM)

今天我们要介绍的是Bp神经网络,准确的说是采用Bp算法进行

训练的多层前馈神经网络,Bp算法应用比较广泛。

1基本概念:

1.1神经元模型

机器学习中所谈论的神经网络源于生物上的神经网络,实际上指

的是〃神经网络〃与〃机器学习〃的交叉部分,一个最简单的M-P神

经元模型如下图所示:

\4=1

该神经元收到来自其他n个输入神经元传递过来的输入信号(加

权和的形式),然后将其与神经元的阈值进行比较,通过激活函数进

行处理,产生神经元的输出。

1.2常用激活函数

激活函数的作用是对其他所有神经元传过来的所有信号加权和进

行处理,产生神经元输出。

下图是常用的激活函数,最简单的是:阶跃函数,它简单,最理

想,但是性质最差(不连续/不光滑),因此在实际中,最常用的是

Sigmoid函数。

PlotEquationDerivative

Identity/f(c)=Xrs)=i

/

/..Wv=f0forx<0w/_fofor工a0

Binarystep_r_zt1forx>Q,⑺x龙(?for工=0

Logistic(a.k.a

)-l+LAx)=/(z)(l-/(z))

Softstep)人工

2

Tarfl/(工)=tanh(x)=2,1/")=1-/(x)2

1If

ArcTan/(1)=tan-1(z),⑺-工2+i

Rectified

“、f0forz<0...x(0forx<0

LinearUnit=tzforz>0/(X)=l1forz>0

(ReLU)

Parapeteric

a

Rectified//、(axforz<0f>\-fx<0

//(X)=lzforz>0(x

LinearUnit/㈤-(1forx>0

(PReLU)121/

Exponentialx

f>(Tx-Jf()+°hr4V。

LinearUnit八)-(1forx>0

(EUD⑶

70/、1/4.X\…1

1.3前馈神经网络

多层前馈神经网络的准确定义:每一层神经元与下一层神经元全

互连,神经元之间不存在同层连接,不存在跨层连接,如下图所示就

是一个经典的前馈神经网络,

(随便插一句,当神经网络中隐层数越来越多,达到8-9层E寸,

就变成了一个深度

学习模型,我曾在一篇论文中看到网络结构有达128层的,关于

下面这块,下面还会再叙述)O

2.标准Bp算法

2.0关于梯度

首先我们应该清楚,一个多元函数的梯度方向是该函数值增大最

陡的方向。具体化到1元函数中时,梯度方向首先是沿着曲线的切线

的,然后取切线向上增长的方向为梯度方向,2元或者多元函数中,梯

度向量为函数值f对每个变量的导数,该向量的方向就是梯度的方向,

当然向量的大小也就是梯度的大小。

梯度下降法(steepestdescendmethod)用来求解表达式最大或

者最小值的,属于无约束优化问题。梯度下降法的基本思想还是挺简

单的,现假设我们要求函数f的最小值,首先得选取一个初始点后,然

后下一个点的产生时是沿着梯度直线方向,这里是沿着梯度的反方向

(因为求的是最小值,如果是求最大值的话则沿梯度的正方向即可),如

2.1神经网络学习过程

神经网络在外界输入样本的刺激下不断改变网络的连接权值,以使

网络的输出不断地接近期望的输出,讲几个要点:

(1)学习过程可以简述为:

(2)学习的本质:对各连接权值以及所有功能神经元的阈值动

态调整

注:可以将权值与阈值的学习统一为权值的学习,即将阈值看成

一个〃哑节点〃,如下图所示:

(3)权值调整规则:即在学习过程中网络中各神经元的连接权

变化所依据的一定的调整规则,(Bp算法中权值调整采用的是梯度下

降策略,下面会详细介绍)

Bp网络的学习流程如下图所示:

(百度图库里搜的,能说明问题就行)

2.2权值调整策略:

首先说明一句』神经网络学习属于监督学习的范畴。每输入一个

样本,进行正向传播(输入层一隐层一输出层),得到输出结果以后,计

算误差,达不到期望后,将误差进行反向传播(输出层一隐层一输入

层),采用梯度下降策略对所有权值和阈值进行调整。

对训练例(耿,如),假定神经网络的输出为yk=(片次…4),即

-=/(-一%),

则网络在{xk,yk)上的均方误差为

g_1'、/八"«.*、2

注:上面的Ek是根据第k个样本数据算出的误差,可以看出:标

准Bp算法每次迭代更新只针对单个样例。

权值与阈值的调整公式如下:

(D采用感知机学习规则:VV

(2)梯度下降法:即以训练样本被错分的程度为目标函数,训练中每次出现错误时便使权系

数朝着目标函数相对于权系数负梯度方向更新,知道目标中没有被错分的样本为止。

△w》=rjgjbh9j=/(1一磅)域-Vj)

△%=-V9jif

绢:--若微•需仆“一

△。访=TJChXi,

QR.

△7h=-T)eh,瓦力=":学习率"

:十.1-右二〜止匕:出东V/\小且工M人珏+皿山WzGA+n田诙苴工后二大T珏

上述公式的详细推导过程见下图:

篇标本,舔力余乂夕八灯…

蝌及二彳⑹叫)

-E"舂笊-犷.

r,夕J-,

俸的栩酬移*

①dWq

也二"刀繇购恶二埠••巡必

J2的,?〜"5的Mj.叼

二阴7;),电-M〉bh

二瓶1-曲途琴心/

”人力«4lVhi二”丁,9,Zi_0F,/髡一曲b二刀9;b,,

订年二2劭-%).

Q)Av7h.'\,

42万瑞,楚歌二嗫■赛篇二琳加巨产由—M

统林东二者端*二者须打一^^1台网句人心)X;

:收入?、/少卜二k力瑞;二一力务w^.%b力"b力)冷’

\二力l^cHh^whj^jXf.^.ne^]

:----------------Y,

:助

y峥f翳火崎二寄•瑞二-哈力伽物

.二W-外)曾,中

彳3=〉/用二一力金,I-95(小■赛)--力加

'防/的4金

c..^.、U、,__lZ

2.3BP神经网络总结

(1)BP神经网络一般用于分类或者逼近问题。

如果用于分类,则激活函数一般选用Sigmoid函数或者硬极限函

数,如果用于函数逼近,则输出层节点用线性函数。

(2)BP神经网络在训练数据时可以采用增量学习或者批量学习。

一增量学习要求输入模式要有足够的随机性,对输入模式的噪声

比较敏感,即对于剧烈变化的输入模式,训练效果比较差,适合在线

处理。

一批量学习不存在输入模式次序问题,稳定性好,但是只适合离

线处理。

(3)如何确定隐层数以及每个隐含层节点个数

Pre隐含层节点个数不确定,那么应该设置为多少才合适呢(隐含

层节点个数的多少对神经网络的性能是有影响的)?

有一个经验公式可以确定隐含层节点数目:

h=y/m+n+a

.(其中h:隐含层节点数目,m:为输入层节点数目,n:为输出层

节点数目,a:为之间的调节常数)。

2.4标准BP神经网络的缺陷

(1)容易形成局部极小值而得不到全局最优值。

(采用梯度下降法),如果仅有一个局部极小值二〉全局最小,多

个局部极小二〉不一定全局最小。这就要求对初始权值和阀值有要求,

要使得初始权值和阀值随机性足够好,可以多次随机来实现。

(2)训练次数多使得学习效率低,收敛速度慢。

每次更新只针对单个样本;不同样例出现〃抵消〃现象。

(3)过拟合问题

通过不断训练,训练误差达到很低,但测试误差可能会上升(泛

化性能差).

解决策略:

1,〃早停〃:

即将样本划分成训练集和验证集,训练集用来算梯度,更新权值

和阈值,验证集用来估计误差,当训练集误差降低而验证集误差升高

时就停止训练,返回具有最小验证集误差的权值和阈值。

2,〃正则化方法〃:

_tm(v***'CSLUS人

,即在误差目标中增加一个用于描述网络复杂程度的部分,其中

参数人常用交叉验证来确定。

2.5BP算法的改进

(1)累积BP算法

目的:为了减小整个训练集的全局误差,而不针对某一特定样本

1/W?

B*4rL乙A..9\Lr»

(更新策略做相应调整)

(2)利用动量法改进BP算法

(标准Bp学习过程易震荡,收敛速度慢)

增加动量项,引入动量项是为了加速算法收敛,即如下公式:

a为动量系数,通常0<a<0.9o

(3)自适应调节学习率n

调整的基本指导思想是:在学习收敛的情况下,增大n,以缩短学

习时间;当n偏大致使不能收敛(即发生震荡)时,要及时减小n,直

到收敛为止。

3工程搭建与C++实现

实验平台:vs2013

项目包含文件:

个>QKK(H:)>BpNet>Bphet>

项目流程如下图所示:

初始化网络结构

(3层前馈神经网络)

用测试数据测试

(1)Bp.h

#ifndef_BP_H_

#define_BP_H_

#include<vector>

〃参数设置

#defineLAYER3〃三层神经网络

#defineNUM10〃每层的最多节点数

#defineA30.0

#defineB10.0//A和B是S型函数的参数

#defineITERS1000〃最大训练次数

#defineETA_W0.0035〃权值调整率

#defineETA.B0.001〃阀值调整率

#defineERROR0.002〃单个样本允许的误差

#defineACCU0.005〃每次迭代允许的误差

〃类型

#defineTypedouble

#defineVectorstd::vector

structData

(

Vector<Type>x;〃输入属性

Vector<Type>y;〃输出属性

);

classBP{

public:

voidGetData(constVector<Data>);

voidTrain();

Vector<Type>ForeCast(constVector<Type>);

voidForCastFromFile(BP*&);

voidReadFile(constchar*InutFileNamejntm,intn);

voidReadTestFile(constchar*InputFileName,intmzintn);

voidWriteToFile(constchar*OutPutFileName);

private:

voidInitNetWorkO;〃初始化网络

voidGetNumsO;〃获取输入、输出和隐含层节点数

voidForwardTransfer();〃正向传播子过程

voidReverseTransfer(int);〃逆向传播子过程

voidCalcDelta(int);〃计算w和b的调整量

voidUpdateNetWork();〃更新权值和阀值

TypeGetError(int);〃计算单个样本的误差

TypeGetAccuQ;〃计算所有样本的精度

TypeSigmoid(constType);〃计算Sigmoid的值

voidsplit(char*bufferzVector<Type>&vec);

private:

intin_num;〃输入层节点数

intou_num;〃输出层节点数

inthd_num;〃隐含层节点数

Vector<Data>data;〃样木数据

Vector<Vector<Type>>testdata;〃测试数据

Vector<Vector<Type>>result;〃测试结果

introwLen;〃样本数量

intrestrowLen;〃测试样本数量

Typew[LAYER][NUM][NUM];//BP网络的权值

Typeb[LAYER][NUM];//BP网络节点的阀值

Typex[LAYER][NUM];〃每个神经元的值经S型函数转化后

的输出值,输入层就为原值

Typed[LAYER][NUM];〃记录delta学习规则中delta的值,

使用delta规则来调整联接权重Wij(t+l)=Wij(t)+a(Yj-Aj(t))Oi(t)

);

#endif//_BP_H_

(2)Bp.cpp

#include<string.h>

#include<stdio.h>

#include<math.h>

#include<assert.h>

#include<cstdlib>

#include<fstream>

#include<iostream>

usingnamespacestd;

#include"Bp.h"

〃获取训练所有样本数据

voidBP::GetData(constVector<Data>_data)

data=_data;

)

voidBP::split(char*bufferzVector<Type>&vec)

(

char*p=strtok(buffer,"z");/At

while(p!=NULL)

(

vec.push_back(atof(p));

p=strtok(NULL/"\n");

)

)

voidBP::ReadFile(constchar*InutFileName,intmJntn)

(

FILE*pFile;

//Test

//pFile=fopen("D:\\testSet.txt\"r");

M

pFile=fopen(InutFileNamez"r);

if(!pFile)

(

printf("openfile%sfailed...\n"/InutFileName);

exit(O);

)

//initdataSet

char*buffer=newchar[100];

Vector<Type>temp;

while(fgets(buffer,100,pFile))

(

Datat;

temp.clearO;

split(bufferztemp);

//data[x].push_back(temp);

for(inti=0;i<temp.size();i++)

(

if(i<m)

t.x.push_back(temp[i]);

else

t.y.push_back(temp[i]);

)

data.push_back(t);

)

//initrowLen

rowLen=data.size();

)

voidBP::ReadTestFile(constchar*InputFileName,intm,int

n)

(

FILE*pFile;

pFile=fopen(InputFileName,"r");

if(IpFile)

printf("openfile%sfailed...\n"/InputFileName);

exit(O);

)

//initdataSet

char*buffer=newchar[100];

Vector<Type>temp;

while(fgets(buffer,100,pFile))

(

Vector<Type>t;

temp.clearO;

split(bufferztemp);

for(inti=0;i<temp.size();i++)

(

t.push_back(temp[i]);

)

testdata.push_back(t);

)

restrowLen=testdata.size();

)

voidBP::WriteToFile(constchar*OutPutFileName)

(

ofstreamfout;

fout.open(OutPutFileName);

if(!fout)

cout<<"fileresult.txtopenfailed"<<endl;

exit(O);

)

Vector<Vector<Type>>::iteratorit=testdata.begin();

Vector<Vector<Type>>::iteratoritx=result.begin();

while(it!=testdata.end())

(

Vector<Type>::iteratoritt=(*it).begin();

Vector<Type>::iteratorittx=(*itx).begin();

while(itt!=(*it).end())

(

fout<<(*itt)<<

itt++;

)

fout<<"\t";

while(ittx!=(*itx).end())

(

fout<<(*ittx)<<

ittx++;

)

it++;

itx++;

fout<<"\n";

)

)

〃开始进行训练

voidBP::Train()

printf("BegintotrainBPNetWork!\n");

GetNums();

InitNetWork();

intnum=data.sizeQ;

for(intiter=0;iter<=ITERS;iter++)

(

for(intent=0;ent<num;cnt++)

(

〃第一层输入节点赋值

for(inti=0;i<in_num;i++)

x[0][i]=data.at(cnt).x[i];

while(1)

(

ForwardTransfer();

if(GetError(cnt)<ERROR)〃如果误差比较小,则针对单个样

本跳出循环

break;

ReverseTransfer(cnt);

)

)

printf("Thisisthe%dthtrainningNetWork!\n"ziter);

Typeaccu=GetAccuQ;〃每一轮学习的均方误差E

printf("AIISamplesAccuracyis%lf\n"/accu);

if(accu<ACCU)break;

)

printf("TheBPNetWorktrainEnd!\n");

)

〃根据训练好的网络来预测输出值

Vector<Type>BP::ForeCast(constVector<Type>data)

(

intn=data.sizeO;

assert(n==in_num);

for(inti=0;i<in_num;i++)

x[0][i]=data[i];

ForwardTransfer();

Vector<Type>v;

for(inti=0;i<ou_num;i++)

v.push_back(x[2][i]);

returnv;

)

voidBP::ForCastFromFile(BP*&pBp)

(

Vector<Vector<Type>>::iteratorit=testdata.begin();

Vector<Type>ou;

while(it!=testdata.end())

(

ou=pBp->ForeCast(*it);

result.push_back(ou);

it++;

)

)

〃获取网络节点数

voidBP::GetNums()

(

in_num=data[O].x.size();〃获取输入层节点数

ou.num=data[O].y.size();〃获取输出层节点数

hd_num=(int)sqrt((in_num+ou_num)*1.0)+5;〃获取隐

含层节点数

if(hd_num>NUM)hd_num=NUM;〃隐含层数

目不能超过最大设置

)

〃初始化网络

voidBP::InitNetWork()

(

memset(wz0,sizeof(w));〃初始化权值和阀值为0,也可以初

始化随机值

memset(bz0,sizeof(b));

)

〃工作信号正向传递子过程

voidBP::ForwardTransfer()

(

〃计算隐含层各个节点的输出值

for(intj=0;j<hd_num;j++)

(

Typet=0;

for(inti=0;i<in_num;i++)

t+=w[l][i][j]*x[0][i];

t+=b[l][j];

x[l][j]=Sigmoid(t);

)

〃计算输出层各节点的输出值

for(intj=0;j<ou_num;j++)

(

Typet=0;

for(inti=0;i<hd_num;i++)

t+=w[2][i][j]*x[l][i];

t+=b[2][j];

x[2][j]=Sigmoid(t);

)

)

〃计算单个样本的误差

TypeBP::GetError(intent)

(

Typeans=0;

for(inti=0;i<ou_num;i++)

ans+=0.5*(x[2][i]-data.at(cnt).y[i])*(x[2][i]

data.at(cnt).y[i]);

returnans;

)

〃误差信号反向传递子过程

voidBP::ReverseTransfer(intent)

CalcDelta(cnt);

UpdateNetWork();

)

〃计算所有样本的精度

TypeBP::GetAccu()

(

Typeans=0;

intnum=data.size();

for(inti=0;i<num;i++)

(

intm=data.at(i).x.size();

for(intj=0;j<m;j++)

x[0][j]=data.at(i).x[j];

ForwardTransfer();

intn=data.at(i).y.size();〃样本输出的维度

for(intj=0;j<n;j++)

ans+=0.5*(x[2][j]-data.at(i).y[j])*(x[2][j]-data.at(i).y[j]);//

对第i个样本算均方误差

)

returnans/num;

〃计算调整量

voidBP::CalcDelta(intent)

(

〃计算输出层的delta值

for(inti=0;i<ou_num;i++)

d[2][i]=(x[2][i]-data.at(cnt).y[i])*x[2][i]*(A-x[2][i])/(A*

B);

〃计算隐含层的delta值

for(inti=0;i<hd_num;i++)

Typet=0;

for(intj=0;j<ou_num;j++)

t+=w[2][i][j]*d[2][j];

d[l][i]=t*x[l][i]*(A-x[l][i])/(A*B);

)

)

〃根据计算出的调整量对BP网络进行调整

voidBP::UpdateNetWork()

(

〃隐含层和输出层之间权值和阀值调整

for(inti=0;i<

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

最新文档

评论

0/150

提交评论