Nevermore. 发表于 2014-7-30 15:36

大家,各位高手,帮帮一起讨论下我的BP神经网络C语言程序吧,急急急


#include<stdio.h>
#include<stdlib.h>
#include<math.h>
#include<malloc.h>

#define TRUE         1
#define FALSE        0

#define NUM_LAYERS   3
#define NUM          124        //训练实例个数
#define N            5         //输入层单元数
#define M            1         //输出层单元数

int Units = {N,7,M};   //每层单元数
        FILE *fp,*fb;

typedef struct                //训练实例
{
        float x;
        float y;
}TRAIN;

typedef struct                //网络层结构
{
        int Units;               //该层中单元的个数
        float *Output;           //第 i 个单元的输出
        float *Error ;            //第 i 个单元的校正误差
        float **Weight;          //第 i 个单元的连接权值
}LAYER;

typedef struct                        //网络
{
        LAYER **Layer;                     //隐层定义
        LAYER *Inputlayer;                 //输入层
        LAYER *Outputlayer;                //输出层
        float Error;                       //允许误差
        float Eta;                         //学习率
}NET;

//初始化伪随机数发生器
void InitializeRandoms()
{
        srand(4711);
        return;
}

//产生随机实数并规范化
float RandomReal()                      //产生(-0.5,0.5)之间的随机数
{
        return (float)(((rand()%200)-100)/200.0);
}

//初始化训练数据
void InitializeTrainingData(TRAIN *training)
{
        int i,j;
        char filename;
        printf("\n请输入训练实例的数据文件名: \n");
        gets(filename);
        fb = fopen(filename,"r");
        fprintf(fp,"\n\n--Saving initialization training datas ...\n");
        for(i=0;i<NUM;i++)
        {
                for(j=0;j<N;j++)
                {
                        fscanf(fb,"%f",&(training+i)->x);
                        fprintf(fp,"%10.4f",(training+i)->x);
                }
                for(j=0;j<M;j++)
                {
                        fscanf(fb,"%f",&(training+i)->y);
                        fprintf(fp,"%10.4f",(training+i)->y);
                }
                fprintf(fp,"\n");
        }
        fclose(fb);
        return;
}

//应用程序初始化
void InitializeApplication(NET *Net)
{
        Net->Eta = (float)0.3;
        Net->Error = (float)0.0001;
        fp = fopen("BPResultData.txt","w+");
        return;
}

//应用程序关闭时终止打开的文件
void FinalizeApplication(NET *Net)
{
        fclose(fp);
        return;
}

//分配内存,建立网络
void GenerateNetwork(NET *Net)
{
        int l,i;
        Net->Layer = (LAYER **)calloc(NUM_LAYERS,sizeof(LAYER *));
        for(l=0;l<NUM_LAYERS;l++)
        {
                Net->Layer = (LAYER *)malloc(sizeof(LAYER));
                Net->Layer->Units      = Units;
                Net->Layer->Output     = (float *) calloc(Units+1,sizeof(float));
                Net->Layer->Error      = (float *) calloc(Units+1,sizeof(float));
                Net->Layer->Weight     = (float **)calloc(Units+1,sizeof(float *));
                Net->Layer->Output  = 1;
                if(l != 0)
                        for(i=1;i <= Units;i++)                          //下标从"1"开始
                                Net->Layer->Weight = (float *)calloc(Units+1,sizeof(float));
        }
        Net->Inputlayer  = Net->Layer;
        Net->Outputlayer = Net->Layer;
        return;
}

//产生随机实数作为初始连接权值
void RandomWeights(NET *Net)
{
        int l,i,j;
        for(l=1;l<NUM_LAYERS;l++)
                for(i=1;i <= Net->Layer->Units;i++)
                        for(j=0;j <= Net->Layer->Units;j++)
                                Net->Layer->Weight = RandomReal();
        return;
}

//设置输入层的输出值
void SetInput(NET *Net,float *Input)
{
        int i;
        for(i=1;i <= Net->Inputlayer->Units;i++)
                Net->Inputlayer->Output = Input;                          //输入层采用 u(x) = x
        return;
}

//设置输出层的输出值
void GetOutput(NET *Net,float *Output)
{
        int i;
        for(i=1;i <= Net->Outputlayer->Units;i++)
                Output = (float)(1/(1 + exp(-Net->Outputlayer->Output)));         //输出层采用 f(x)=1/(1+e^(-x))
        return;
}

//层间顺传播
void PropagateLayer(NET *Net,LAYER *Lower,LAYER *Upper)
{
        int i,j;
        float sum;
        for(i=1;i <= Upper->Units;i++)
        {
                sum = 0;
                for(j=1;j <= Lower->Units;j++)
                        sum += (Upper->Weight * Lower->Output);
                Upper->Output = (float)(1/(1 + exp(-sum)));
        }
        return;
}

//整个网络所有层间的顺传播
void PropagateNet(NET *Net)
{
        int l;
        for(l=0;l < NUM_LAYERS-1;l++)
                PropagateLayer(Net,Net->Layer,Net->Layer);
        return;
}

//计算输出层误差
void ComputeOutputError(NET *Net,float *target)
{
        int i;
        float Out,Err;
        for(i=1;i <= Net->Outputlayer->Units;i++)
        {
                Out = Net->Outputlayer->Output;
                Err = target - Out;
                Net->Outputlayer->Error = Out*(1-Out)*Err;
        }
        return;
}

//层间逆传播
void BackpropagateLayer(NET *Net,LAYER *Upper,LAYER *Lower)
{
        int i,j;
        float Out,Err;
        for(i=1;i <= Lower->Units;i++)
        {
                Out = Lower->Output;
                Err = 0;
                for(j=1;j <= Upper->Units;j++)
                        Err += (Upper->Weight * Upper->Error);
                Lower->Error = Out*(1-Out)*Err;
        }
        return;
}

//整个网络所有层间的逆传播
void BackpropagateNet(NET *Net)
{
        int l;
        for(l=NUM_LAYERS-1;l>1;l--)
                BackpropagateLayer(Net,Net->Layer,Net->Layer);
        return;
}

//权值调整
void AdjustWeights(NET *Net)
{
        int l,i,j;
        float Out,Err;
        for(l=1;l<NUM_LAYERS;l++)
                for(i=1;i <= Net->Layer->Units;i++)
                        for(j=0;j <= Net->Layer->Units;j++)
                        {
                                Out = Net->Layer->Output;
                                Err = Net->Layer->Error;
                                Net->Layer->Weight += (Net->Eta*Err*Out);
                        }
        return;
}

//网络处理过程
void SimulateNet(NET *Net,float *Input,float *Output,float *target,int TrainOrNot)
{
        SetInput(Net,Input);                             //输入数据
        PropagateNet(Net);                               //模式顺传播
        GetOutput(Net,Output);                           //形成输出
        ComputeOutputError(Net,target);                  //计算输出误差
        if(TrainOrNot)
        {
                BackpropagateNet(Net);                       //误差逆传播
                AdjustWeights(Net);                          //调整权值
        }
        return;
}

//训练过程
void TrainNet(NET *Net,TRAIN *training)
{
        int l,i,j,k;
        int count=0,flag=0;
        float Output,outputfront,ERR,err,sum;
        do
        {
                flag = 0;
                sum = 0;
                ERR = 0;
                if(count >= 1)
                        for(j=0;j<M;j++)
                                outputfront=Output;
                SimulateNet(Net,(training+(count%NUM))->x,Output,(training+(count%NUM))->y,TRUE);
                if(count >= 1)
                {
                        k = count%NUM;
                        for(i=1;i <= Net->Outputlayer->Units;i++)
                        {
                                sum += Net->Outputlayer->Error;
                                err = (training+k-1)->y - outputfront;
                                ERR += (outputfront * (1 - outputfront) * err);
                        }
                        if(sum <= ERR)
                                Net->Eta = (float)(0.9999 * Net->Eta);
                        else
                                Net->Eta = (float)(1.0015 * Net->Eta);

                }
                if(count >= NUM)
                {
                        for(k=1;k <= M;k++)
                                if(Net->Outputlayer->Error > Net->Error)
                                {   flag=1;     break;   }
                        if(k>M)
                                flag=0;
                }
                count++;
        }while(flag || count <= NUM);
        fprintf(fp,"\n\n\n");
        fprintf(fp,"--training results ... \n");
        fprintf(fp,"training times:   %d\n",count);
        fprintf(fp,"\n*****the final weights*****\n");
        for(l=1;l<NUM_LAYERS;l++)
        {
                for(i=1;i <= Net->Layer->Units;i++)
                {
                        for(j=1;j <= Net->Layer->Units;j++)
                                fprintf(fp,"%15.6f",Net->Layer->Weight);
                        fprintf(fp,"\n");
                }
                fprintf(fp,"\n\n");
        }
}

//评估过程
void EvaluateNet(NET *Net)
{
        int i;
        printf("\n\n(");
        fprintf(fp,"\n\n(");
        for(i=1;i <= Net->Inputlayer->Units;i++)
        {
                printf(" %.4f",Net->Inputlayer->Output);
                fprintf(fp,"%10.4f",Net->Inputlayer->Output);
        }
        printf(")\t");
        fprintf(fp,")\t");
        for(i=1;i <= Net->Outputlayer->Units;i++)
        {
                if(fabs(Net->Outputlayer->Output - 1.0) <= 0.0499)
                {
                        printf("肯定是第 %d 类, ",i);
                        fprintf(fp,"肯定是第 %d 类, ",i);
                }
                if(fabs(Net->Outputlayer->Output - 0.9) <= 0.0499)
                {
                        printf("几乎是第 %d 类,  ",i);
                        fprintf(fp,"几乎是第 %d 类, ",i);
                }
                if(fabs(Net->Outputlayer->Output - 0.8) <= 0.0499)
                {
                        printf("极是第 %d 类, ",i);
                        fprintf(fp,"极是第 %d 类, ",i);
                }
                if(fabs(Net->Outputlayer->Output - 0.7) <= 0.0499)
                {
                        printf("很是第 %d 类, ",i);
                        fprintf(fp,"很是第 %d 类, ",i);
                }
                if(fabs(Net->Outputlayer->Output - 0.6) <= 0.0499)
                {
                        printf("相当是第 %d 类,  ",i);
                        fprintf(fp,"相当是第 %d 类,  ",i);
                }
                if(fabs(Net->Outputlayer->Output - 0.5) <= 0.0499)
                {
                        printf("差不多是第 %d 类, ",i);
                        fprintf(fp,"差不多是第 %d 类, ",i);
                }
                if(fabs(Net->Outputlayer->Output - 0.4) <= 0.0499)
                {
                        printf("比较像是第 %d 类, ",i);
                        fprintf(fp,"比较像是第 %d 类, ",i);
                }
                if(fabs(Net->Outputlayer->Output - 0.3) <= 0.0499)
                {
                        printf("有些像是第 %d 类, ",i);
                        fprintf(fp,"有些像是第 %d 类, ",i);
                }
                if(fabs(Net->Outputlayer->Output - 0.2) <= 0.0499)
                {
                        printf("有点像是第 %d 类, ",i);
                        fprintf(fp,"有点像是第 %d 类, ",i);
                }
                if(fabs(Net->Outputlayer->Output - 0.1) <= 0.0499)
                {
                        printf("稍稍像是第 %d 类, ",i);
                        fprintf(fp,"稍稍像是第 %d 类, ",i);
                }
                if(Net->Outputlayer->Output <= 0.0499)
                {
                        printf("肯定不是第 %d 类, ",i);
                        fprintf(fp,"肯定不是第 %d 类, ",i);
                }
        }
        printf("\n\n");
        fprintf(fp,"\n\n\n");
        return;
}

//测试过程
void TestNet(NET *Net)
{
        TRAIN Testdata;
        float Output;
        int i,j,flag=0;
        char select;
        fprintf(fp,"\n\n--Saving test datas ...\n");
        do
        {
                printf("\n请输入测试数据(x1,x2,x3,x4,x5,y): \n");
                for(j=0;j<N;j++)
                {
                        scanf("%f",&Testdata.x);
                        fprintf(fp,"%10.4f",Testdata.x);
                }
                for(j=0;j<M;j++)
                {
                        scanf("%f",&Testdata.y);
                        fprintf(fp,"%10.4f",Testdata.y);
                }
                fprintf(fp,"\n");
                SimulateNet(Net,Testdata.x,Output,Testdata.y,FALSE);
                fprintf(fp,"\n--NET Output and Error of the Test Data ....\n");
                for(i=1;i <= Net->Outputlayer->Units;i++)
                        fprintf(fp,"%10.6f  %10.6f\n",Net->Outputlayer->Output,Net->Outputlayer->Error);
                EvaluateNet(Net);
                printf("\n继续测试?(y/n):\n");
                getchar();
                scanf("%c",&select);
                printf("\n");
                if((select == 'y')||(select == 'Y'))
                        flag = 1;
                else
                        flag=0;
        }while(flag);
        return;
}


void OUTPUT(NET *Net)
{
    float  a={0.0};
    float  b={0.0};
        float  sum1={0.0};
        float  sum2={0.0};;
        float test;
        //int i,j,k;
    fprintf(fp,"\n\n--true input datas ...\n");
        printf("\n请输入要判别岩性的自然伽马值、密度值、中子值、声波时差值、深电阻率值:\n\n");
        for(int i=0;i<N;i++)
                {
                        scanf("%f",&test);
                        fprintf(fp,"%10.4f",test);
        }


        for(int l=1;l<NUM_LAYERS;l++)
        {
                if(l==1)
                {
                        for(int i=1;i <= Net->Layer->Units;i++)
                        {
                                for(int j=1;j <= Net->Layer->Units;j++)
                                                (float)sum1+=test*Net->Layer->Weight;
                                (float)a=1/(1+exp(-sum1));
                        }
                        printf("\n");
                }

                if(l==2)
                {
                        for(int i=1;i <= Net->Layer->Units;i++)
                        {
                                for(int j=1;j <= Net->Layer->Units;j++)
                                                (float)sum1+=a*Net->Layer->Weight;
                                (float)a=1/(1+exp(-sum1));
                                printf("%f\t",a);
                        }
                }
        }
}


//主函数
void main()
{
        TRAIN TrainingData;
        NET Net;
        InitializeRandoms();                                  //初始化伪随机数发生器
        GenerateNetwork(&Net);                                //建立网络
        RandomWeights(&Net);                                  //形成初始权值
        InitializeApplication(&Net);                          //应用程序初始化,准备运行
        InitializeTrainingData(TrainingData);                 //记录训练数据
        TrainNet(&Net,TrainingData);                          //开始训练
        TestNet(&Net);
        OUTPUT(&Net);
        FinalizeApplication(&Net);                            //程序关闭,完成善后工作
        return;
}


页: [1]
查看完整版本: 大家,各位高手,帮帮一起讨论下我的BP神经网络C语言程序吧,急急急