一 题目:

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:

 #include<iostream>
#include<fstream>
#include<iomanip>
#include<stdlib.h>
#include<math.h>
#include<time.h> #define SampleCount 15 //学习样本个数
#define INnum 2 //输入层神经元数目
#define HN 15//隐层神经元数目
#define ONnum 1 //输出层神经元数目 using namespace std;

  头文件bp.h:

 #ifndef BP_H
#define BP_H #include "necessary.h" class Back_propagation
{ public:
Back_propagation();
double W[HN][INnum]; //输入层至隐层权值
double V[ONnum][HN]; //隐层至输出层权值
double P[INnum]; //单个样本输入数据
double T[ONnum]; //单个样本期望输出值 double OLD_W[HN][INnum]; //保存HN-IN旧权!
double OLD_V[ONnum][HN]; //保存ON-HN旧权!
double HI[HN]; //隐层的输入
double OI[ONnum]; //输出层的输入
double hidenLayerOutput[HN]; //隐层的输出
double OO[ONnum]; //输出层的输出
double err_m[SampleCount]; //第m个样本的总误差
double studyRate;//学习效率效率
double b;//步长
double e_err[HN];
double d_err[ONnum];
void input_p(int m);
void input_t(int m);
void H_I_O();
void O_I_O();
void Err_Output_Hidden(int m);
void Err_Hidden_Input();
void Adjust_O_H(int m,int n);
void Adjust_H_I(int m,int n);
void saveWV();
struct
{
double input[INnum];
double teach[ONnum];
}Study_Data[SampleCount];
private:
}; #endif

  源文件necessary.cpp:

 #include "necessary.h"

  源文件bp.cpp:

 #include"bp.h"

 Back_propagation::Back_propagation()
{ srand( (unsigned)time( NULL ) ); for( int i = ; i < HN; i ++ )
{
for( int j = ; j < INnum; j ++ )
{
W[i][j] = double( rand() % ) / ; //初始化输入层到隐层的权值
}
}
for( int ii = ; ii < ONnum; ii ++ )
{
for( int jj = ; jj < HN; jj ++ )
{
V[ii][jj] = double( rand() % ) / ; //初始化隐层到输出层的权值
}
}
} void Back_propagation::input_p(int m)
{
for( int i = ; i < INnum; i ++ )
{
P[i] = Study_Data[m].input[i];
}
} void Back_propagation::input_t(int m)
{
for( int k = ; k < ONnum; k ++ )
{
T[k] = Study_Data[m].teach[k];
}
} void Back_propagation::H_I_O()
{
double net;
int i,j;
for( j = ; j < HN; j ++ )
{
net = ;
for( i = ; i < INnum; i ++ )
{
net += W[j][i] * P[i];//求隐层内积
}
HI[j] = net;// - Thread_Hiden[j];//求隐层输入
hidenLayerOutput[j] = 1.0 / ( 1.0 + exp(-HI[j]) );//求隐层输出
}
} void Back_propagation::O_I_O()
{
double net;
int k,j;
for( k = ; k < ONnum; k ++ )
{
net = ;
for( j = ; j < HN; j ++ )
{
net += V[k][j] * hidenLayerOutput[j];//求输出层内积
}
OI[k] = net; //求输出层输入
OO[k] = 1.0 / ( 1.0 + exp(-OI[k]) );//求输出层输出
}
} void Back_propagation::Err_Output_Hidden( int m )
{
double abs_err[ONnum];//样本误差
double sqr_err = ;//临时保存误差平方 for( int k = ; k < ONnum; k ++ )
{
abs_err[k] = T[k] - OO[k]; //求第m个样本下的第k个神经元的绝对误差 sqr_err += (abs_err[k]) * (abs_err[k]);//求第m个样本下输出层的平方误差 d_err[k] = abs_err[k] * OO[k] * (1.0-OO[k]);//d_err[k]输出层各神经元的一般化误差
}
err_m[m] = sqr_err / ;//第m个样本下输出层的平方误差/2=第m个样本的均方误差,据ppt1.5-3 } void Back_propagation::Err_Hidden_Input()
{
double sigma;
for( int j = ; j < HN; j ++ )
{
sigma = 0.0;
for( int k = ; k < ONnum; k ++ )
{
sigma += d_err[k] * V[k][j];
} e_err[j] = sigma * hidenLayerOutput[j] * ( - hidenLayerOutput[j] );//隐层各神经元的一般化误差
}
} void Back_propagation::Adjust_O_H( int m,int n )
{
if( n <= )
{
for( int k = ; k < ONnum; k ++ )
{
for( int j = ; j < HN; j ++ )
{
V[k][j] = V[k][j] + studyRate * d_err[k] * hidenLayerOutput[j];//输出层至隐层的权值调整
}
}
}
else if( n > )
{
for( int k = ; k < ONnum; k ++ )
{
for( int j = ; j < HN; j ++ )
{
V[k][j] = V[k][j] + studyRate * d_err[k] * hidenLayerOutput[j] + b * ( V[k][j] - OLD_V[k][j] );//输出层至隐层的权值调整
}
}
}
} void Back_propagation::Adjust_H_I( int m,int n )
{
if( n <= )
{
for( int j = ; j < HN; j ++ )
{
for ( int i = ; i < INnum; i ++ )
{
W[j][i] = W[j][i] + studyRate * e_err[j] * P[i];//隐层至输入层的权值调整
}
} }
else if( n > )
{
for( int j = ; j < HN; j ++ )
{
for( int i = ; i < INnum; i ++ )
{
W[j][i] += studyRate * e_err[j] * P[i] + b * ( W[j][i] - OLD_W[j][i] );//隐层至输入层的权值调整
}
}
}
} void Back_propagation::saveWV()
{
for( int i = ; i < HN; i ++ )
{
for( int j = ; j < INnum; j ++ )
{
OLD_W[i][j] = W[i][j];
}
} for( int ii = ; ii < ONnum; ii ++ )
{
for( int jj = ; jj < HN; jj ++ )
{
OLD_V[ii][jj] = V[ii][jj];
}
}
}

  源文件main.cpp:

 #include "bp.h"

 void saveWV( Back_propagation bp )
{
for( int i = ; i < HN; i ++ )
{
for( int j = ; j < INnum; j ++ )
{
bp.OLD_W[i][j] = bp.W[i][j];
}
} for( int ii = ; ii < ONnum; ii ++ )
{
for( int jj = ; jj < HN; jj ++ )
{
bp.OLD_V[ii][jj] = bp.V[ii][jj];
}
}
} //保存数据
void savequan( Back_propagation bp )
{
ofstream outW( "w.txt" );
ofstream outV( "v.txt" ); for( int i = ; i < HN; i ++ )
{
for( int j = ; j < INnum; j ++ )
{
outW << bp.W[i][j] << " ";
}
outW << "\n";
} for( int ii = ; ii < ONnum; ii ++ )
{
for( int jj = ; jj < HN; jj ++ )
{
outV << bp.V[ii][jj] << " ";
}
outV << "\n";
} outW.close();
outV.close(); } double Err_Sum( Back_propagation bp )
{
double total_err = ;
for ( int m = ; m < SampleCount; m ++ )
{
total_err += bp.err_m[m];//每个样本的均方误差加起来就成了全局误差
}
return total_err;
} int main()
{
double sum_err;
int study;
int m;
double check_in, check_out;
ifstream Train_in( "trainin.txt", ios::in );
ifstream Train_out( "trainout.txt", ios::in ); if( ( Train_in.fail() ) || ( Train_out.fail() ) )
{
//printf( "Error input file!\n" );
cerr << "Error input file!" << endl;
exit();
} Back_propagation bp; cout << "请输入学习效率: studyRate = ";
cin >> bp.studyRate; cout << "\n请输入步长: b= ";
cin >> bp.b; study = ;
double Pre_error ; //预定误差
cout << "\n请输入预定误差: Pre_error = ";
cin >> Pre_error; int Pre_times;
cout << "\n请输入预定最大学习次数:Pre_times=";
cin >> Pre_times; for( m = ; m < SampleCount; m ++ )
{
for( int i = ; i < INnum; i ++ )
{
Train_in >> bp.Study_Data[m].input[i];
}
} cout << endl;
for( m = ; m < SampleCount; m ++ )
{
for( int k = ; k < ONnum; k ++ )
{
Train_out >> bp.Study_Data[m].teach[k];
}
} cout << endl; do
{
++ study;
if( study > Pre_times )
{
cout << "训练失败!" << endl;
break;
} for ( int m = ; m < SampleCount; m ++ )
{
bp.input_p(m); //输入第m个学习样本 (2)
bp.input_t(m);//输入第m个样本的教师信号 (3)
bp.H_I_O(); //第m个学习样本隐层各单元输入、输出值 (4)
bp.O_I_O();
bp.Err_Output_Hidden(m); //第m个学习样本输出层至隐层一般化误差 (6)
bp.Err_Hidden_Input(); //第m个学习样本隐层至输入层一般化误差 (7)
bp.Adjust_O_H(m,study);
bp.Adjust_H_I(m,study);
if( m == )
{
cout << bp.V[][] << " " << bp.V[][] << endl;
}
}//全部样本训练完毕
sum_err = Err_Sum(bp); //全部样本全局误差计算 (10)
bp.saveWV();
}while( sum_err > Pre_error ); if( ( study <= Pre_times ) & ( sum_err < Pre_error ) )
{
cout << "训练结束!" << endl;
cout << "你已经学习了 " << study << "次" << endl;
}
double net;
int k, j;
while()
{
printf( "请输入蠓虫的触角及翅膀的长度:" );
cin >> check_in;
cin >> check_out;
bp.P[] = check_in;
bp.P[] = check_out;
bp.H_I_O();
for ( k = ; k < ONnum; k ++ )
{
net = ;
for( j = ; j < HN; j ++ )
{
net += bp.V[k][j] * bp.hidenLayerOutput[j];//求输出层内积
}
bp.OI[k] = net; //求输出层输入
bp.OO[k] = 1.0 / ( 1.0 + exp(-bp.OI[k]) );//求输出层输出
}
if( bp.OO[] > 0.5 )
{
printf( "该蠓虫是af!\n" );
}
else if( bp.OO[] >= )
{
printf( "该蠓虫是apf!\n" );
}
}
return ;
}

三 测试文件:

  文件trainin.txt:

 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
1.14 1.82
1.18 1.96
1.20 1.86
1.26 2.00
1.28 2.00
1.30 1.96

  文件trainout.txt:


四 实验结果:

图1 输入数据

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

附录:

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

参考文献:

[1]甘刚.BP算法在IDS中应用与实现的研究[J].成都:电子科技大学,硕博学位论文,2005.

最新文章

  1. Thinkphp更改子集
  2. MyBatis无法根据中文条件查询出结果
  3. WPF之 DataGrid分页
  4. 今日 使用ajaxfileupload 异步上传 但是在IE下面 会弹出下载框
  5. 对Vector3.Lerp 插值的理解
  6. 如何实现多个div水平均匀排列且量两端贴壁
  7. getName()、getCanonicalName()、getSimpleName()异同
  8. Oracle存储过程实现返回多个结果集 在构造函数方法中使用 dataset
  9. (4)java方法区
  10. SGU 187.Twist and whirl - want to cheat( splay )
  11. [android更新类的内容开发APP]四、项目布局的基本功能(继续)
  12. Hololens生成与安装(旁加载)应用
  13. JavaScrpt笔记之第三天
  14. 基于flash的web视频对讲直播测试
  15. QT连接postgreSQL
  16. Java8-Map
  17. 大数据处理过程核心技术ETL详细介绍
  18. PopupWindows 在2.3.3下报java.lang.NullPointerException
  19. shell编程小技巧(命令篇)
  20. jquery 删除table行,该如何解决

热门文章

  1. Java EE学习笔记(一)
  2. Influxdb 时序数据库 centos 安装
  3. 关于pycharm的一个imoprt的随笔
  4. Java动态解析域名
  5. Navicat for MySQL在ubuntu下运行没有反应
  6. Java之final、static关键字及匿名对象
  7. Java之构造方法及this、super关键字
  8. ios 自定义消息提示框
  9. (转)Linux下清理Cache方法
  10. Redis性能优化之redis.cnf配置参数