⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mybp1.c

📁 一个用C语言实现的bp算法,用于学习sin曲线.
💻 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 + -