This is BackPropEngine.m in view mode; [Download] [Up]
/* ======================================================= Neural Network Classes for the NeXT Computer Written by: Ralph Zazula University of Arizona zazula@bonehead.tucson.az.us (NeXT Mail) ==========================================================*/ #import "BackPropEngine.h" double *error; @implementation BackPropEngine - inputs { return inputs; } - hidden { return hidden; } - outputs { return outputs; } - (double)getEta { return ETA; } - setEta:(double)newEta { ETA = newEta; return self;} - (double)getError { return Error; } - init { [super init]; inputs = [[List alloc] init]; hidden = [[List alloc] init]; outputs = [[List alloc] init]; random = [[Random alloc] init]; ETA = 0.9; ALPHA = 0.9; Error = 0.0; return self; } - initWithInputs:(int)Nin hidden:(int)Nhid outputs:(int)Nout { int i,j; [self init]; // // create the nodes // for(i=0; i<Nin; i++) [inputs addObject:[[[Neuron alloc] init] setRandom:random]]; for(i=0; i<Nhid; i++) [hidden addObject:[[[Neuron alloc] init] setRandom:random]]; for(i=0; i<Nout; i++) [outputs addObject:[[[Neuron alloc] init] setRandom:random]]; // // make the connections // for(j=0; j<Nhid; j++) for(i=0; i<Nin; i++) [[hidden objectAt:j] connect:[inputs objectAt:i]]; for(j=0; j<Nout; j++) for(i=0; i<Nhid; i++) [[outputs objectAt:j] connect:[hidden objectAt:i]]; // // allocate other variables // error = (double *)malloc((Nout+1)*sizeof(double)); return self; } - applyInput:(double *)input { int i; for(i=0; i<[inputs count]; i++) [[inputs objectAt:i] setOutput:(double)input[i]]; for(i=0; i<[hidden count]; i++) [[hidden objectAt:i] step]; for(i=0; i<[outputs count]; i++) [[outputs objectAt:i] step]; return self; } - correctWithTarget:(double *)target { int i,j,k; id oNode, hNode, iNode; double O, delta; // // correct the hidden->output weights // and update the error // Error=0.0; for(i=0; i<[outputs count]; i++) { oNode = [outputs objectAt:i]; O = [oNode lastOutput]; error[i] = target[i] - O; Error += error[i]*error[i]/2.0; for(j=0; j<[hidden count]; j++) { hNode = [hidden objectAt:j]; [oNode changeWeightFor:hNode by:error[i]*[hNode lastOutput]*ETA*O*(1-O)]; } } // // correct the input->hidden weights // for(k=0; k<[inputs count]; k++) { iNode = [inputs objectAt:k]; for(j=0; j<[hidden count]; j++) { hNode = [hidden objectAt:j]; delta = 0.0; for(i=0; i<[outputs count]; i++) { oNode = [outputs objectAt:i]; O = [oNode lastOutput]; delta +=O*(1-O)*error[i]*[oNode getWeightFor:hNode]; } [hNode changeWeightFor:iNode by:delta*ETA*[iNode lastOutput]* [hNode lastOutput]*(1-[hNode lastOutput])]; } } return self; } @end
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.