//neural.cpp, the "reincarnated" version. //(c) 1999, Oguz Yetkin //NO OBJECTS IN THIS ONE. //the header was last modified 1/11/1999 //when the program was last modified is anyone's guess :) // //WARNING! CURRENTLY PROGRAM DOESN'T TEST EXISTING NETS FOR ERROR, AND IS NOT //SUITEDFOR DISTRIBUTED TRAINING! #include #include #include #include #include #include #include #include "array2d.h" #include "neural.h" #define PI 3.141592654 //for export of data to outside applications double** trainset; double** trainnew; //newset const int MAX=64; int num=5; //we'll use globals for speed and simplicity long n=32; long m=32; double s=1; double d0=0.000001; long gaussnum=32; array2d* wts; double* x; double* y; double* xe; double* ye; //globals long Gimprovements=0; long Gsteps=0; double Gerror=0; double Gle=0; long Gleiters=200; //iterations for lyapunov calculation double Gmisses=0; double Gconstraint=0; double Gcalculate_lyapunov=1; double Gtemperature=1; //added 2/8/1999 double Glower=0; //lower LE constraint double Gupper=0; //upper LE constraint //1 for passing constraint, 0 for failing it. int constrain(double constraint, double le){ if(Glower!=0||Gupper!=0){ //ignore others, work on global constraints if(le>Gupper){ return 0; } if(le0){ return 1; } if(constraint==-1 && le<=0){ return 1; } if(le==0){ return 1; //just to get things going... } return 0; } void report(void){ //output to screen static int firstrun=1; if(firstrun==1){ firstrun=0; cout<<"%improvements steps error le temp misses constraint:"<base[j][i]=output[j]; } } */ //old_error=error(tset, newset->base, n, tlength); //new_error=old_error; //cout<<"\ninit error is: "<base[i][j]=output[j]; input[j]=output[j]; //added 1/6/1998, reassign! } } //calculate new error new_error=error(tset, newset->base, n, tlength); cerr<<"\noriginalerror determined to be: "<=old_error){ Gsteps++; //global variable for stats tracking //printf("\n**new_error:%f>old_error:%f temp: %f",new_error, old_error,temp); //create copy of network for(i=0;ibase[i][j]=wts[i][j]; //changed 1/4/1998 //changed 1/6/1998--let caller handle zeroing out! //scratch->base[i][j]=0; scratch->base[i][j]=wts[i][j]; } } //perturb the weights //cout<<"\nperturbing weights!"<base[i][j]+=((temp*(rand()/(double)RAND_MAX))/(float)sqrt(m)); //division of gauss() by sqrt(m) added 1/10/1999 scratch->base[i][j]+=temp*gauss()/(float)sqrt(m); } } //cout<<"\nweights perturbed!"<base, n,m,s); for(j=0;jbase[i][j]=output[j]; input[j]=output[j]; //added 1/6/1998, reassign! } } /* cout<<"\n***dumping input: "<base[i][n-1]<<" "; } */ ::trainset=tset; //set global variables for comm w/ outside :: trainnew=newset->base; //calculate new error new_error=error(tset, newset->base, n, tlength); //printf("\n--t: %f e:%f !base,Gleiters); } if(constrain(Gconstraint, Gle)==0){ //the way this works is backwards, //don't ask me why Oguz 1/12/1999 2:39 am //cout<<"\nfailed!"<base[i][j]; } } //since we've found something better, double the temperature if(temp<1){ temp*=2; } }else{ /* label fail */ //means scratch will not be copied to wts either because //of bad error or lyapunov constraint failure fail: //temp*=1.1; temp*=cooldown; //cooldown must be less than one } }//end while return new_error; } //I/O functions. We assume user knows file size in network. //this may change in the future //written 1/10/1999 3:40 am //neural net file has the form int save(double** wts, int n, int m, double s, char* filename, char* header){ int returnval=0,i,j; ofstream outfile; if(header==NULL){ header=new char[MAX]; sprintf(header,"%d %d %f",n,m,s); //write a minimal amt of info } outfile.open(filename); if(!outfile){ returnval=0; goto end; //bail out } outfile<>wts[i][j]; if(infile.eof()){ goto end; //bail out with error } } } returnval=1; end: return returnval; } //takes training input from a file, and trains for "improvements" steps //runs the trained net ever run_freq improvements for run_len iters if run_len //is >0. If run_len==0, then outfilename is ignored //tset file looks like: //n1 n2 n3...nN //t0 t0 t0...t0 //t1 t1 t1...t1 //... //tTlength... //where every column is a desired time series entry for a neuron int trainonfile(char* trainfilename, char*netfilename, char* outfilename, int n, int m, double s, long goal_improvements, long run_freq, long run_len, double& error){ /* set the globals */ Gimprovements=0; Gsteps=0; Gerror=0; Gle=0; Gmisses=0; if(Gconstraint!=0){ Gcalculate_lyapunov=1; } long i,j,k; long improvements=0; int ok=0; ifstream trainfile; ofstream outfile; ofstream netfile; array2d* tset; array2d* wts; double* input; double* output; char header[MAX]; //neural file header, may come in handy long tlength=n; //length of training set double temp=1; double cooldown=0.9995; cerr<<"\n**allocating "<base, n, m, netfilename, header); //delete[] header; if(!ok){//there's no file there, we have to create our own net cerr<<"**zeroing out weights"<bzero(); /* disabled because this messes up sine positive 1/13/1999 2:43 am */ //error=0;//if error is 0, train() automatically determines it for you //wts->randomize(); } ok=save(wts->base, n, m, s, netfilename,NULL); //ok=load(wts->base, n, m, netfilename, header); //redundant, but will make it work if(!ok){ cerr<<"\ncouldn't save: "<>ch; //load training set trainfile.open(trainfilename); if(!trainfile){ cerr<<"\ncouldn't open training file"<>tset->base[j][i]; //yes, stuff looks reversed, but this should be OK 1/10/1999 } } /* end of initial file I/O operations */ //remember that tlength=n for now (1/10/1999) for(improvements=1;improvements<=goal_improvements;improvements++){ //printf("\nimp: %d n: %d m: %d s: %f err: %f tlength: %d temp: %f cooldown: %f", improvements, n, m, s, error, tlength, temp, cooldown); Gimprovements=improvements; //train handles lyapunov constraint checking and LE calculation through globals error=train(tset->base, wts->base, n, m, s, error, tlength, temp, cooldown); Gerror=error; Gtemperature=temp; report(); //output stuff to screen if(improvements%run_freq==0){ ok=save(wts->base, n, m, s, netfilename,NULL); if(run_len>0){ /* begin run code */ outfile.open(outfilename); outfile<<"% improvements: "<base[j][0]; //get the first value in each column } for(i=0;ibase, n, m, s); for(j=0;jbase[i][j]=0.5*sin(((2*PI*(j+i))/(float)n)); } } cerr<<"\nwriting to outfile!"<base[i][j]"<base[i][j]<base[i][j])<<" "; } outfile<