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

📄 bp.cpp

📁 一个简单灵活的数据挖掘实验平台
💻 CPP
字号:
#pragma warning(disable: 4786)

#include "BP.h"
#include "..\\Core\\Exception.h"
#include "..\\Utils\\xs.h"
#include "..\\Input\\File\\ArffStream.h"
#include <cmath>
#include <fstream>
#include <iostream>

//: for test
#include <ctime>
using namespace std;
BP::BP(vector<Data>* train_set,BP_PARAM params)
{

	_ni        = params.input;
	_nh        = params.hidden;
	_no        = params.output;
	_enta      = params.learning_rate;
	_range     = params.random_range;
	_max_epoch = params.max_epoch;

	_train_set = train_set;
	
	this->initialize();
}
BP::~BP()
{
	delete[] _wih;	delete[] _who;
	delete[] _dwih;	delete[] _dwho;

	delete[] _bh;	delete[] _bo;
	delete[] _dbh;	delete[] _dbo;
	delete[] _sh;	delete[] _so;
	delete[] _oh;	delete[] _oo;
}
void BP::train()
{
	if(_train_set == NULL)
		throw new Exception("BP::train, current is working mode, training is forbidden!");
	int i = 0;
	vector<Data>::iterator it;
	while(i++<_max_epoch)
	{
		for(it=_train_set->begin();it!=_train_set->end();it++)
		{
			forward(*it);
			backward(*it);
		}
		update_weights();
	}
}
void BP::work(Data& data)
{
	this->forward(data);
	for(int k=0;k<_no;k++)
		data[_ni+k] = _oo[k];
}
void BP::check()
{
	
	if(_ni < 0)
		throw new Exception("BP::check,input layer count < 0");
	cout<<"BP: using input layer count: "<<_ni<<endl;
	if(_nh < 0)
		throw new Exception("BP::check,hidden layer count < 0");
	cout<<"BP: using hidden layer count: "<<_nh<<endl;
	if(_no < 0)
		throw new Exception("BP::check,output layer count < 0");
	cout<<"BP: using output layer count: "<<_no<<endl;
	if(_enta < 0)
		throw new Exception("BP::check,learning rate < 0");

	if(_enta >= 1)
		cout<<"WARNING: learning rate>=1.0"<<endl;
	cout<<"BP: using learning rate: "<<_enta<<endl;
	if(abs(_range)>0.5)
		cout<<"WARNING: random range>0.5"<<endl;
	cout<<"BP: using random range: "<<_range<<endl;
	if(_max_epoch < 100)
		cout<<"WARNING: maximum epoch count < 100"<<endl;
	if(_max_epoch > 10000)
		cout<<"WARNING: maximum epoch count > 10000"<<endl;
	cout<<"BP: using maximum epoch: "<<_max_epoch<<endl;
}

double BP::random()
{
	return _range*(rand()-RAND_MAX/2)/RAND_MAX*2;
}
void BP::initialize()
{
	this->check();
	
	//: weights
	_wih  = new double[_ni*_nh];
	_who  = new double[_nh*_no];
	_dwih = new double[_ni*_nh];
	_dwho = new double[_nh*_no];
	
	//: biases
	_bh   = new double[_nh];
	_bo   = new double[_no];
	_dbh  = new double[_nh];
	_dbo  = new double[_no];

	//: sigma error
	_sh   = new double[_nh];
	_so   = new double[_no];
	//: output 
	_oh   = new double[_nh];
	_oo   = new double[_no];

	int i,j,k;
	//: initialize weights and biases with random range
	for(i=0;i<_ni;i++)
	{
		for(j=0;j<_nh;j++)
		{
			_wih[i*_nh+j]  = random();
			_dwih[i*_nh+j] = 0;
		}
	}
	for(j=0;j<_nh;j++)
	{
		for(k=0;k<_no;k++)
		{
			_who[j*_no+k]  = random();
			_dwho[j*_no+k] = 0;
		}
	}
	for(j=0;j<_nh;j++)
	{
		_bh[j] = random();
		_dbh[j] = 0;
	}
	for(k=0;k<_no;k++)
	{
		_bo[k] = random();
		_dbo[k] = 0;
	}
}
void BP::forward(Data data)
{
	int i,j,k;
	//: hidden layer
	for(j=0;j<_nh;j++)
	{
		double netj = _bh[j]; //: bias is a must
		for(i=0;i<_ni;i++) //: compute input layer activity
			netj += data[i]*_wih[i*_nh+j];
		_oh[j] = squash(netj);
	}
	//: output layer
	for(k=0;k<_no;k++)
	{
		double netk = _bo[k]; //: bias is a must
		for(j=0;j<_nh;j++) //: compute hidden layer activity
			netk += _oh[j] *_who[j*_no+k];
		_oo[k] = squash(netk);
	}
}
void BP::backward(Data data)
{
	int i,j,k;
	//: output layer backward propagation
	for(k=0;k<_no;k++)
		_so[k] = dx_squash(_oo[k])*(data[_ni+k]-_oo[k]);
	//: hidden layer backward propagation
	for(j=0;j<_nh;j++)
	{
		double ss = 0;
		//: calculates the sigma of output layer affection
		for(k=0;k<_no;k++)
			ss += _who[j*_no+k]*_so[k];
		_sh[j] = dx_squash(_oh[j])  * ss;
	}
	//: compute delta weights and delta bias weights
	for(j=0;j<_nh;j++)
		for(k=0;k<_no;k++)
			_dwho[j*_no+k] += _enta*_so[k]*_oh[j];
	for(i=0;i<_ni;i++)
		for(j=0;j<_nh;j++)
			_dwih[i*_nh+j] += _enta*_sh[j]*data[i];
	for(j=0;j<_nh;j++)
		_dbh[j] += _enta*_sh[j];
	for(k=0;k<_no;k++)
		_dbo[k] += _enta*_so[k];

}
void BP::update_weights()
{
	int i,j,k;
	//: weights between input and hidden layer
	for(i=0;i<_ni;i++)
		for(j=0;j<_nh;j++)
			_wih[i*_nh+j] += _dwih[i*_nh+j];
	//: weights between hidden and output layer
	for(j=0;j<_nh;j++)
		for(k=0;k<_no;k++)
			_who[j*_no+k] += _dwho[j*_no+k];

	for(j=0;j<_nh;j++)
		_bh[j] += _dbh[j];
	for(k=0;k<_no;k++)
		_bo[k] += _dbo[k];

	//:reset delta weights
	for(j=0;j<_nh;j++)
		for(k=0;k<_no;k++)
			_dwho[j*_no+k] = 0;
	for(i=0;i<_ni;i++)
		for(j=0;j<_nh;j++)
			_dwih[i*_nh+j] = 0;
	for(j=0;j<_nh;j++)
		_dbh[j] = 0;
	for(k=0;k<_no;k++)
		_dbo[k] = 0;
}
//////////////////////////////////////////////////////////////////////////
//: activity functions
//////////////////////////////////////////////////////////////////////////
double BP::squash(double net)
{
	return 1/(1+exp(-net));
}
//: o is the output of the neuron
double BP::dx_squash(double o)
{
	return o*(1-o);
}
double BP::linear(double net)
{
	return net;
}
double BP::dx_linear(double o)
{
	return 1;
}
//////////////////////////////////////////////////////////////////////////
//: saving and loading network file section here
//////////////////////////////////////////////////////////////////////////
//: saves the network to a specified file, for data format see the content
void BP::save(string file)
{
	ofstream stream(file.c_str());
	if(!stream.is_open())
		throw new Exception("LUGD::save file: "+file + " cannot open to write");
	//: file save format as following, input,output,weight sections
	stream<<"INPUT="<<_ni<<endl;
	stream<<"HIDDEN="<<_nh<<endl;
	stream<<"OUTPUT="<<_no<<endl;
	stream<<"WIH=";
	int i;
	int lih = _ni*_nh;
	for(i=0;i<lih;i++)
	{
		if(i != lih-1)	stream<<_wih[i]<<",";
		else stream<<_wih[i]<<endl;
	}
	int lho = _nh*_no;
	stream<<"WHO=";
	for(i=0;i<lho;i++)
	{
		if(i != lho-1)	stream<<_who[i]<<",";
		else stream<<_who[i]<<endl;
	}
	stream<<"BH=";
	for(i=0;i<_nh;i++)
	{
		if(i != _nh-1)	stream<<_bh[i]<<",";
		else stream<<_bh[i]<<endl;
	}
	stream<<"BO=";
	for(i=0;i<_no;i++)
	{
		if(i != _no-1)	stream<<_bo[i]<<",";
		else stream<<_bo[i]<<endl;
	}
}
//: load the network from a specified file to build a BP algorithm
BP* BP::load(string file)
{
	ifstream stream(file.c_str());
	if(!stream.is_open())
		throw new Exception("Cannot open file: "+file);

	//:reads input,output and weight section strings
	string input,hidden,output,wih,who,bh,bo;
	if(!getline(stream,input))
		throw new Exception("File missing input-node number line,check for no blank line!");
	if(!getline(stream,hidden))
		throw new Exception("File missing hidden-node number line,check for no blank line!");
	if(!getline(stream,output))
		throw new Exception("File missing output-number data line,check for no blank line!");
	if(!getline(stream,wih))
		throw new Exception("File missing weights between input and hidden layer,check for no blank line!");
  	if(!getline(stream,who))
		throw new Exception("File missing weights between hidden and output layer,check for no blank line!");
	if(!getline(stream,bh))
		throw new Exception("File missing bias weight of hidden layer,check for no blank line!");
	if(!getline(stream,bo))
		throw new Exception("File missing bias weight of output layer,check for no blank line!");
    stream.close();
	//: parses the three sections
	vector<string> vi = xs::split(input," =;");
	if(vi.size() != 2)
		throw new Exception("input section format error!");
	int ni = atoi(vi[1].c_str());
	vector<string> vh = xs::split(hidden," =;");
	if(vh.size() != 2)
		throw new Exception("hidden section format error!");
	int nh = atoi(vh[1].c_str());
	vector<string> vo = xs::split(output," =;");
	if(vo.size() != 2)
		throw new Exception("output section format error!");
	int no = atoi(vo[1].c_str());

	vector<string> vwih = xs::split(wih," =,;");
	if(vwih.size() != ni*nh+1 )
		throw new Exception("wih section format error!");
	vector<string> vwho= xs::split(who," =,;");
	if(vwho.size() != nh*no+1 )
		throw new Exception("who section format error!");
	vector<string> vbh = xs::split(bh," =,;");
	if(vbh.size() != nh+1 )
		throw new Exception("BH section format error!");
	vector<string> vbo = xs::split(bo," =,;");
	if(vbo.size() != no+1 )
		throw new Exception("BO section format error!");

	BP_PARAM params;
	params.input = ni;
	params.hidden = nh;
	params.output = no;
	BP* bp = new BP(NULL,params);
	for(int i=1;i<vwih.size();i++)
		bp->_wih[i-1] = atof(vwih[i].c_str());
	for(i=1;i<vwho.size();i++)
		bp->_who[i-1] = atof(vwho[i].c_str());
	for(i=1;i<vbh.size();i++)
		bp->_bh[i-1] = atof(vbh[i].c_str());
	for(i=1;i<vbo.size();i++)
		bp->_bo[i-1] = atof(vbo[i].c_str());

	return bp;
}

//========================================================================
/************************************************************************/
void main()
{
	clock_t start,end;
	
	start = clock();
	BP_PARAM params;
	ArffStream arff("arff//838.arff");
	try
	{
		arff.open();
		vector<Data> data;
		while(arff.next())
		{
			data.push_back(Data(arff.data()));
		}
		params.input = 8;
		params.hidden = 3;
		params.output = 8;
		params.learning_rate = 0.5;
		params.random_range = 0.01;
 		params.max_epoch = 5000;
//		BP* bp = BP::load("arff//bp.ini");
//
		BP* bp = new BP(&data,params);
		bp->train();

// 		bp->save("arff//bp.ini");
        
        Data d = data[1];
		cout<<d.to_string()<<endl;
		bp->work(d);
		cout<<d.to_string()<<endl;
		delete bp;
	}
	catch(Exception* e)
	{
		cout<<e->message()<<endl;
		delete e;
	}
	end = clock();
	cout<<"Time eclipsed[s]:"<<(double)(end-start)/CLOCKS_PER_SEC<<endl;
}
/************************************************************************/

⌨️ 快捷键说明

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