“程序设计与算法训练”课程设计:“BP神经网络的实现”(C++类封装实现)

一 题目:

71 BP神经网络的实现:

  利用C++语言实现BP神经网络, 并利用BP神经网络解决螨虫分类问题:

  蠓虫分类问题:对两种蠓虫(A与B)进行鉴别,依据的资料是触角和翅膀的长度,已知了9支Af和6支Apf 的数据如下:A: (1.24,1.27), (1.36,1.74),(1.38,1.64) , (1.38,1.82) , (1.38,1.90) , (1.40,1.70) , (1.48,1.82) , (1.54,1.82) ,(1.56,2.08).B: (1.14,1.82), (1.18,1.96), (1.20,1.86), (1.26,2.00), (1.28,2.00),(1.30,1.96).
  要求:(1)阐述BP神经网络的结构构成及数学原理;

(2)利用C++实现BP神经网络;

(3)利用BP神经网络实现螨虫分类.

二 源代码:

  头文件necessary.h:

 1 #include<iostream>
 2 #include<fstream>
 3 #include<iomanip>
 4 #include<stdlib.h>
 5 #include<math.h>
 6 #include<time.h>
 7
 8 #define SampleCount 15 //学习样本个数
 9 #define INnum 2 //输入层神经元数目
10 #define HN 15//隐层神经元数目
11 #define ONnum 1 //输出层神经元数目
12
13 using namespace std;

  头文件bp.h:

 1 #ifndef BP_H
 2 #define BP_H
 3
 4 #include "necessary.h"
 5
 6
 7 class Back_propagation
 8 {
 9
10 public:
11     Back_propagation();
12     double W[HN][INnum]; //输入层至隐层权值
13     double V[ONnum][HN]; //隐层至输出层权值
14     double P[INnum]; //单个样本输入数据
15     double T[ONnum]; //单个样本期望输出值
16
17     double OLD_W[HN][INnum];  //保存HN-IN旧权!
18     double OLD_V[ONnum][HN];  //保存ON-HN旧权!
19     double HI[HN]; //隐层的输入
20     double OI[ONnum]; //输出层的输入
21     double hidenLayerOutput[HN]; //隐层的输出
22     double OO[ONnum]; //输出层的输出
23     double err_m[SampleCount]; //第m个样本的总误差
24     double studyRate;//学习效率效率
25     double b;//步长
26     double e_err[HN];
27     double d_err[ONnum];
28     void input_p(int m);
29     void input_t(int m);
30     void H_I_O();
31     void O_I_O();
32     void Err_Output_Hidden(int m);
33     void Err_Hidden_Input();
34     void Adjust_O_H(int m,int n);
35     void Adjust_H_I(int m,int n);
36     void saveWV();
37     struct
38     {
39         double input[INnum];
40         double teach[ONnum];
41     }Study_Data[SampleCount];
42 private:
43 };
44
45 #endif

  源文件necessary.cpp:

1 #include "necessary.h"

  源文件bp.cpp:

  1 #include"bp.h"
  2
  3 Back_propagation::Back_propagation()
  4 {
  5
  6
  7     srand( (unsigned)time( NULL ) );
  8
  9     for( int i = 0; i < HN; i ++ )
 10     {
 11         for( int j = 0; j < INnum; j ++ )
 12         {
 13             W[i][j] = double( rand() % 100 ) / 100; //初始化输入层到隐层的权值
 14         }
 15     }
 16     for( int ii = 0; ii < ONnum; ii ++ )
 17     {
 18         for( int jj = 0; jj < HN; jj ++ )
 19         {
 20             V[ii][jj] = double( rand() % 100 ) / 100;  //初始化隐层到输出层的权值
 21         }
 22     }
 23 }
 24
 25 void Back_propagation::input_p(int m)
 26 {
 27        for( int i = 0; i < INnum; i ++ )
 28     {
 29         P[i] = Study_Data[m].input[i];
 30     }
 31 }
 32
 33 void Back_propagation::input_t(int m)
 34 {
 35     for( int k = 0; k < ONnum; k ++ )
 36     {
 37         T[k] = Study_Data[m].teach[k];
 38     }
 39 }
 40
 41 void Back_propagation::H_I_O()
 42 {
 43     double net;
 44     int i,j;
 45     for( j = 0; j < HN; j ++ )
 46     {
 47         net = 0;
 48         for( i = 0; i < INnum; i ++ )
 49         {
 50             net += W[j][i] * P[i];//求隐层内积
 51         }
 52         HI[j] = net;// - Thread_Hiden[j];//求隐层输入
 53         hidenLayerOutput[j] = 1.0 / ( 1.0 + exp(-HI[j]) );//求隐层输出
 54     }
 55 }
 56
 57 void Back_propagation::O_I_O()
 58 {
 59     double net;
 60     int k,j;
 61     for( k = 0; k < ONnum; k ++ )
 62     {
 63         net = 0;
 64         for( j = 0; j < HN; j ++ )
 65         {
 66             net += V[k][j] * hidenLayerOutput[j];//求输出层内积
 67         }
 68         OI[k] = net; //求输出层输入
 69         OO[k] = 1.0 / ( 1.0 + exp(-OI[k]) );//求输出层输出
 70     }
 71 }
 72
 73 void Back_propagation::Err_Output_Hidden( int m )
 74 {
 75     double abs_err[ONnum];//样本误差
 76     double sqr_err = 0;//临时保存误差平方
 77
 78     for( int k = 0; k < ONnum; k ++ )
 79     {
 80         abs_err[k] = T[k] - OO[k];    //求第m个样本下的第k个神经元的绝对误差
 81
 82         sqr_err += (abs_err[k]) * (abs_err[k]);//求第m个样本下输出层的平方误差
 83
 84         d_err[k] = abs_err[k] * OO[k] * (1.0-OO[k]);//d_err[k]输出层各神经元的一般化误差
 85     }
 86     err_m[m] = sqr_err / 2;//第m个样本下输出层的平方误差/2=第m个样本的均方误差,据ppt1.5-3
 87
 88 }
 89
 90 void Back_propagation::Err_Hidden_Input()
 91 {
 92   double sigma;
 93   for( int j = 0; j < HN; j ++ )
 94   {
 95      sigma = 0.0;
 96      for( int k = 0; k < ONnum; k ++ )
 97      {
 98         sigma += d_err[k] * V[k][j];
 99      }
100
101      e_err[j] = sigma * hidenLayerOutput[j] * ( 1 - hidenLayerOutput[j] );//隐层各神经元的一般化误差
102   }
103 }
104
105 void Back_propagation::Adjust_O_H( int m,int n )
106 {
107     if( n <= 1 )
108     {
109         for( int k = 0; k < ONnum; k ++ )
110         {
111             for( int j = 0; j < HN; j ++ )
112             {
113                 V[k][j] = V[k][j] + studyRate * d_err[k] * hidenLayerOutput[j];//输出层至隐层的权值调整
114             }
115         }
116     }
117     else if( n > 1 )
118     {
119         for( int k = 0; k < ONnum; k ++ )
120         {
121             for( int j = 0; j < HN; j ++ )
122             {
123                 V[k][j] = V[k][j] + studyRate * d_err[k] * hidenLayerOutput[j] + b * ( V[k][j] - OLD_V[k][j] );//输出层至隐层的权值调整
124             }
125         }
126     }
127 }
128
129 void Back_propagation::Adjust_H_I( int m,int n )
130 {
131     if( n <= 1 )
132     {
133         for( int j = 0; j < HN; j ++ )
134         {
135             for ( int i = 0; i < INnum; i ++ )
136             {
137                 W[j][i] = W[j][i] + studyRate * e_err[j] * P[i];//隐层至输入层的权值调整
138             }
139         }
140
141     }
142     else if( n > 1 )
143     {
144         for( int j = 0; j < HN; j ++ )
145         {
146             for( int i = 0; i < INnum; i ++ )
147             {
148                 W[j][i] += studyRate * e_err[j] * P[i] + b * ( W[j][i] - OLD_W[j][i] );//隐层至输入层的权值调整
149             }
150         }
151     }
152 }
153
154 void Back_propagation::saveWV()
155 {
156     for( int i = 0; i < HN; i ++ )
157     {
158         for( int j = 0; j < INnum; j ++ )
159         {
160             OLD_W[i][j] = W[i][j];
161         }
162     }
163
164     for( int ii = 0; ii < ONnum; ii ++ )
165     {
166         for( int jj = 0; jj < HN; jj ++ )
167         {
168             OLD_V[ii][jj] = V[ii][jj];
169         }
170     }
171 }

  源文件main.cpp:

  1 #include "bp.h"
  2
  3 void saveWV( Back_propagation bp )
  4 {
  5     for( int i = 0; i < HN; i ++ )
  6     {
  7         for( int j = 0; j < INnum; j ++ )
  8         {
  9             bp.OLD_W[i][j] = bp.W[i][j];
 10         }
 11     }
 12
 13     for( int ii = 0; ii < ONnum; ii ++ )
 14     {
 15         for( int jj = 0; jj < HN; jj ++ )
 16         {
 17             bp.OLD_V[ii][jj] = bp.V[ii][jj];
 18         }
 19     }
 20 }
 21
 22 //保存数据
 23 void savequan( Back_propagation bp )
 24 {
 25     ofstream outW( "w.txt" );
 26     ofstream outV( "v.txt" );
 27
 28     for( int i = 0; i < HN; i ++ )
 29     {
 30         for( int j = 0; j < INnum; j ++ )
 31         {
 32             outW << bp.W[i][j] << "   ";
 33         }
 34         outW << "\n";
 35     }
 36
 37     for( int ii = 0; ii < ONnum; ii ++ )
 38     {
 39         for( int jj = 0; jj < HN; jj ++ )
 40         {
 41             outV << bp.V[ii][jj] << "   ";
 42         }
 43         outV << "\n";
 44     }
 45
 46
 47     outW.close();
 48     outV.close();
 49
 50 }
 51
 52 double Err_Sum( Back_propagation bp )
 53 {
 54     double total_err = 0;
 55     for ( int m = 0; m < SampleCount; m ++ )
 56     {
 57       total_err += bp.err_m[m];//每个样本的均方误差加起来就成了全局误差
 58     }
 59     return total_err;
 60 }
 61
 62 int main()
 63 {
 64     double sum_err;
 65     int study;
 66     int m;
 67     double check_in, check_out;
 68     ifstream Train_in( "trainin.txt", ios::in );
 69     ifstream Train_out( "trainout.txt", ios::in );
 70
 71     if( ( Train_in.fail() ) || ( Train_out.fail() ) )
 72     {
 73         //printf( "Error input file!\n" );
 74         cerr << "Error input file!" << endl;
 75         exit(0);
 76     }
 77
 78     Back_propagation bp;
 79
 80     cout << "请输入学习效率: studyRate = ";
 81     cin >> bp.studyRate;
 82
 83     cout << "\n请输入步长: b= ";
 84     cin >> bp.b;
 85
 86     study = 0;
 87     double Pre_error ; //预定误差
 88     cout << "\n请输入预定误差: Pre_error = ";
 89     cin >> Pre_error;
 90
 91     int Pre_times;
 92     cout << "\n请输入预定最大学习次数:Pre_times=";
 93     cin >> Pre_times;
 94
 95     for( m = 0; m < SampleCount; m ++ )
 96     {
 97         for( int i = 0; i < INnum; i ++ )
 98         {
 99             Train_in >> bp.Study_Data[m].input[i];
100         }
101     }
102
103     cout << endl;
104     for( m = 0; m < SampleCount; m ++ )
105     {
106         for( int k = 0; k < ONnum; k ++ )
107         {
108            Train_out >> bp.Study_Data[m].teach[k];
109         }
110     }
111
112     cout << endl;
113
114     do
115     {
116         ++ study;
117         if( study > Pre_times )
118         {
119             cout << "训练失败!" << endl;
120             break;
121         }
122
123         for ( int m = 0; m < SampleCount; m ++ )
124         {
125             bp.input_p(m); //输入第m个学习样本 (2)
126             bp.input_t(m);//输入第m个样本的教师信号 (3)
127             bp.H_I_O(); //第m个学习样本隐层各单元输入、输出值 (4)
128             bp.O_I_O();
129             bp.Err_Output_Hidden(m); //第m个学习样本输出层至隐层一般化误差 (6)
130             bp.Err_Hidden_Input(); //第m个学习样本隐层至输入层一般化误差 (7)
131             bp.Adjust_O_H(m,study);
132             bp.Adjust_H_I(m,study);
133             if( m == 0 )
134             {
135                 cout << bp.V[0][0] << " " << bp.V[0][1] << endl;
136             }
137         }//全部样本训练完毕
138         sum_err = Err_Sum(bp); //全部样本全局误差计算 (10)
139         bp.saveWV();
140     }while( sum_err > Pre_error );
141
142     if( ( study <= Pre_times ) & ( sum_err < Pre_error ) )
143     {
144         cout << "训练结束!" << endl;
145         cout << "你已经学习了 " << study << "次" << endl;
146     }
147     double net;
148     int k, j;
149     while(1)
150     {
151         printf( "请输入蠓虫的触角及翅膀的长度:" );
152         cin >> check_in;
153         cin >> check_out;
154         bp.P[0] = check_in;
155         bp.P[1] = check_out;
156         bp.H_I_O();
157         for ( k = 0; k < ONnum; k ++ )
158         {
159             net = 0;
160             for( j = 0; j < HN; j ++ )
161             {
162                 net += bp.V[k][j] * bp.hidenLayerOutput[j];//求输出层内积
163             }
164             bp.OI[k] = net; //求输出层输入
165             bp.OO[k] = 1.0 / ( 1.0 + exp(-bp.OI[k]) );//求输出层输出
166         }
167         if( bp.OO[0] > 0.5 )
168         {
169             printf( "该蠓虫是af!\n" );
170         }
171         else if( bp.OO[0] >= 0 )
172         {
173             printf( "该蠓虫是apf!\n" );
174         }
175     }
176     return 0;
177 }

三 测试文件:

  文件trainin.txt:

 1 1.24 1.27
 2 1.36 1.74
 3 1.38 1.64
 4 1.38 1.82
 5 1.38 1.90
 6 1.40 1.70
 7 1.48 1.82
 8 1.54 1.82
 9 1.56 2.08
10 1.14 1.82
11 1.18 1.96
12 1.20 1.86
13 1.26 2.00
14 1.28 2.00
15 1.30 1.96

  文件trainout.txt:

 1 1
 2 1
 3 1
 4 1
 5 1
 6 1
 7 1
 8 1
 9 1
10 0
11 0
12 0
13 0
14 0
15 0

四 实验结果:

图1 输入数据

图2 测试算法“学习”结果

附录:

  题目里面既有“螨(音mǎn)虫”,也有“蠓(音měng)虫”,程序里面用的是“蠓虫”。

原文地址:https://www.cnblogs.com/25th-engineer/p/10352454.html

时间: 2024-10-08 10:19:41

“程序设计与算法训练”课程设计:“BP神经网络的实现”(C++类封装实现)的相关文章

野生程序员初长成——记北大程序设计与算法专项课程

欢迎转载,博客中的文章均为meelo原创,转载请务必以链接形式注明本文地址:www.cnblogs.com/meelo/p/5595306.html <程序设计与算法>是北京大学在Coursera上开设的一个专项课程.专项课程由6门课程构成,分别是计算导论.C程序设计.C++程序设计.算法基础.数据结构基础.高级数据结构与算法,外加一个编程毕业项目.专项课程没有假定任何先修知识,如果你对编程感兴趣或者羡慕程序员的高工资,你都可以学习这个专项课程来感悟编程的滋味.教授这些课程的老师都是北大的教授

北京大学-程序设计与算法 专项课程

程序设计与算法专项课程 https://www.coursera.org/specializations/biancheng-suanfa 计算导论 https://www.coursera.org/learn/jisuanji-biancheng C程序设计 https://www.coursera.org/learn/c-chengxu-sheji C++程序设计 https://www.coursera.org/learn/cpp-chengxu-sheji 算法基础 https://ww

野生程序员初长成 记北大程序设计与算法专项课程

<程序设计与算法>是北京大学在Coursera上开设的一个专项课程.专项课程由6门课程构成,分别是计算导论.C程序设计.C++程序设计.算法基础.数据结构基础.高级数据结构与算法,外加一个编程毕业项目.专项课程没有假定任何先修知识,如果你对编程感兴趣或者羡慕程序员的高工资,你都可以学习这个专项课程来感悟编程的滋味.教授这些课程的老师都是北大的教授,所以课程的内容是毋庸置疑的.下面是教授专项课程的四位老师. 这6门课程,每门课程大致有6周的课程内容,真实对应于北大开设的三门课.所以不用说,这个专

coursera 北京大学 程序设计与算法 专项课程 完美覆盖

#include <iostream> using namespace std; /*int wanmeifugai(int n){ if(n%2){ return 0; } else if(n==2){ return 3; }else if(n == 0) return 1; else return (2+ 3*3)*wanmeifugai(n-4); }*/ //下面是参考网上的程序 /*思路:引自:http://m.blog.csdn.net/blog/njukingway/204518

字符识别OCR研究一(模板匹配&amp;amp;BP神经网络训练)

摘 要 在MATLAB环境下利用USB摄像头採集字符图像.读取一帧保存为图像.然后对读取保存的字符图像,灰度化.二值化,在此基础上做倾斜矫正.对矫正的图像进行滤波平滑处理,然后对字符区域进行提取切割出单个字符.识别方法一是採用模板匹配的方法逐个对字符与预先制作好的字符模板比較,假设结果小于某一阈值则结果就是模板上的字符:二是採用BP神经网络训练.通过训练好的net对待识别字符进行识别.最然后将识别结果通过MATLAB下的串口工具输出51单片机上用液晶显示出来. keyword: 倾斜矫正.字符切

模式识别之ocr项目---(模板匹配&amp;BP神经网络训练)

摘 要 在MATLAB环境下利用USB摄像头采集字符图像,读取一帧保存为图像,然后对读取保存的字符图像,灰度化,二值化,在此基础上做倾斜矫正,对矫正的图像进行滤波平滑处理,然后对字符区域进行提取分割出单个字符,识别方法一是采用模板匹配的方法逐个对字符与预先制作好的字符模板比较,如果结果小于某一阈值则结果就是模板上的字符:二是采用BP神经网络训练,通过训练好的net对待识别字符进行识别.最然后将识别结果通过MATLAB下的串口工具输出51单片机上用液晶显示出来. 关键字: 倾斜矫正,字符分割,模板

基于BP神经网络的简单字符识别算法自小结(C语言版)

本文均属自己阅读源码的点滴总结,转账请注明出处谢谢. 欢迎和大家交流.qq:1037701636 email:[email protected] 写在前面的闲话: 自我感觉自己应该不是一个很擅长学习算法的人,过去的一个月时间里因为需要去接触了BP神经网络.在此之前一直都认为算法界的神经网络.蚁群算法.鲁棒控制什么的都是特别高大上的东西,自己也就听听好了,未曾去触碰与了解过.这次和BP神经网络的邂逅,让我初步掌握到,理解透彻算法的基本原理与公式,转为计算机所能识别的代码流,这应该就是所谓的数学和计

bp神经网络算法

对于BP神经网络算法,由于之前一直没有应用到项目中,今日偶然之时 进行了学习, 这个算法的基本思路是这样的:不断地迭代优化网络权值,使得输入与输出之间的映射关系与所期望的映射关系一致,利用梯度下降的方法更新调整各层的权值,求目标函数的最小化. 1:初始化网络权值和神经元阈值(最简单的方法是随机初始化): 2:前向算法:这是bp神经网络的经典算法,主要过程是,按照公式一层层计算隐层神经元和输出神经元的Input和Output. net=x1*w1 + x2*w2 + .....+xn*wn tan

题外:分类篇(音乐风格分类)基于BP神经网络

语音特征参数MFCC的提取及识别 (2012-09-07 20:24:03) 转载▼ 耳蜗实质上相当于一个滤波器组,耳蜗的滤波作用是在对数频率尺度上进行的,在1000HZ下,人耳的感知能力与频率成线性关系:而在1000HZ以上,人耳的感知能力与频率不构成线性关系,而更偏向于对数关系,这就使得人耳对低频信号比高频信号更敏感.Mel频率的提出是为了方便人耳对不同频率语音的感知特性的研究.频率与Mel频率的转换公式为: MFCC在一定程度上模拟了人耳对语音的处理特点,应用了人耳听觉感知方面的研究成果,