www.pudn.com > NeuralNetworkSourceCode.zip > ART.CPP, change:2001-02-17,size:9850b
/**************************************************************************** * * * ADAPTIVE RESONANCE THEORY (ART) NETWORK * * * *****************************************************************************/ #include <stdio.h> #include <stdlib.h> #include <string.h> #include <conio.h> #include <math.h> // DEFINES #define MAXCNEURONS 75 // MAX COMPARISON LAYER NEURONS #define MAXRNEURONS 30 // MAX RECOGNITION LAYER NEURONS #define MAXPATTERNS 30 // MAX NUMBER OF PATTERNS IN A TRAINING SET #define VERBOSE 1 class ARTNET { private: double Wb[MAXCNEURONS][MAXRNEURONS]; // Bottom up weight matrix int Wt[MAXRNEURONS][MAXCNEURONS]; // Top down weight matrix int InData[MAXPATTERNS][MAXCNEURONS];// Array of input vectors to be // presented to the network int NumPatterns; // Number of input patterns double VigilThresh; // Vigilence threshold value double L; // ART training const (see text) int M; // # of neurons in C-layer int N; // # of neurons in R-layer int XVect[MAXCNEURONS]; // Current in vect at C-layer. int CVect[MAXCNEURONS]; // Output vector from C-layer int BestNeuron; // Current best R-layer Neuron int Reset; // Active when vigilence has // disabled someone int RVect[MAXCNEURONS]; // Output vector from R-layer int PVect[MAXCNEURONS]; // WeightedOutput vector from R-layer int Disabled[MAXRNEURONS]; // Resets way of disqualifying neurons int Trained[MAXRNEURONS]; // To identify allocated R-Neurons void ClearPvect(); void ClearDisabled(); void RecoPhase(); // Recognition phase void CompPhase(); // Comparison phase void SearchPhase(); // Search Phase void RunCompLayer(); // Calc comparison layer by 2/3 rule void RunRecoLayer(); // Calc recognition layers R-vect void Rvect2Pvect(int); // Distribute winners result int Gain1(); // Comp layer gain int Gain2(); // Reco layer gain double Vigilence(); // Calc vigilence metric void InitWeights(); // Initialize weights void Train(); // Weight adjustment is done here public: ARTNET(void); // Constructor/initializations int LoadInVects(char *Fname); // load all data vectors void Run(int i); // Run net w/ ith pattern void ShowWeights(); // display top down and // bottom up weights void ShowInVect(); // Display current input pattern void ShowOutVect(); // P-vector from Reco layer(see text) }; // ------------------------------------------------------------------------ // METHOD DEFINITIONS ARTNET::ARTNET(){ int i; L=2.0; N=MAXRNEURONS; for (i=0; i<N; i++) { //Set all neurons to untrained and enabled Trained[i]=0; Disabled[i]=0; } /* endfor */ } int ARTNET::LoadInVects(char *Fname){ FILE *PFILE; int i,j,k; PFILE = fopen(Fname,"r"); if (PFILE==NULL){ printf("\nUnable to open file %s\n",Fname); exit(0); } fscanf(PFILE,"%d",&NumPatterns); //How many patterns fscanf(PFILE,"%d",&M); //get width of input vector fscanf(PFILE,"%lf",&VigilThresh); for (i=0; i<NumPatterns; i++) { for (j=0; j<M; j++) { fscanf(PFILE,"%d",&k); //Read all the pattern data and... InData[i][j]=k; // ...save it for later. } /* endfor */ } /* endfor */ InitWeights(); return NumPatterns; } int ARTNET::Gain2(){ int i; for (i=0; i<M; i++) { if (XVect[i]==1) return 1; } /* endfor */ } void ARTNET::Rvect2Pvect(int best){ int i; for (i=0; i<M; i++) { PVect[i]= Wt[best][i]; } /* endfor */ } int ARTNET::Gain1(){ int i,G; G=Gain2(); for (i=0; i<M; i++) { if (RVect[i]==1) return 0; } /* endfor */ return G; } void ARTNET::RunCompLayer(){ int i,x; for (i=0; i<M; i++) { x=XVect[i]+Gain1()+PVect[i]; if (x>=2) { CVect[i]=1; } else { CVect[i]=0; } /* endif */ } /* endfor */ } double ARTNET::Vigilence(){ int i; double S,K,D; // count # of 1's in p-vect & x-vect K=0.0; D=0.0; for (i=0; i<M; i++) { K+=CVect[i]; D+=XVect[i]; } /* endfor */ S=K/D; return S; } void ARTNET::RunRecoLayer(){ int i,j,k; double Net[MAXRNEURONS]; int BestNeruon=-1; double NetMax=-1; for (i=0; i<N; i++) { //Traverse all R-layer Neurons Net[i]=0; for (j=0; j<M; j++) { // Do the product Net[i] +=Wb[i][j]*CVect[j]; } /* endfor */ if ((Net[i]>NetMax) && (Disabled[i]==0)) { //disabled neurons cant win! BestNeuron=i; NetMax=Net[i]; } } /* endfor */ for (k=0; k<N; k++) { if (k==BestNeuron) RVect[k]=1; // Winner gets 1 else RVect[k]=0; // lateral inhibition kills the rest } /* endfor */ } void ARTNET::RecoPhase(){ int i; //First force all R-layer outputs to zero for (i=0; i<N; i++) { RVect[i]=0; } /* endfor */ for (i=0; i<M; i++) { PVect[i]=0; } /* endfor */ //Now Calculate C-layer outputs RunCompLayer(); //C-vector now has the result RunRecoLayer(); //Calc dot prod w/ bot up weight & C Rvect2Pvect(BestNeuron); } void ARTNET::CompPhase(){ double S; RunCompLayer(); //Cvector<-dif between x & p S=Vigilence(); if (S<VigilThresh){ Reset=1; RVect[BestNeuron]=0; Disabled[BestNeuron]=1; } else Reset=0; } void ARTNET::SearchPhase(){ double S; while (Reset) { ClearPvect(); RunCompLayer(); //Xvect -> Cvect RunRecoLayer(); //Find a new winner with prev winners disabled Rvect2Pvect(BestNeuron); //new pvect based on new winner S=Vigilence(); //calc vigilence for the new guy if (S<VigilThresh){ //check if he did ok Reset=1; // if not disable him too RVect[BestNeuron]=0; Disabled[BestNeuron]=1; } else Reset=0; //Current Best neuron is a good winner...Train him } /* endwhile */ if (BestNeuron!=-1) { Train(); } else { //Failed to allocate a neuron for current pattern. printf("Out of neurons in F2\n"); } /* endif */ ClearDisabled(); } void ARTNET::ClearDisabled() { int i; for (i=0; i<M; i++) { Disabled[i]=0; } /* endfor */ } void ARTNET::ClearPvect() { int i; for (i=0; i<M; i++) { PVect[i]=0; } /* endfor */ } void ARTNET::Train(){ int i,z=0; for (i=0; i<M; i++) { z+=CVect[i]; } /* endfor */ for (i=0; i<M; i++) { Wb[BestNeuron][i]=L*CVect[i]/(L-1+z); Wt[BestNeuron][i]=CVect[i]; } /* endfor */ Trained[BestNeuron]=1; } void ARTNET::Run(int tp){ int i,j; ClearPvect(); for (i=0; i<M; i++) { XVect[i]=InData[tp][i]; } /* endfor */ RecoPhase(); CompPhase(); SearchPhase(); } void ARTNET::InitWeights(){ // Initialize weights int i,j; double b; for (i=0; i<N; i++) { // from R-neuron i for (j=0; j<M; j++) { // to C-neuron j Wt[i][j]= 1; // All init'd to 1 } /* endfor */ } /* endfor */ b=L/(L-1+M); for (i=0; i<N; i++) { // from C-neuron i for (j=0; j<M; j++) { // to R-neuron j Wb[i][j]= b; } /* endfor */ } /* endfor */ } void ARTNET::ShowWeights(){ int i,j; printf("\nTop Down weights:\n"); for (i=0; i<N; i++) { if(Trained[i]==1){ for (j=0; j<M; j++) { printf("%d ",Wt[i][j]); } /* endfor */ printf("\n"); } /* endif */ } /* endfor */ printf("\nBottom up weights:\n"); for (i=0; i<N; i++) { if(Trained[i]==1){ for (j=0; j<M; j++) { printf("%f ",Wb[i][j]); } /* endfor */ printf("\n"); } /* endif */ } /* endfor */ } void ARTNET::ShowInVect(){ int i; printf("BEST NEURON:%d\nIN: ",BestNeuron); for (i=0; i<M; i++) { printf("%d ",XVect[i]); } /* endfor */ printf("\n"); } void ARTNET::ShowOutVect(){ int i; printf("OUT: "); for (i=0; i<M; i++) { printf("%d ",CVect[i]); } /* endfor */ printf("\n"); } // ------------------------------------------------------------------------ ARTNET ART; /****************************************************************************** * MAIN * ******************************************************************************/ int main(int argc, char *argv[]) { int TstSetSize; int i; if (argc>1) { TstSetSize=ART.LoadInVects(argv[1]); for (i=0; i<TstSetSize; i++) { ART.Run(i); //Evaluate ith test pattern printf("\n"); ART.ShowInVect(); ART.ShowOutVect(); if (VERBOSE==1) ART.ShowWeights(); } /* endfor */ } else { printf("USAGE: ART PATTERN_FILE_NAME\n"); exit(0); } return 0; }