This is BackPropEngine.m in view mode; [Download] [Up]
/* =======================================================
Neural Network Classes for the NeXT Computer
Written by: Ralph Zazula
University of Arizona - Fall 1991
zazula@pri.com (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.