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

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© Dr_。Zeor` 初级黑马   /  2014-5-18 17:12  /  7038 人查看  /  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不怎么用的上
回复 使用道具 举报
写进博客不错~
回复 使用道具 举报 1 0
支持一下,辛苦了
回复 使用道具 举报
大神 膜拜呀!
回复 使用道具 举报
犀利。。。。
回复 使用道具 举报
Dr_Cai 初级黑马 2014-6-17 19:49:12
7#
好厉害楼主。
回复 使用道具 举报
楼主  威武
回复 使用道具 举报
看不太懂, 还是支持一下
回复 使用道具 举报
亮~ 中级黑马 2014-6-24 22:08:45
10#
加油!!!
回复 使用道具 举报
多谢分享
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马