📄 bp.cpp
字号:
#include <iostream.h>
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define NULL 0 //网络层数
#define IN 2 //输入层神经元个数 2
#define HN 2 //隐含层神经元个数 2
#define ON 1 //输出层神经元个数 1
#define MODEL 4 //输入模式 4
static int p[IN][MODEL]={{0,0,1,1},{0,1,0,1}}; //输入模式p
static int d[MODEL]={0,1,1,0}; //没组对应的期望输出d
double w[IN][HN] ,dw[IN][HN],b[HN],db[HN]; //隐层权值w及其调整量bw,阈值b及其调整量db
double v[HN][ON] ,dv[HN][ON],r[ON],dr[ON]; //隐层权值v及其调整量bv,阈值b及其调整量dv
double a1[IN][MODEL],a2[MODEL]; //隐层个神经元输出a1(2行4列),输出各层各神经元输出a2(1行4列)
double e2[MODEL],e1[IN][MODEL]; //输出层至隐层反向误差e2,隐层至输出层反向误差e1
double e[MODEL],E; //输出误差e,总平方误差E
double EE=0.0001; //误差指标
double lr=0.75; //学习速率lr
int i,j,k,t,x,n;
double h; //中间过程量h
//程序批处理
void Init() //初始化权值阈值为随机输 -1<(w,b,v,r)<1
{
for(i=0;i<IN;i++)
for(j=0;j<HN;j++)
{
w[i][j]=2.00*rand()/RAND_MAX-1.00;
}
for(j=0;j<HN;j++)
for(t=0;t<ON;t++)
{
v[j][t]=2.00*rand()/RAND_MAX-1.00;
}
for(j=0;j<HN;j++)
{
b[j]=2.00*rand()/RAND_MAX-1.00;
}
for(t=0;t<ON;t++)
{
r[t]=2.00*rand()/RAND_MAX-1.00;
}
}
void Hout() //隐层的输出a1
{
for(j=0;j<HN;j++)
for(k=0;k<MODEL;k++)
{
h=0.00;
for(i=0;i<IN;i++)
{
h=h+w[i][j]*p[i][k];
}
a1[j][k]=1.00/(1.00+exp(-(h+b[j])));
}
}
void Oout() //输出层的输出a2
{
for(t=0;t<ON;t++)
for(k=0;k<MODEL;k++)
{
h=0.00;
for(j=0;j<HN;j++)
{
h=h+v[j][t]*a1[j][k];
}
a2[k]=1.00/(1.00+exp(-(h+r[t])));
}
}
void Tolerate() //输出误差e
{
E=0;
for(k=0;k<MODEL;k++)
{
e[k]=d[k]-a2[k];
E=E+e[k]*e[k]/2.0;
}
cout<<"E="<<E<<'/n';
}
void Btolerate() //反向误差e1,e2
{
for(k=0;k<MODEL;k++)
{
e2[k]=a2[k]*(1-a2[k])*e[k];
}
for(t=0;t<ON;t++)
for(j=0;j<HN;j++)
for(k=0;k<MODEL;k++)
{
e1[j][k]=a1[j][k]*(1.00-a1[j][k])*e2[k]*v[j][t];
}
}
void Change() //权值阈值的调整
{
//所有隐层至输入层反向误差e1乘于学习速率lr
for(j=0;j<HN;j++)
for(k=0;k<MODEL;k++)
{
e1[j][k]=lr*e1[j][k];
}
//输入层至隐层权值w调整
for(i=0;i<IN;i++)
for(j=0;j<HN;j++)
{
dw[i][j]=0.00;
for(k=0;k<MODEL;k++)
{
dw[i][j]+=e1[j][k]*p[i][k];
}
w[i][j]+=dw[i][j];
}
//隐层阈值b调整
for(j=0;j<HN;j++)
{
db[j]=0.00;
for(k=0;k<MODEL;k++)
{
db[j]=db[j]+e1[j][k]; //求所有反向误差e1之和
}
b[j]=b[j]+db[j];
}
//所有输出层至隐层反向误差e2乘以学习速率lr
for(k=0;k<MODEL;k++)
{
e2[k]=lr*e2[k];
}
//隐层至输出层权值v调整
for(t=0;t<ON;t++)
for(j=0;j<HN;j++)
{
dv[j][t]=0.0;
for(k=0;k<MODEL;k++)
{
dv[j][t]=dv[j][t]+e2[k]*a1[j][k];
}
v[j][t]=v[j][t]+dv[j][t];
}
//输出层阈值r的调整
for(t=0;t<ON;t++)
{
dr[t]=0.00;
for(k=0;k<MODEL;k++)
{
dr[t]=dr[t]+e2[k]; //求所有反向误差e2之和
}
r[t]=r[t]+dr[t];
}
}
void Out() //计算训练后的输出结果
{
for(j=0;j<HN;j++)
for(k=0;k<MODEL;k++)
{
h=0.00;
for(i=0;i<IN;i++)
{
h=h+w[i][j]*p[i][k];
}
a1[j][k]=1.00/(1.00+exp(-(h+b[j])));
}
for(t=0;t<ON;t++)
for(k=0;k<MODEL;k++)
{
h=0.00;
for(j=0;j<HN;j++)
{
h=h+v[j][t]*a1[j][k];
}
a2[k]=1.00/(1.00+exp(-(h+r[t])));
}
}
void Oinit() //输出训练结束的权值和阈值
{
cout<<"输入层至隐层权值w:"<<'\n';
for(i=0;i<IN;i++)
{
for(j=0;j<HN;j++)
{
cout<<"w["<<i<<"]["<<j<<"]="<<w[i][j]<<'\t';
}
cout<<'\n';
}
cout<<"隐层阈值b:"<<'\n';
for(j=0;j<HN;j++)
{
cout<<"b["<<j<<"]="<<b[j]<<'\t';
}
cout<<'\n';
cout<<"隐层至输出层权值v:"<<'\n';
for(j=0;j<HN;j++)
for(t=0;t<ON;t++)
{
cout<<"v["<<j<<"]["<<t<<"]="<<v[j][t]<<'\t';
}
cout<<'\n';
cout<<"输出层阈值r:"<<'\n';
for(t=0;t<ON;t++)
{
cout<<"r["<<t<<"]="<<r[t]<<'\t';
}
cout<<'\n';
}
void Nout_tolerate() //训练结果后期望值和网络实际输出误差e
{
for(k=0;k<MODEL;k++)
{
e[k]=d[k]-a2[k];
}
}
void main() //主程序
{
FILE *fp1,*fp2,*fp3,*fp4,*fp5;
Init();
n=0;
fp1=fopen("w00.txt","w");
fp2=fopen("b0.txt","w");
fp3=fopen("v00.txt","w");
fp4=fopen("r0.txt","w");
fp5=fopen("xor.txt","w");
do
{
Hout();
Oout();
Tolerate();
Btolerate();
Change();
fprintf(fp1,"%d%f\n",n,w[0][0]);
fprintf(fp2,"%d%f\n",n,b[0]);
fprintf(fp3,"%d%f\n",n,v[0][0]);
fprintf(fp4,"%d%f\n",n,r[0]);
fprintf(fp5,"%d%f%f%f%f\n",n,w[0][0],b[0],v[0][0],r[0]);
n++;
}while(E>EE); //一直训练到吗组误差指标EE为止
cout<<"训练次数n="<<n<<'\t'<<'\n';
Out();
Oinit();
Nout_tolerate();
cout<<"网络输出"<<" "<<"期望输出"<<" "<<"网络输出"<<" "<<"期望输出与实际值误差"<<'\n';
double O[4][5]={{0,0,0,a2[0],e[0]},{0,1,1,a2[1],e[1]},{1,0,1,a2[2],e[2]},{1,1,0,a2[3],e[3]}};
for(i=0;i<4;i++)
{
for(j=0;j<5;j++)
{
cout<<O[i][j]<<'t';
}
cout<<'\n';
}
cout<<'\n';
fclose(fp1); fclose(fp2); fclose(fp3); fclose(fp4); fclose(fp5);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -