A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

© Dr_。Zeor` 初级黑马   /  2014-5-18 17:12  /  7800 人查看  /  10 人回复  /   1 人收藏 转载请遵从CC协议 禁止商业使用本文

最近在学习人工神经网络,就把BP实现了下,主要参考《人工神经网络导论》(蒋宗礼著)。好久没有编程,发现C语言已经忘的差不多了,一个语言上的小问题就能困扰我好一阵子,到底是C呀,什么都得照顾到,不像许多高级语言,很多细节就不需要人来考虑了,比如Python,关注她已经很久啦,matlab的实现就更简单了,这里不再详述。代码如下,愿与每一位黑马程序员共同探讨

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

#define OUT_COUT 2        //输出向量维数
#define IN_COUT  3        //输入向量维数
#define COUT        6        //样本数量

typedef struct {          //bp人工神经网络结构
       int h;                //实际使用隐层数量
       double v[IN_COUT][50];      //隐藏层权矩阵i,隐层节点最大数量为50
       double w[50][OUT_COUT];      //输出层权矩阵
       double a;             //学习率
       double b;             //精度控制参数
       int LoopCout;         //最大循环次数
} bp_nn;

double fnet(double net) { //Sigmoid函数,神经网络激活函数
       return 1/(1+exp(-net));
}

int InitBp(bp_nn *bp) { //初始化bp网络
      
       printf("请输入隐层节点数,最大数为100:\n");      
       scanf("%d", &(*bp).h);
      
       printf("请输入学习率:\n");
       scanf("%lf", &(*bp).a);       //(*bp).a为double型数据,所以必须是lf

       printf("请输入精度控制参数:\n");
       scanf("%lf", &(*bp).b);

       printf("请输入最大循环次数:\n");
       scanf("%d", &(*bp).LoopCout);

       int i, j;
       srand((unsigned)time(NULL));
       for (i = 0; i < IN_COUT; i++)
              for (j = 0; j < (*bp).h; j++)
                     (*bp).v[j] = rand() / (double)(RAND_MAX);      
       for (i = 0; i < (*bp).h; i++)
              for (j = 0; j < OUT_COUT; j++)
                     (*bp).w[j] = rand() / (double)(RAND_MAX);      
      
       return 1;
}

int TrainBp(bp_nn *bp, float x[COUT][IN_COUT], int y[COUT][OUT_COUT]) {
//训练bp网络,样本为x,理想输出为y
       double f = (*bp).b;                         //精度控制参数
       double a = (*bp).a;                         //学习率
       int h = (*bp).h;                            //隐层节点数
       double v[IN_COUT][50], w[50][OUT_COUT];  //权矩阵
       double ChgH[50], ChgO[OUT_COUT];            //修改量矩阵
       double O1[50], O2[OUT_COUT];                //隐层和输出层输出量
       int LoopCout = (*bp).LoopCout;              //最大循环次数
       int i, j, k, n;
       double temp;

       for (i = 0; i < IN_COUT; i++)               // 复制结构体中的权矩阵
              for (j = 0; j < h; j++)
                     v[j] = (*bp).v[j];
       for (i = 0; i < h; i++)
              for (j = 0; j < OUT_COUT; j++)
                     w[j] = (*bp).w[j];
      
       double e = f + 1;
       for (n = 0; e > f && n < LoopCout; n++) { //对每个样本训练网络
              e = 0;
              for (i= 0; i < COUT; i++) {  
                     for (k= 0; k < h; k++) {             //计算隐层输出向量
                            temp = 0;
                            for (j = 0; j < IN_COUT; j++)
                                   temp = temp + x[j] * v[j][k];      
                            O1[k] = fnet(temp);
                     }
                     for (k = 0; k < OUT_COUT; k++) {  //计算输出层输出向量
                            temp = 0;
                            for (j = 0; j < h; j++)
                                   temp = temp + O1[j] * w[j][k];
                            O2[k] = fnet(temp);
                     }
                     for (j = 0; j < OUT_COUT; j++)       //计算输出层的权修改量      
                            ChgO[j] = O2[j] * (1 - O2[j]) * (y[j] - O2[j]);
                     for (j = 0; j < OUT_COUT ; j++)      //计算输出误差
                            e = e + (y[j] - O2[j]) * (y[j] - O2[j]);
                     for (j = 0; j < h; j++) {            //计算隐层权修改量
                            temp = 0;
                            for (k = 0; k < OUT_COUT; k++)
                                   temp = temp + w[j][k] * ChgO[k];
                            ChgH[j] = temp * O1[j] * (1 - O1[j]);
                     }
                     for (j = 0; j < h; j++)              //修改输出层权矩阵
                            for (k = 0; k < OUT_COUT; k++)
                                   w[j][k] = w[j][k] + a * O1[j] * ChgO[k];
                     for (j = 0; j < IN_COUT; j++)
                            for (k = 0; k < h; k++)
                                   v[j][k] = v[j][k] + a * x[j] * ChgH[k];
              }
              if (n % 10 == 0)
                     printf("误差 : %f\n", e);
       }
       printf("总共循环次数:%d\n", n);
       printf("调整后的隐层权矩阵:\n");
       for (i = 0; i < IN_COUT; i++) {      
              for (j = 0; j < h; j++)
                     printf("%f       ", v[j]);      
              printf("\n");
       }
       printf("调整后的输出层权矩阵:\n");
       for (i = 0; i < h; i++) {
              for (j = 0; j < OUT_COUT; j++)
                     printf("%f       ", w[j]);      
              printf("\n");
       }
       for (i = 0; i < IN_COUT; i++)                //把结果复制回结构体  
              for (j = 0; j < h; j++)
                     (*bp).v[j] = v[j];
       for (i = 0; i < h; i++)
              for (j = 0; j < OUT_COUT; j++)
                     (*bp).w[j] = w[j];
       printf("bp网络训练结束!\n");

       return 1;
}

int UseBp(bp_nn *bp) {       //使用bp网络
       float Input[IN_COUT];
       double O1[50];
       double O2[OUT_COUT];  //O1为隐层输出,O2为输出层输出
       while (1) {              //持续执行,除非中断程序
              printf("请输入3个数:\n");
              int i, j;
              for (i = 0; i < IN_COUT; i++)
                     scanf("%f", &Input);
              double temp;
              for (i = 0; i < (*bp).h; i++) {
                     temp = 0;
                     for (j = 0; j < IN_COUT; j++)
                            temp += Input[j] * (*bp).v[j];
                     O1 = fnet(temp);
              }
              for (i = 0; i < OUT_COUT; i++) {
                     temp = 0;
                     for (j = 0; j < (*bp).h; j++)
                            temp += O1[j] * (*bp).w[j];
                     O2 = fnet(temp);
              }
              printf("结果:      ");
              for (i = 0; i < OUT_COUT; i++)
                     printf("%.3f ", O2);
              printf("\n");
       }
       return 1;
}

int main()
{
       float x[COUT][IN_COUT] = {{0.8,0.5,0},  
                                                                     {0.9,0.7,0.3},
                                                                  {1,0.8,0.5},
                                                                     {0,0.2,0.3},
                                                                  {0.2,0.1,1.3},
                                                                     {0.2,0.7,0.8}}; //训练样本
       int y[COUT][OUT_COUT] = {{0,1},
                                                                 {0,1},
                                                              {0,1},
                                                                    {1,0},
                                                                 {1,0},
                                                              {1,0}};             //理想输出
       bp_nn bp;

       InitBp(&bp);                       //初始化bp网络结构
       TrainBp(&bp, x, y);                //训练bp神经网络
       UseBp(&bp);                        //测试bp神经网络

       return 1;
}

评分

参与人数 1黑马币 +3 收起 理由
傘が咲く + 3

查看全部评分

10 个回复

倒序浏览
这种算法其实学IOS不怎么用的上
回复 使用道具 举报
支持一下,辛苦了
回复 使用道具 举报
大神 膜拜呀!
回复 使用道具 举报
犀利。。。。
回复 使用道具 举报
好厉害楼主。
回复 使用道具 举报
楼主  威武
回复 使用道具 举报
看不太懂, 还是支持一下
回复 使用道具 举报
亮~ 中级黑马 2014-6-24 22:08:45
9#
加油!!!
回复 使用道具 举报
多谢分享
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马