Bp网络神经算法

来源:互联网 发布:防火墙软件测试报告 编辑:程序博客网 时间:2024/04/30 02:10

***原型题目在2011年武汉科技大学程序设计大赛,百度文库上有,属于本人上传***

1、权阵可以手动输入,可以随机产生,也可以选择题目要求矩阵

2、手动设置误差限,学习率,隐藏结点等

3、对结果采用模糊语言输出。


#include <stdio.h>#include <stdlib.h>#include <math.h>#include <time.h>#define OUT 2     //输出向量维数#define IN  2     //输入向量维数#define NUM     20     //样本数量#define Loop_MAX 524280 //最大循环次数#define dot_MAX 20 //最大结点个数typedef struct   //bp人工神经网络结构{    int dot;             //隐层节点数    double v[IN][dot_MAX];     //输入层权矩阵double u[dot_MAX][dot_MAX];//隐藏层权矩阵    double w[dot_MAX][OUT];    //输出层权矩阵    double rate;          //学习率    double error;          //允许误差限} bp_net;double fnet(double net)   //Sigmoid函数{     return 1/(1+exp(-net));}void Initialize_Bp(bp_net *bp)   //初始化bp网络{        printf("请输入隐层结点数:\n");        scanf("%d", &(*bp).dot);        printf("请输入学习率:\n");    scanf("%lf", &(*bp).rate);     printf("请输入允许误差限:\n");    scanf("%lf", &(*bp).error);    int i, j;    srand((unsigned)time(NULL));//随机函数产生随机权矩阵    for (i = 0; i < IN; i++)         for (j = 0; j < (*bp).dot; j++)            (*bp).v[i][j] = rand() / (double)(RAND_MAX);    for (i = 0; i < (*bp).dot; i++) for (j = 0; j < (*bp).dot; j++)(*bp).u[i][j] = rand() / (double)(RAND_MAX); for (i = 0; i < (*bp).dot; i++) for (j = 0; j < OUT; j++)(*bp).w[i][j] = rand() / (double)(RAND_MAX);  printf("初始化输入权矩阵:\n");for (i = 0; i < IN; i++) {for (j = 0; j < (*bp).dot; j++)printf("%lf   ",(*bp).v[i][j]); printf("\n");}printf("初始化隐藏层权矩阵:\n");for (i = 0; i < (*bp).dot; i++) {for (j = 0; j < (*bp).dot; j++)printf("%lf   ",(*bp).u[i][j]); printf("\n");}printf("初始化输出权矩阵:\n");for (i = 0; i < (*bp).dot; i++) {for (j = 0; j < OUT; j++)printf("%lf   ",(*bp).w[i][j]); printf("\n");}printf("\n");}void Train_Bp(bp_net *bp, double x[NUM][IN], int y[NUM][OUT])  //训练bp网络{    double e = (*bp).error;               //允许误差限           double rate = (*bp).rate;             //学习率             int dot = (*bp).dot;                  //隐藏层结点          double v[IN][dot_MAX], w[dot_MAX][OUT],u[dot_MAX][dot_MAX];  //权矩阵    double Error_Input[dot_MAX],Error_hider[dot_MAX], Error_Output[OUT];       //各个结点的反向误差    double Input[dot_MAX],hider[dot_MAX], Output[OUT];             //各个层的结点输出    int i, j, k, n,flag;                                 //flag为是否继续修改权矩阵标志量    double temp,t;    for (i = 0; i < IN; i++)                     //复制结构体中的权矩阵         for (j = 0; j < dot; j++)            v[i][j] = (*bp).v[i][j];for (i = 0; i < dot; i++)for (j = 0; j < dot; j++)u[i][j] = (*bp).u[i][j];for (i = 0; i < dot; i++)for (j = 0; j < OUT; j++)w[i][j] = (*bp).w[i][j];for (n = 0;n<Loop_MAX; n++)       //反向误差计算{ flag=1;for (i= 0; i < NUM; i++) { for (k= 0; k < dot; k++)       //计算输入层输出向量{      temp = 0;for (j = 0; j < IN; j++)temp+= x[i][j] * v[j][k];    Input[k] = fnet(temp);}for (k= 0; k < dot; k++)         //计算隐藏层输出向量{      temp = 0;for (j = 0; j < dot; j++)temp+=Input[j] * u[j][k];    hider[k] = fnet(temp);}for (k = 0; k < OUT; k++)          //计算输出层输出向量{temp = 0;for (j = 0; j < dot; j++)temp += hider[j] * w[j][k];Output[k] = fnet(temp);}for (j = 0; j < OUT ; j++)       //测试结果与是否在误差范围内{t=(y[i][j]-Output[j])*(y[i][j]-Output[j]);   t=sqrt(t);//求输出结果与理想输出的误差的绝对值(abs()函数忽略掉小数部分,故不能用)if(t<e)continue;                      //如果满足精度要求,则继续测试下一个结点的情况else{flag=0;                      //修改了权矩阵for (j = 0; j < OUT; j++)                  Error_Output[j] = (y[i][j] - Output[j]);for (j = 0; j < dot; j++)  //计算隐层权修改量{       temp = 0;for (k = 0; k < OUT; k++)temp += w[j][k] * Error_Output[k];Error_hider[j] = temp * hider[j]*(1-hider[j]);}for (j = 0; j < dot; j++)           //修改输出层权矩阵for (k = 0; k < OUT; k++)w[j][k]+= rate * hider[j] * Error_Output[k]; for(j=0;j<dot;j++){temp=0;for(k=0;k<dot;k++)temp+=u[j][k]*Error_hider[k];Error_Input[j]=temp*Input[j]*(1-Input[j]);}for (j = 0; j < dot; j++)for (k = 0; k < dot; k++)u[j][k]+= rate * Input[j] * Error_hider[k];for(j=0;j<IN;j++)for(k=0;k<dot;k++)v[j][k]+=rate*x[i][j]*Error_Input[k];break; //如果一个实例的第一个输出结果不满足精度条件,修改权矩阵后,继续学习下一个实例。}}}if(!flag)continue;elsebreak;}printf("总共循环次数:%d\n", n);printf("\n");printf("修改后的输入权矩阵:\n");   //输出修改后的输入层权矩阵for (i = 0; i < IN; i++) {    for (j = 0; j < dot; j++)printf("%f    ", v[i][j]);    printf("\n");}printf("修改后的隐藏层权矩阵:\n");  //输出修改后的隐藏层权矩阵for (i = 0; i < dot; i++) {    for (j = 0; j < dot; j++)printf("%f    ", u[i][j]);    printf("\n");}printf("修改后的输出层权矩阵:\n");  //输出修改后的输出权矩阵for (i = 0; i < dot; i++) {for (j = 0; j < OUT; j++)printf("%f    ", w[i][j]);    printf("\n");}for (i = 0; i < IN; i++)             //将修改后的输入层权矩阵返回给bp结构体 for (j = 0; j < dot; j++)(*bp).v[i][j] = v[i][j];for (i = 0; i < dot; i++)//将修改后的隐藏层权矩阵返回给bp结构体for (j = 0; j < dot; j++)(*bp).u[i][j] = u[i][j];for (i = 0; i < dot; i++)//将修改后的输出层权矩阵返回给bp结构体for (j = 0; j < OUT; j++)(*bp).w[i][j] = w[i][j];printf("bp网络训练结束!\n");}void Use_Bp(bp_net *bp)    //使用bp网络测试结果{    float Input[IN];    //输入实例    double Output_In[dot_MAX];   //输入层输出    double Output_Hi[dot_MAX];      //隐藏层输出double Output_Ou[OUT];//输出层输出double temp;    while (1) {                         printf("请输入一个实例:\n");        int i, j;        for (i = 0; i <IN ; i++)            scanf("%f", &Input[i]);        for (i = 0; i < (*bp).dot; i++)    //计算输入层输出{            temp = 0;            for (j = 0; j < IN; j++)                temp += Input[j] * (*bp).v[j][i];            Output_In[i] = fnet(temp);        }for (i = 0; i < (*bp).dot; i++)//计算隐藏层输出{            temp = 0;            for (j = 0; j < (*bp).dot; j++)                temp += Output_In[j] * (*bp).u[j][i];            Output_Hi[i] = fnet(temp);        }        for (i = 0; i < OUT; i++)//计算输出层输出{            temp = 0;            for (j = 0; j < (*bp).dot; j++)                temp += Output_Hi[j] * (*bp).w[j][i];            Output_Ou[i] = fnet(temp);        }        printf("bp网络计算结果:   \n");printf("\n");        for (i = 0; i < OUT; i++){            printf("%.6f ", Output_Ou[i]);if(Output_Ou[i]>=1)printf("   肯定是!\n");elseswitch((int)(Output_Ou[i]*10)){case 0:printf("    肯定不是!");break;case 1:printf("    稍稍像是!");break;case 2:printf("    有点像是!");break;case 3:printf("    有些像是!");break;case 4:printf("    比较像是!");break;case 5:printf("    差不多是!");break;case 6:printf("    相当是!");break;case 7:printf("    很是!");break;case 8:printf("    极是!");break;case 9:printf("    几乎是!");break;}printf("\n");}}}void main(void){double x[NUM][IN]=       //训练样本{{0.05,0.02}, {0.09,0.11},{0.12,0.20},{0.15,0.22},{0.20,0.25},{0.75,0.75},{0.80,0.83},{0.82,0.80},{0.90,0.89},{0.95,0.89},{0.09,0.04},{0.10,0.10},{0.14,0.21},{0.18,0.24},{0.22,0.28},{0.77,0.78},{0.79,0.81},{0.84,0.82},{0.94,0.93},{0.98,0.99},}; int y[NUM][OUT] =   //理想输出{{1,0},{1,0},{1,0},{1,0},{1,0},{0,1},{0,1},{0,1},{0,1},{0,1},{1,0},{1,0},{1,0},{1,0},{1,0},{0,1},{0,1},{0,1},{0,1},{0,1},};bp_net bp;//定义bp结构体Initialize_Bp(&bp);              //初始化bp网络结构Train_Bp(&bp, x, y);             //训练bp神经网络Use_Bp(&bp);                     //测试bp神经网络}


原创粉丝点击