📄 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 + -