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