📄 bp网络识别.c
字号:
//
//bp网络识别
//
//训练集4,输入单元46(有阈值-1),输出单元4,隐层1,隐单元10
//学习率0.05,允许误差上限0.005,最大迭代次数5000
//
//"训练.txt"存放图2.1训练集合
//"识别1.txt"存放图2.2识别集合
//"识别2.txt"存放图2.3识别集合
//"识别3.txt"存放图2.4识别集合
//"result.txt"存放输出结果。
#include "stdio.h"
#include "math.h"
#define TRAINNUM 4 //训练集总数
#define INPUTNUM 46 //输入层单元个数
#define OUTPUTNUM 4 //输出层单元个数
#define MASKNUM 10 //隐层单元个数
#define BETA 1 //Segmiod函数中的参数Beta
#define ETA 0.05 //学习率
#define VAREPSILON 0.005 //误差控制
#define TIMES 50000 //迭代次数控制
double E; //误差
int Cycletimes; //迭代次数
int Input[TRAINNUM+1][INPUTNUM+1]; //输入向量
int Expectation[TRAINNUM+1][OUTPUTNUM+1]; //期望输出向量
double Output[TRAINNUM+1][OUTPUTNUM+1]; //实际输出向量
double reOutput[TRAINNUM+1][OUTPUTNUM+1]; //实际输出向量
double innerProduct[TRAINNUM+1][TRAINNUM+1]; //内积
double w_in[MASKNUM+1][INPUTNUM+1]; //输入层和隐层之间的权值
double w_out[OUTPUTNUM+1][MASKNUM+1]; //输出层和隐层之间的权值
FILE *out,*in;
/********************读取训练集********************/
void ReadData()
{
int j,n,m;
for(j=1;j<=TRAINNUM;j++)
{
for(n=1;n<=INPUTNUM;n++)
fscanf(in,"%d",&Input[j][n]);//输入向量
for(m=1;m<=OUTPUTNUM;m++)
fscanf(in,"%d",&Expectation[j][m]);//期望输出向量
}
}
/********************输出结果********************/
void WriteData()
{
int j,m;
for(j=1;j<=TRAINNUM;j++)
{
for(m=1;m<=OUTPUTNUM;m++)
{
fprintf(out,"%f\t",reOutput[j][m]);
}
fprintf(out," +||+ ");
for(m=1;m<=TRAINNUM;m++)//与已知第i组
{
fprintf(out,"%f\t",innerProduct[j][m]);
}
fprintf(out,"\n");
}
fprintf(out,"/////////////////////////////////////\n");
}
/********************随机赋初始权值********************/
void PrimalWeight()
{
int i,j;
double RandomSgn;
srand((unsigned)time(NULL));
//输出层和隐层之间的权值
for(i=1;i<=OUTPUTNUM;i++)
{
for(j=1;j<=MASKNUM;j++)
{
RandomSgn=fmod((double)rand(),2.0);
if(RandomSgn<0.001)
w_out[i][j]=(-1)*((rand()%9000)+1000)/100000.0*5;
else
w_out[i][j]=((rand()%9000)+1000)/100000.0*5;
}
}
//输入层和隐层之间的权值
for(i=1;i<=MASKNUM;i++)
{
for(j=1;j<=INPUTNUM;j++)
{
RandomSgn=fmod((double)rand(),2.0);
if(RandomSgn<0.001)
w_in[i][j]=(-1)*((rand()%9000)+1000)/100000.0*5;
else
w_in[i][j]=((rand()%9000)+1000)/100000.0*5;
}
}
}
/********************Segmoid型函数********************/
double Segmoid(double x)
{
double y;
x=x*BETA;
y=(exp(x)-exp(-x))/(exp(x)+exp(-x));
return(y);
}
/********************Segmoid型函数的导函数********************/
double DerivativeSeg(double x)
{
double y;
y=BETA*(1-Segmoid(x)*Segmoid(x));
return(y);
}
/********************训练并修改权值********************/
void Training()
{
int p,n,m,j;
double sum; //辅助量(E)
double ssum[TRAINNUM+1];
double tao[TRAINNUM+1][MASKNUM+1]; //隐层输出
double H[TRAINNUM+1][OUTPUTNUM+1];//辅助量(w_out[][]*tao[]相加)
double h[TRAINNUM+1][MASKNUM+1];//辅助量(w_in[][]*Input[]相加)
E=0.0;//误差赋初值
//////////计算实际输出向量//////////
for(j=1;j<=TRAINNUM;j++)//训练集//
{
sum=0.0;
for(m=1;m<=OUTPUTNUM;m++)//输出层单元//
{
H[j][m]=0.0;
for(p=1;p<=MASKNUM;p++)//隐层单元//
{
h[j][p]=0.0;
for(n=1;n<=INPUTNUM;n++)//输入层单元//
{
h[j][p]=h[j][p]+w_in[p][n]*Input[j][n];
}
tao[j][p]=Segmoid(h[j][p]);//活化函数作用,计算出隐层输出
H[j][m]=H[j][m]+w_out[m][p]*tao[j][p];
}
Output[j][m]=Segmoid(H[j][m]);//活化函数作用,计算出实际输出
sum=sum+(Output[j][m]-Expectation[j][m])*(Output[j][m]-Expectation[j][m]);
}
//////////计算误差//////////
E=E+sum;
}
E=E/2.0;
//////////误差后向传播//////////
//////////修改输出层和隐层之间的权值//////////
for(m=1;m<=OUTPUTNUM;m++)//输出层单元//
{
for(p=1;p<=MASKNUM;p++)//隐层单元//
{
sum=0.0;
for(j=1;j<=TRAINNUM;j++)//训练集//
{
sum=sum+(Expectation[j][m]-Output[j][m])*DerivativeSeg(H[j][m])*tao[j][p];
}
w_out[m][p]=w_out[m][p]+ETA*sum;
}
}
//////////修改输入层和隐层之间的权值//////////
for(p=1;p<=MASKNUM;p++)//隐层单元//
{
for(n=1;n<=INPUTNUM;n++)//输入层单元//
{
sum=0.0;
for(j=1;j<=TRAINNUM;j++)//训练集//
{
ssum[j]=0.0;
for(m=1;m<=OUTPUTNUM;m++)//输出层单元//
{
ssum[j]=ssum[j]+(Expectation[j][m]-Output[j][m])*DerivativeSeg(H[j][m])*w_out[m][p];
}
sum=sum+DerivativeSeg(h[j][p])*ssum[j]*Input[j][n];
}
w_in[p][n]=w_in[p][n]+ETA*sum;
}
}
}
/********************识别函数********************/
void Recognise()
{
int p,n,m,j,i,k;
double sum; //辅助量(E)
double tao[TRAINNUM+1][MASKNUM+1]; //隐层输出
double H[TRAINNUM+1][OUTPUTNUM+1];//辅助量(w_out[][]*tao[]相加)
double h[TRAINNUM+1][MASKNUM+1];//辅助量(w_in[][]*Input[]相加)
E=0.0;//误差赋初值
//////////计算实际输出向量//////////
for(j=1;j<=TRAINNUM;j++)//训练集//
{
sum=0.0;
for(m=1;m<=OUTPUTNUM;m++)//输出层单元//
{
H[j][m]=0.0;
for(p=1;p<=MASKNUM;p++)//隐层单元//
{
h[j][p]=0.0;
for(n=1;n<=INPUTNUM;n++)//输入层单元//
{
h[j][p]=h[j][p]+w_in[p][n]*Input[j][n];
}
tao[j][p]=Segmoid(h[j][p]);//活化函数作用,计算出隐层输出
H[j][m]=H[j][m]+w_out[m][p]*tao[j][p];
}
reOutput[j][m]=Segmoid(H[j][m]);//活化函数作用,计算出实际输出
sum=sum+(reOutput[j][m]-Output[j][m])*(reOutput[j][m]-Output[j][m]);
}
//////////计算误差//////////
E=E+sum;
}
E=E/2.0;
//////////计算内积//////////
for(k=1;k<=TRAINNUM;k++)//第k组
{
for(i=1;i<=TRAINNUM;i++)//与已知第i组
{
innerProduct[k][i]=0.0;
for(j=1;j<=OUTPUTNUM;j++)//第j个分量
{
innerProduct[k][i]+=(reOutput[k][j]-Output[i][j])*(reOutput[k][j]-Output[i][j]);
}
}
}
}
/********************主函数********************/
main()
{
int j,m;
int tag;
tag=1;//训练中止标识
Cycletimes=0;
in=fopen("训练.txt","r");
ReadData(); //从训练.txt中读取训练集
fclose(in);
PrimalWeight(); //随机赋初始权值
while(tag)
{
Cycletimes++;//迭代次数加1
Training(); //一次训练(修改权值和计算误差)
printf("%d ",Cycletimes);
printf("%f\n",E);//跟踪每次迭代误差E
if((Cycletimes>TIMES)||(E<VAREPSILON))//结束条件
tag=0;
}
out=fopen("result.txt","a+");
if((Cycletimes==(TIMES+1))&&(E>VAREPSILON))
{
fprintf(out,"失败!!!!!!!!\n");
fprintf(out,"Don't give up,come on!~ :)\n");
}
else{
fprintf(out,"Success!!!!!!!!\n");
fprintf(out,"You did a good job!~ :)\n");
fprintf(out,"迭代次数:%d\n",Cycletimes);
fprintf(out,"误 差:%f\n",E);
fprintf(out,"训练期望输出:\n");
for(j=1;j<=TRAINNUM;j++)
{
for(m=1;m<=OUTPUTNUM;m++)
{
fprintf(out,"%d\t",Expectation[j][m]);
}
fprintf(out,"\n");
}
fprintf(out,"训练实际输出:\n");
for(j=1;j<=TRAINNUM;j++)
{
for(m=1;m<=OUTPUTNUM;m++)
{
fprintf(out,"%f\t",Output[j][m]);
}
fprintf(out,"\n");
}
}
fprintf(out,"/////////////////////////////////////\n");
{
in=fopen("识别1(污染2个点).txt","r");
ReadData(); //从识别1.txt中读取识别集
fclose(in);
Recognise();
fprintf(out,"识别1与训练实际输出之间的误差为:%f\n",E);
fprintf(out,"识别1实际输出:\n");
WriteData();//输出结果到result.txt
}
{
in=fopen("识别2(污染5个点).txt","r");
ReadData(); //从识别1.txt中读取识别集
fclose(in);
Recognise();
fprintf(out,"识别2与训练实际输出之间的误差为:%f\n",E);
fprintf(out,"识别2实际输出:\n");
WriteData();//输出结果到result.txt
}
{
in=fopen("识别3(污染9个点).txt","r");
ReadData(); //从识别1.txt中读取识别集
fclose(in);
Recognise();
fprintf(out,"识别3与训练实际输出之间的误差为:%f\n",E);
fprintf(out,"识别3实际输出:\n");
WriteData();//输出结果到result.txt
}
fprintf(out,"////////////////////////////////////////////////////////////\n");
fclose(out);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -