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

📄 bp.cpp

📁 BP神经网络分类器 程序有两种运行状态
💻 CPP
字号:
#include <iostream.h>
#include <fstream.h>
#include <time.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>

#define HIDDENLAYER 10
#define INLEN 6
#define OUTLEN 3
#define NUMOFSAMPLES 14


class FileRender{

	
	ofstream fout;
	ifstream fin;


public:
	FileRender(){
			
	}
//This function writes the weight matrix into the  filename
// * L1_Matrix (inLen * HIDDENLAYER)
// * L2_Matrix (HIDDENLAYER * outLen )
void putWeights(char * fileName,int inLen, int outLen,
                          double * L1_Matrix, double * L2_Matrix){
    int i,j;
                           			
	fout.open(fileName,ios::out|ios::app);//open file
	if(!fout){
		cerr<<fileName<<" cannot be opened"<<endl;
		exit(1);
	}
	
	for (i = 0; i < inLen; i++){
	   for (j = 0; j < HIDDENLAYER; j++)
	       fout<<*L1_Matrix++<<" ";
	   fout<<endl;
	}
	
	for (i = 0; i < HIDDENLAYER; i++){
	   for (j = 0; j < outLen; j++)
	       fout<<*L2_Matrix++<<" ";
	   fout<<endl;
	}

		
		
    fout.close();

		
	}
//This function writes the classfication results into the  filename
// results[sum][OUTLEN] contains the results of classfication
void putResults(char * fileName,double * results,int sum){
    int i,j, largest;
                           			
	fout.open(fileName,ios::out|ios::app);//open file
	if(!fout){
		cerr<<fileName<<" cannot be opened"<<endl;
		exit(1);
	}
	
	for (i = 0; i < sum; i++){
	   largest = 0;
	   for (j = 0; j < OUTLEN; j++)
	       //if( results[i*OUTLEN+j] > results[i*OUTLEN+largest])
			//largest = j;
			if( fabs(results[i*OUTLEN+j] - 1) < 0.1)// 10 can be changeto 1
			switch(j){
				case 0:
					fout<<"第"<<i+1<<"个行业为一般行业"<<endl;break;
				case 1:
					fout<<"第"<<i+1<<"个行业为辅助行业"<<endl;break;
				case 2:
					fout<<"第"<<i+1<<"个行业为主导行业"<<endl;break;
				default:
					fout<<"error"<<endl;
			}

	   
		}
		
    fout.close();
}

//This function gets the weight matrix from the  filename
// * L1_Matrix (inLen * HIDDENLAYER)
// * L2_Matrix (HIDDENLAYER * outLen )
void getWeights(char * fileName,int inLen, int outLen,
                          double * L1_Matrix, double * L2_Matrix){
    int i,j;
                           			
	fin.open(fileName,ios::in|ios::nocreate);//open file
	if(!fin){
		cerr<<fileName<<" cannot be opened"<<endl;
		//return NULL;
		exit(1);
	}
	
	for (i = 0; i < inLen; i++)
	   for (j = 0; j < HIDDENLAYER; j++)
	       fin>>*L1_Matrix++;
	
	for (i = 0; i < HIDDENLAYER; i++)
	   for (j = 0; j < outLen; j++)
	       fin>>*L2_Matrix++;
		
		
    fin.close();

		
}

// This function reads in the learning samples and their tutor into two matrix
// *filename is the name of the file which contains the learning samples and tutors
 // *num is the number of the total samples
 // *InLen is the num of the  length of the learning sample
 // *outLen is the length of the tutor
 // *sampleMatrix is the starting address of the matrix which contains the learning sample datum(num*InLen)
 // *tutorMatrix is the starting address of the matrix which contains the learning sample datum(num*outLen)
	void learningFromTutor(char * fileName, int num, int inLen, int outLen,
                          double * sampleMatrix, double * tutorMatrix){			
		
	    int i,j;
	
		
		fin.open(fileName,ios::in|ios::nocreate);
		if(!fin){
			cerr<<fileName<<" cannot be opened"<<endl;
			exit(1);
		}
		for(i = 0; i < num; i++){
			for(j = 0; j < inLen; j++)
				fin>>*sampleMatrix++;  //reading in the learning sample
			for(j = 0; j < outLen; j++)
                fin>>*tutorMatrix++;  //reading in the tutors	

        }
        fin.close();

	}
// This function reads in the datum to be classfied
// *filename is the name of the file which contains the learning samples and tutors
 // *num is the number of the total items
 // *InLen is the num of the  length of the learning sample
 // *outLen is the length of the tutor
 // *sampleMatrix is the starting address of the matrix which contains the data to be classfied
	void readInDatum(char * fileName, int num, int inLen, double * sampleMatrix){			
		
	    int i,j;
	
		
		fin.open(fileName,ios::in|ios::nocreate);
		if(!fin){
			cerr<<fileName<<" cannot be opened"<<endl;
			exit(1);
		}
		for(i = 0; i < num; i++){
			for(j = 0; j < inLen; j++)
				fin>>*sampleMatrix++;  //reading in the datum to be classfied
		}
        fin.close();

	}



	~FileRender(){
		if(fout != NULL) fout.close();
		if(fin != NULL) fout.close();
		
	}

};//end of class FileRender

class BP{
    FileRender fRender;
    int inLen,outLen,numOfSamples;
    double sampleMatrix[NUMOFSAMPLES][INLEN];
    double tutorMatrix[NUMOFSAMPLES][OUTLEN];
    double L1_Matrix[INLEN][HIDDENLAYER],L2_Matrix[HIDDENLAYER][OUTLEN];
    double errorLimit,learningRate;
    int itera;//itera: How many times iterated
    int learnAt;//learnAt: which sample is the BP learning
    int i,j;// looping variables
    double Init;//learning initia
    double temper;
    double L2_Node[HIDDENLAYER][2], L3_Node[OUTLEN][2];
	bool timeOff;
    //[][0] for the node's input value, [][1] for node's output value
	void calL2InAndOut(int index){
		//index stands for the sequence number of the samples
		int i,j;
		double sum;
		for(i = 0; i < HIDDENLAYER; i++){
			sum = 0;
			for(j = 0; j < INLEN; j++){
				sum += L1_Matrix[j][i] * sampleMatrix[index][j];
			}
			L2_Node[i][0] = sum;
			L2_Node[i][1] = sigmoid(sum);
		}
	}
	
	void calL3InAndOut(){
		int i,j;
		double sum;
		for(i = 0; i < OUTLEN; i++){
			sum = 0;
			for(j = 0; j < HIDDENLAYER; j++){
				sum += L2_Node[j][1] * L2_Matrix[j][i];
			}
			L3_Node[i][0] = sum;
			L3_Node[i][1] = sigmoid(sum);
		}
	
	}
    
	bool  checkPass(int index){
		//index is the number sequence of the samples
		int i;
		double sum = 0;
		
		for(i = 0; i < OUTLEN; i++)
			//if((L3_Node[i][1] - tutorMatrix[index][i]) > errorLimit)
			sum +=  pow((L3_Node[i][1] - tutorMatrix[index][i]),2);
		return ( ( sum / 2 ) < errorLimit);
		 
	}
	void adjustWeight(int index){
		int i,j,k;
		double L2_Backup[HIDDENLAYER][OUTLEN];
		double DE[OUTLEN];
		double DE2;

		//adjust L2 weight matrix
	    for(i = 0; i < HIDDENLAYER; i++)
			for(j = 0; j < OUTLEN; j++){
				   L2_Backup[i][j] = L2_Matrix[i][j];
				   DE[j] =  (L3_Node[j][1] - tutorMatrix[index][j]) * deSigmoid(L3_Node[j][0]);
	       	       L2_Matrix[i][j] = L2_Matrix[i][j]*Init - learningRate * DE[j] * L2_Node[i][1];
			}
						

		//adjust L1 weight matrix 
	    for(i = 0; i < INLEN; i++)
			for(j = 0; j < HIDDENLAYER; j++){
				DE2 = 0;
				for(k = 0; k < OUTLEN ; k++){
					DE2 += L2_Backup[j][k] * DE[k];
				}
				DE2 *=  deSigmoid(L2_Node[j][0]);
	       	    L1_Matrix[i][j] = L1_Matrix[i][j]*Init - learningRate * DE2 * L2_Node[i][1];
			}
				
	}

    public:
    BP(){
	    itera = 999999;
	    learningRate = 0.5;
	    learnAt = 0;
	    Init = 1;
	    errorLimit = 0.01;
	    temper = 1;
		timeOff = false;
	    
	    //initializing the weight matrixs
	    for(i = 0; i < INLEN; i++)
	       	    for(j = 0; j < HIDDENLAYER; j++)
	       	       L1_Matrix[i][j] = random(i*INLEN+j);
	    for(i = 0; i < HIDDENLAYER; i++)
	       	    for(j = 0; j < OUTLEN; j++)
	       	       L2_Matrix[i][j] = random(i*HIDDENLAYER+j);
    }//End of BP()
    
    
    ~BP(){
    }

	void setIter(int i){
		itera = i;
	}
    bool isFinished(){

    }
    
    void learningFromTutor(char * sampleFileName, char * weightFileName){

        int i;//i for big loop,by finishing this loop all samples learned
		//int j,k;
		bool passedWithWeightChange = 0;
		int  numOfSamplesLearned = 0;
		int ite = 0;
        
        fRender.learningFromTutor(sampleFileName,NUMOFSAMPLES,INLEN,OUTLEN,
                          *sampleMatrix, *tutorMatrix);//read datum
        //following code performes the learning process

	 
		/*	for(j = 0; j < NUMOFSAMPLES; j++ ){
				for(k = 0; k < INLEN; k++){
					cout<<sampleMatrix[j][k]<<" ";
				}
				cout<<endl;
			}
			for(j= 0; j < NUMOFSAMPLES; j++ ){
				for(k = 0; k < OUTLEN; k++){
					cout<<tutorMatrix[j][k]<<" ";
				}
				cout<<endl;			
			}
		*/
	
     
        for(i = 0; i < NUMOFSAMPLES; i = (i + 1) % NUMOFSAMPLES){
			calL2InAndOut(i);
			calL3InAndOut();
			passedWithWeightChange = 0;
			while(!checkPass(i) ){
				ite++;
				cout<<ite<<"th interation for sample "<<i<<" ."<<endl;
				passedWithWeightChange = 1;
				adjustWeight(i);
				calL2InAndOut(i);
				calL3InAndOut();
			}
			if(!passedWithWeightChange)
				numOfSamplesLearned++;
			else
				numOfSamplesLearned = 0;

			if(timeOff){
				if(numOfSamplesLearned == NUMOFSAMPLES )
				break;//learning finished,you can set the ite >= itera as the exit condition
			}else{
				if(numOfSamplesLearned == NUMOFSAMPLES || ite > itera)
				break;//learning finished,you can set the ite >= itera as the exit condition			
			}
			 
        }//end of i loop


        //write the weights learned into the two matrixes   			
        fRender.putWeights(weightFileName,INLEN,OUTLEN,*L1_Matrix,*L2_Matrix);
        
    }

	void setTimesOff(bool b){
		timeOff = b;
	}

    //classfy can classft an input array based on the former learning knowledge
    // *inArray[] stores the data to be classfied
    // *outArray[] stores the results of classfication
    void classfy(double *inArray, double * outArray, double * L1_Matrix, double * L2_Matrix){
        //get the weight matrixes learned from the filename   			
		int i,j;
		double sum;
        //fRender.getWeights(fileName,INLEN,OUTLEN,*L1_Matrix,*L2_Matrix);

		for(i = 0; i < HIDDENLAYER; i++){
			sum = 0;
			for(j = 0; j < INLEN; j++){
				sum += L1_Matrix[j*HIDDENLAYER+i] * inArray[j];
			}
			L2_Node[i][0] = sum;
			L2_Node[i][1] = sigmoid(sum);
		}
		for(i = 0; i < OUTLEN; i++){
			sum = 0;
			for(j = 0; j < HIDDENLAYER; j++){
				//sum += L2_Node[j][1] * L2_Matrix[j*HIDDENLAYER+i];
				sum += L2_Node[j][1] * L2_Matrix[j*OUTLEN+i];
			}
			//L3_Node[i][0] = sum;
			*outArray = sigmoid(sum);
			cout<<*outArray<<endl;
			outArray++;
			
		}

    }
    //classfyFile can classf an bundle of datum stored in a file
	//based on the former learning knowledge
    // *dataFile stores the data to be classfied
	//*resultFile stores the result of the classfication
	// sum indicates how many items to be classfied
    void classfyFile(int sumOfItems, char *dataFile, char * resultFile, char * weightFileName){
        //get the weight matrixes learned from the filename   			
		int i,j,k;
		double * datum_back, * results_back;
		double * datum =(double*) malloc(sizeof(double) * sumOfItems * INLEN);
		double * results = (double*)malloc(sizeof(double) * sumOfItems * OUTLEN);

		datum_back = datum;
		results_back = results;

        fRender.getWeights(weightFileName,INLEN,OUTLEN,*L1_Matrix,*L2_Matrix);
	 /*
			for(j = 0; j < INLEN; j++ ){
				for(k = 0; k < HIDDENLAYER; k++){
					cout<<L1_Matrix[j][k]<<" ";
				}
				cout<<endl;
			}
			for(j= 0; j < HIDDENLAYER; j++ ){
				for(k = 0; k < OUTLEN; k++){
					cout<<L2_Matrix[j][k]<<" ";
				}
				cout<<endl;			
			}
	*/	

		fRender.readInDatum(dataFile,sumOfItems,INLEN,datum);

			for(j= 0; j < sumOfItems; j++ ){
				for(k = 0; k < INLEN; k++){
					cout<<datum[j*INLEN+k]<<" ";
				}
				cout<<endl;			
			}

		for(i = 0; i < sumOfItems; i++){
			classfy(datum_back,results_back,*L1_Matrix,*L2_Matrix);
			datum_back += INLEN;
			results_back += OUTLEN;
		}

		for(i = 0; i < sumOfItems; i++){
			for(j = 0; j < OUTLEN; j++){
				cout<<*(results+i*OUTLEN+j)<<" " ;
			}
			cout<<endl;
		}

		fRender.putResults(resultFile, results, sumOfItems);
		
	}
    
    void setLearningInit(double i){
        Init = i;
    }
    void setErrorLimit(double e){
        errorLimit = e;
    }
    double getErrorLimit(){
        return(errorLimit);
    }
    void setLearningRate(double r){
        learningRate = r;
    }
    double getLearningRate(){
        return(learningRate);
    }
    
    void setTemperature(double t){
        temper = t;
    }

    double random(int seed){
        int num,m_rand;
        double m_fRand;
        double bound = 27;
        srand( time(NULL) + seed );
        m_rand = rand();
        while( (num=m_rand%100) <= bound ) m_rand = rand(); ;
        m_fRand = bound/num;
        return m_fRand;
    }

    double sigmoid(double x){
         return ( 1 / (1 + exp(-x*temper)) );
    }

    double deSigmoid(double x){
         return ( sigmoid(x) * (1 - sigmoid(x) )  );
    }

};//end of class BP



int main(int argc, char *argv[]){
    BP bp;
 
    
    char * sampleFile = "sample.dat";
	char * weightFile = "weight.dat";
	char * datumFile = "classfyMe.dat";
	char * resultsFile = "results.dat";
	int items,iter;
	double e;
    /*---------  The learning rate,learning initia and error boundary can be setted alternativly
    //---------  The default value for the 3 para are  r= 0.5 e = 0.01 ini = 1
    int i;
	double e,r,ini;
    cout<<"please input the minimum error differency:"<<endl;
    cin>>e;
    cout<<"please input the iteration times:"<<endl;
    cin>>iter;

    cout<<"please input the learning initia:"<<endl;
    cin>>ini;
    cout<<"please input the learning rate:"<<endl;
    cin>>r;
    bp.setErrorLimit(e);
    bp.setLearningRate(r);
    bp.setLearningInit(ini);
	bp.setIter(iter);
    -----------*/
	
    //if you just start the learning ,just remove the following comment mark
	if(!strcmp(argv[1],"learn")){

		cout<<"请输入迭代次数(如果输入0则表示采用系统的默认次数(999999次)):"<<endl;    
		cin>>iter;
		if(iter != 0)		bp.setIter(iter);
		cout<<"请输入误差上限(如果输入0则表示采用系统的默认上限(0.01)):"<<endl;    
		cin>>e;
		if(e != 0) bp.setErrorLimit(e);

		//bp.setErrorLimit(0.000001);
		//bp.setIter(999999);
		//bp.setTimesOff(true);//no time limit
		bp.learningFromTutor(sampleFile,weightFile);

	}else if(!strcmp(argv[1],"work")){
		cout<<"请输入有多少样本待分类:"<<endl;
		cin>>items;
		bp.classfyFile(items, datumFile, resultsFile, weightFile);
	}

    return (1);
}

⌨️ 快捷键说明

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