⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 bp.cpp

📁 BP神经网络算法的C语言实现
💻 CPP
字号:
#include "iostream.h"
#include "iomanip.h"
#include <math.h>
#include "stdio.h"
#include <stdlib.h>
#include "stdafx.h"
#include "IniFile.h"

#define  MAX   100			
int n;					//学习样本个数
int in;					//输入层神经元数目
int hn;					//隐层神经元数目
int on;					//输出层神经元数目
double alpha;			//输出层至隐层的学习效率
double beta;			//隐层至输入层学习效率
double P[MAX];			//单个样本输入数据
double T[MAX];			//单个样本教师数据
double W[MAX][MAX];		//输入层至隐层权值
double V[MAX][MAX];		//隐层至输出层权值
double X[MAX];			//隐层的输入
double Y[MAX];			//输出层的输入
double H[MAX];			//隐层的输出
double O[MAX];			//输出层的输出
double sita[MAX];		//隐层的阈值
double gama[MAX];		//输出层的阈值
double err_m[MAX];		//第m个样本的总误差

FILE *fp=fopen("bp.log","a+");

//定义一个放学习样本的结构
struct {
	double input[MAX];
	double teach[MAX];
}Study_Data[MAX][MAX];

//初始化权、阈值
initial()
{
	float rnd;
	int i,j;

	cout<<"---------开始初始化------------------\n";
	cout<<"随机产生的权值\n";
	//隐层权、阈值初始化
	for (j=0;j<hn;j++)
	{
		for (i=0;i<in;i++)
		{
			rnd=rand()%10000;
			W[j][i]= rnd/10000;		//隐层权值初始化。
							
			cout<<"W[][]:"<<W[j][i]<<endl;
		}

		rnd=rand()%10000;
		sita[j]= rnd/10000;	//中间层阈值初始化		
		//sita[j]=0;
		//cout<<"第"<<j+1<<"个sita:"<<sita[j]<<endl;
	}

	cout<<"随机产生的权值\n";
	//输出层权、阈值初始化
	for (int k=0;k<on;k++)
	{
		for (int j=0;j<hn;j++) 
		{
			rnd=rand()%10000;
			V[k][j]=rnd/10000;	//第m个样本输出层权值初始化
			
			cout<<"V[][]:"<<V[k][j]<<endl;
		}

		rnd=rand()%10000;
		gama[k]=rnd/10000;		//输出层阈值初始化
		//gama[k]=0;
		//cout<<"第"<<k+1<<"个gama:"<<gama[k]<<endl;
	}
	
	cout<<"---------初始化结束------------------\n";
	return 1;
 
}


//第m个学习样本输入
input_P(int m)
{
	for (int i=0;i<in;i++)
		P[i]=Study_Data[m]->input[i];

	return 1;
}


//第m个样本教师信号
input_T(int m)
{
	for (int k=0;k<on;k++)   
		T[k]=Study_Data[m]->teach[k];
	
	return 1;
}

//隐层各单元输入、输出值
H_I_O()
{
	double sigma;
	int i,j;
	for (j=0;j<hn;j++)
	{
		sigma=0.0;
		for (i=0;i<in;i++)
		{
			sigma+=W[j][i]*P[i];	//求隐层内积
		}
		X[j]=sigma + sita[j];	//求隐层净输入
		
		//cout<<"sigma:"<<sigma<<"\n";
		//cout<<"隐层净输入X[]:"<<X[j]<<"\n";

		H[j]=1.0/(1.0+exp(-X[j]));	//求隐层输出
		//cout<<"隐层输出H[]:"<<H[j]<<"\n";
	}
	return 1;
}

//输出层各单元输入、输出值
O_I_O()
{
	double sigma;
	for (int k=0;k<on;k++)
	{
		sigma=0.0;
		for (int j=0;j<hn;j++)
		{
			sigma+=V[k][j]*H[j];	//求输出层内积  
		}
		Y[k]=sigma-gama[k];		//求输出层净输入
		//cout<<"输出层净输入Y[]:"<<Y[k]<<"\n";

		O[k]=1.0/(1.0+exp(-Y[k]));	//求输出层输出
		//cout<<"输出层输出O[]:"<<O[k]<<"\n";
	}
	return 1;
}

//输出层至隐层的一般化误差
double d_err[MAX];
Err_O_H(int m)
{
	double abs_err[100];		//每个样本的绝对误差都是从0开始的
	double sqr_err=0;		//每个样本的平方误差计算都是从0开始的

	for (int k=0;k<on;k++)
	{
		abs_err[k]=T[k]-O[k];
		
		//cout<<"T[K]:"<<T[k]<<"\tO[K]:"<<T[k]<<"\n";
		//cout<<"abs_err:"<<abs_err[k]<<"\n";

		//求第m个样本下的第k个神经元的绝对误差
		sqr_err+=(abs_err[k])*(abs_err[k]);		//求第m个样本下输出层的平方误差

		d_err[k]=abs_err[k]*O[k]*(1.0-O[k]);	//d_err[k]输出层各神经元的一般化误差
	}

	err_m[m]=sqr_err/2;		//第m个样本下输出层的平方误差/2=第m个样本的均方误差
	//cout<<"第"<<m+1<<"个样本err_m:"<<err_m[m]<<"\n";

	return 1;
}

//隐层至输入层的一般化误差
double e_err[MAX];
Err_H_I(){
	double sigma;

	for (int j=0;j<hn;j++)
	{
		sigma=0.0;
		for (int k=0;k<on;k++)
		{ 
			sigma+=d_err[k]*V[k][j];
		}
		e_err[j]=sigma*H[j]*(1-H[j]);	//隐层各神经元的一般化误差
	}
	return 1;
}


//输出层至隐层的权值调整、输出层阈值调整计算
Delta_O_H(int m,FILE* fp)
{
	for (int k=0;k<on;k++)
	{
		for (int j=0;j<hn;j++)
		{
			V[k][j]+=alpha*d_err[k]*H[j];	//输出层至隐层的权值调整
			//cout<<"输出层至隐层的权值调整V[][]:"<<V[k][j]<<"\n";
			//cout<<"alpha:"<<alpha<<"\td_eer[]"<<d_err[k]<<"\tH[]"<<H[j]<<"\n";
		}
		gama[k]+=alpha*d_err[k];	//输出层至隐层的阈值调整
	}
	return 1;
}

//隐层至输入层的权值调整、隐层阈值调整计算
Delta_H_I(int m,FILE* fp)
{
	for (int j=0;j<hn;j++)
	{
		for (int i=0;i<in;i++)
		{
			W[j][i]+=beta*e_err[j]*P[i];	//隐层至输入层的权值调整
			//cout<<"隐层至输入层的权值调整W[][]:"<<W[j][i]<<"\n";
		}
		sita[j]+=beta*e_err[j];
	}
	return 1;
}

//N个样本的全局误差计算
double Err_Sum()
{
	double total_err=0;
	for (int m=0;m<n;m++)
	{
		total_err+=err_m[m];	//每个样本的均方误差加起来就成了全局误差
	}
	return total_err;
}


main()
{	
	double sum_err;		
	int study=1;		//学习次数
	double Pre_error ;	//预定误差
	int Pre_times;		//预定学习次数

	cout<<"以下为从配置文件中读取的参数:\n";
	IniFile *ini = new IniFile();
	char szPathName[100];
    GetModuleFileName(NULL,szPathName,sizeof(szPathName));
    CString path=CString(szPathName);
	int nPos=path.ReverseFind('\\');
	path=path.Left(nPos);
	path+=CString("\\bp.ini");	
    ini->setIniFile(path);

	n=ini->getNumber(1,"init");
	in=ini->getNumber(2,"init");
	hn=ini->getNumber(3,"init");
	on=ini->getNumber(4,"init");	
	cout<<"样本个数:"<<n<<"\t输入层个数:"<<in<<"\t隐含层个数:"<<hn<<"\t输出层个数:"<<on<<"\n";

	alpha=ini->getNumber(1,"efficiency");
	beta=ini->getNumber(2,"efficiency");
	cout<<"alpha="<<alpha<<"\tbeta="<<beta<<"\n";

    Pre_error=ini->getNumber(1,"Pre_error");
	Pre_times=ini->getNumber(1,"Pre_times");
	cout<<"预定误差="<<Pre_error<<"\t预定学习次数="<<Pre_times<<"\n";


	int m=0;
	cout<<"学习样本:";
	for (m=0;m<n;m++)
	{
		for (int i=0;i<in;i++)
		{	
			Study_Data[m]->input[i]=ini->getNumber(in*m+i+1,"input");
			cout<<Study_Data[m]->input[i]<<"\t";
		}
	}
	cout<<"\n";
	cout<<"教师样本:";
	for (m=0;m<n;m++)
	{
		for (int k=0;k<on;k++)
		{
			Study_Data[m]->teach[k]=ini->getNumber(on*m+k+1,"output");
			cout<<Study_Data[m]->teach[k]<<"\t";
		}
	}
	cout<<"\n";

	char start;
	cout<<"是否开始学习(y/n):";
	cin>>start;

	if(start=='y')
	{
			initial();	//隐层、输出层权、阈值初始化 
			double total_err=0;   
			do
			{
				
				for (int m=0;m<n;m++) 
				{
					cout<<"第"<<m+1<<"个样本学习中...\n";

					input_P(m);		//输入第m个学习样本 
					input_T(m);		//输入第m个样本的教师信号
					H_I_O();		//第m个学习样本隐层各单元输入、输出值 
					O_I_O();		//第m个学习样本输出层各单元输入、输出值
					Err_O_H(m);		//第m个学习样本输出层至隐层一般化误差 
					Err_H_I();		//第m个学习样本隐层至输入层一般化误差
					Delta_O_H(m,fp);	//第m个学习样本输出层至隐层权阈值调整、修改 
					Delta_H_I(m,fp);	//第m个学习样本隐层至输入层权阈值调整、修改 

					cout<<"经过学习后的输出:";
					for(int k=0;k<on;k++)
						cout<<O[k]<<"\t";
					cout<<"\n教师样本为:";
					for(k=0;k<on;k++)
						cout<<Study_Data[m]->teach[k]<<"\t";
					cout<<"\n";
					cout<<"----------样本学习结束-----------------\n";
				} //全部样本训练完毕

				sum_err=Err_Sum(); //全部样本全局误差计算 

				cout<<"第"<<study<<"次学习的均方误差为"<<sum_err<<endl;
				fprintf(fp,"第%d次学习的均方误差为:%f\n",study,sum_err);

				cout<<"调整后的权值为:\n";
				for(int i1=0;i1<hn;i1++)
					for(int j1=0;j1<in;j1++)
						cout<<"W[][]:"<<W[i1][j1]<<"\n";
				
				for(int i2=0;i2<on;i2++)
					for(int j2=0;j2<hn;j2++)
						cout<<"V[][]:"<<V[i2][j2]<<"\n";
			
				//char c;
				//cout<<"请随便输入一个字符,按回车!\n";
				//cin>>c;
				cout<<"*************************************"<<"\n";
				
				if(study>=Pre_times)
					break;
				study++; 

			}while (sum_err > Pre_error) ;   
			//N个样本全局误差小于预定误差否?小于则退出 

			if(sum_err <= Pre_error)
			{
				char study='y';
				cout<<"学习结束,是否要验证(y/n):";
				cin>>study;
				while(study=='y')
				{
					for (int i=0;i<in;i++)
					{	
							cout<<"请输入第"<<i+1<<"个输入:"; 
							cin>>Study_Data[0]->input[i];
					}

					input_P(0); 
					input_T(0);
					H_I_O(); 
					O_I_O(); 
					Err_O_H(0); 
					Err_H_I(); 
					//Delta_O_H(0,fp); 
					//Delta_H_I(0,fp); 
					
					cout<<"经过学习后的输出:";
					for(int k=0;k<on;k++)
						cout<<O[k]<<"\t";
					cout<<"\n";


					cout<<"是否还验证(y/n):";
					cin>>study;
				}
			}
			else
			{
				cout<<"学习次数太少,不能到达预期目的\n";
				cout<<"请重新设定学习次数\n";
			}
	}
	char s;
	cout<<"请随便输入一个字符,按回车退出程序!\n";
	cin>>s;

	fclose(fp);
	return 1;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -