📄 mybp1.c
字号:
#include <stdio.h>
#include <math.h>
#include <conio.h>
#include <stdlib.h>
#define ni 81//隐层单元数量
#define nk 30 //样本数量
#define nr 0.80/*学习效率*/
#define EPS 0.001
float x[nk];//输入样本数组
float d[nk];//与输入样本数组对应的期望的输出数组
float whi[ni];//输入节点到隐层各个节点的边的权值数组
float wij[ni];//隐层各个节点到输出节点的边的权值数组
int h,i,j,k; //用于循环计数
float xmin,xmax,dmin,dmax; //用于对输入和输出归一化
FILE *fp1,*fp2;//两个文件指针分别用于指向样本文件sample.txt和权值文件w.txt
void clrscr(void);//清屏函数
void init(void); //初始化输入样本以及期望的输出数组
void startlearning(void); //通过样本学习
void testsample(void); //测试
void readw(void); //从文件w.txt读权值
void writew(); //将权值更新到文件w.txt中
float sigmoid(float a); //用S型特性函数转换
double ranu(void);
void clrscr(void)
{
int t;
for(t=0;t<40;t++)
printf("\n");
}
void main()
{
fp1=fopen("sample.txt","r");
fp2=fopen("w.txt","r+");
init();
while(1)
{
clrscr();
printf("\t\n Please choose a next task...\n\n");
printf("\t\n (S) to start learning.\n");
printf("\t\n (T) to test samples.\n");
printf("\t\n (R) to resume learning.\n");
printf("\t\n (Q)uit.\n");
switch(getchar())
{
case 's': startlearning();break;
case 't': testsample();break;
case 'r': startlearning();break;
case 'q': exit(0);break;
}
}
fclose(fp1);
fclose(fp2);
}
double ranu(void)
{
static double xrand=3.0;
double m=8589934592.0,
a=30517578125.0;
lp: xrand=fmod(xrand*a,m);
if(xrand>1.0)
return(xrand/m);
else
{
xrand=1.0;
goto lp;
}
}
float sigmoid(float a)
{
return(1.0/(1+exp(-a)));
}
void readw(void)
{
for(i=0;i<ni;i++)
fscanf(fp2,"%f",&whi[i]);
for(i=0;i<ni;i++)
fscanf(fp2,"%f",&wij[i]);
}
void writew(void)
{
rewind(fp2);
for(i=0;i<ni;i++)
fprintf(fp2,"%8.3f ",whi[i]);
fprintf(fp2,"\n\n");
for(i=0;i<ni;i++)
fprintf(fp2,"%8.3f ",wij[j]);
fprintf(fp2,"\n\n");
}
void startlearning(void)
{
long int nt,n;
float t;//临时变量
float error[nk];//样本误差数组
float gerror;//学习的全局误差
float xj;//输出节点的净输入
float xi[ni];//隐层各节点净输入的数组
float yj;//输出节点的输出
float yi[ni];//隐层结点的输出数组
float pxi[ni];//隐层单样本点误差变化率
float pxj; //输出层单样本点误差变化率
if(fp2==0)
{
for(i=0;i<ni;i++)
{
whi[i]=-0.1+0.2*ranu();
wij[i]=-0.1+0.2*ranu();
}
fp2=fopen("w.txt","w+");
}
else
readw();
/*学习开始*/
printf("\t\nPlease enter the learning times:\n");
scanf("%ld",&nt);
for(n=0;n<nt;n++) /*学习次数*/
{
gerror=0;
for(k=0;k<nk;k++)/*单样本循环*/
{
for(i=0;i<ni;i++) //求隐层输出
{
t=0;
t+=whi[i]*x[k];
xi[i]=t;
yi[i]=sigmoid(xi[i]);
}
//求输出层输出
t=0;
for(i=0;i<ni;i++)
t+=wij[i]*yi[i];
xj=t;
yj=sigmoid(xj);
//输出层单样本点误差变化率
pxj=yj*(1-yj)*(yj-d[k]);
for(i=0;i<ni;i++)//隐层单样本点误差变化率
{
t=0;
t+=pxj*wij[i];
pxi[i]=yi[i]*(1-yi[i])*t;
}
//修正隐层到输出层的权值
for(i=0;i<ni;i++)
wij[i]=wij[i]-nr*pxj*yi[i];
//修正输入层到隐层的权值
for(i=0;i<ni;i++)
{
whi[i]=whi[i]-nr*pxi[i]*x[k];
}
//求该样本K当前误差
t=0;
t+=(yj-d[k])*(yj-d[k])/2.0;
error[k]=t;
gerror+=error[k];//计算全局误差 g(lobal)error
}/*单样本循环结束*/
if(gerror<EPS)
break;
}/* 学习循环结束*/
writew();
printf("\t\nGlobal error=%8.3f\n",gerror);
printf("\t\nAre you satisfied with the global error?\n");
printf("Press any key to choose a next task!\n");
getch();
}
void testsample(void)
{
float tx,t,xj,xi[ni],yj,yi[ni];
if(fp2==0)
{
clrscr();
printf("\t\ncan not find the weight file:w.txt\n");
exit(0);
}
readw();
printf("\t\nPlease enter the test data:\n");
scanf("%f",&tx);
// tx[h]=fmod(tx[h],360.0);
tx=(tx-xmin)/(xmax-xmin);
for(i=0;i<ni;i++)
{
t=0;
t+=whi[i]*tx;
xi[i]=t;
yi[i]=sigmoid(xi[i]);
}
t=0;
for(i=0;i<ni;i++)
t+=wij[i]*yi[i];
xj=t;
yj=sigmoid(xj);
printf("\t\nNetwork output:\n");
yj=yj*(dmax-dmin)+dmin;
printf("%f ",yj);
printf("\t\nAre you satisfied with the output?\n");
printf("Press any key to choose a next task!\n");
getch();
}
void init(void)
{
int min,max;
if(fp1==0)
{
clrscr();
printf("Can not find the learning sample file!\n");
exit(0);
}
for(k=0;k<nk;k++)
{
//初始化训练样本的输入集合
fscanf(fp1,"%f",&x[k]);
//初始化训练样本的输出集合
fscanf(fp1,"%f",&d[k]);
}
//对输入归一化
min=1;max=1;
for(k=0;k<nk;k++)
{
if(x[k]<x[min])
min=k;
if(x[k]>x[max])
max=k;
}
xmin=x[min];
xmax=x[max];
for(k=0;k<nk;k++)/*归一化*/
x[k]=(x[k]-xmin)/(xmax-xmin);
//输出期望值的归一化
min=1;max=1;
for(k=0;k<nk;k++)
{
if(d[k]<d[min])
min=k;
if(d[k]>d[max])
max=k;
}
dmin=d[min];
dmax=d[max];
for(k=0;k<nk;k++)/*归一化*/
d[k]=(d[k]-dmin)/(dmax-dmin);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -