com.github.basking2.sdsai.sandbox.ai.nnet.NeuralNet Maven / Gradle / Ivy
Show all versions of sdsai-sandbox Show documentation
/* $Id: NeuralNet.java 670 2008-05-02 20:42:07Z sbaskin $ */
package com.github.basking2.sdsai.sandbox.ai.nnet;
import com.github.basking2.sdsai.sandbox.graph.GraphCopier;
import com.github.basking2.sdsai.sandbox.graph.Node;
public class NeuralNet
{
protected boolean learn;
protected IngressEdge[] input;
protected EgressEdge[] output;
/**
* Version of input or output.
*/
protected int version = 0;
/**
* Speed at which to "learn."
*/
protected double eta = 10;
/**
* A scaler used to alter the range of eta values computed.
*/
protected double scaler = 1;
/**
* This constructor takes a user-constructed neural net. The only
* nodes required are ingress and egress edge arrays. All hidden
* nodes are manipulated by recursivly operating on the egress edges.
* The ingress edges are needed to set the input values.
*/
public NeuralNet(IngressEdge[] i, EgressEdge[] o){
input = i;
output = o;
}
/**
* This constructor automates the process of building a neural net.
* The number of input and outputs is specified. The layerSize is an
* array of layer sizes. An array of size 0 or null may be passed if no
* hidden units are desired. The boolean sc, if true, uses a
* ScaledHiddenNode instead of a HiddenNode for the hidden nodes.
* The difference is that a ScaledHiddenNode has one extra edge for input.
* The extra, scaling, edge can sometimes allow for better versatility in
* training but may also confuse the neural net in some instances.
* This is why the option of choices is given. Note the neural nets with
* scaled hidden nodes tend to have significantly longer training epoches.
* @param innumber the number of inputs.
* @param outnumber the number of classes or outputs.
* @param layerSizes an array of sizes for each hidden layer from the
* inputs to the outputs.
* @param sc if true, ScaledHiddenNodes are used instead of HiddenNodes.
*/
public NeuralNet(int innumber, int outnumber, int[] layerSizes, boolean sc)
{
input = new IngressEdge[innumber];
output = new EgressEdge[outnumber];
if(layerSizes==null)
layerSizes=new int[0];
HiddenNode[] layer1 = new HiddenNode[innumber]; /* set up input */
HiddenNode[] layer2; /* another layer used later*/
/**** CREATE INPUT LAYER ****/
for(int i=0;iinput.length?input.length:in.length-1)-1;i>=0;i--)
input[i].setInput(in[i]);
nextVersion();
}
public void setTargets(double[] t){
for(int i=(t.length>output.length?output.length:t.length)-1;i>=0;i--)
output[i].setTarget(t[i]);
nextVersion();
}
public void set(TrainingInstance instance){
double[] x = instance.getTargets();
for(int i=(x.length>output.length?output.length:x.length)-1;i>=0;i--)
output[i].setTarget(x[i]);
x = instance.getData();
for(int i=(x.length>input.length?input.length:x.length)-1;i>=0;i--)
input[i].setInput(x[i]);
nextVersion();
}
/**
* Train the neural net with the data input instance and the target values.
*/
public void train(TrainingInstance in){
/**
* If the error gradiant is steep, then we want to take small
* steps so we don't RUSH past the minimum.
* If the error gradiant is gradual, then we want to take bigger
* setps to cause significant change in the error.
*/
eta=scaler/sigma();
set(in);
for(int i=0; icurrE){
currE=tmpE;
curr=i;
}
i--;
} while(i>=0);
return curr;
}
/**
* Return the index of the training instance that is
* the nth worst.
*/
public int worst(TrainingSet s, int n){
int i = s.size()-1;
int[] curr = new int[n+1];
double[] currE = new double[n+1];
do {
/* to sort, we need a tmp integer value for indecies. */
int tmpi = i;
/* Get some error value for i */
double tmpE = errorDistance(s.getInstance(tmpi));
/* Insert it in the error array and mark the index */
for(int j=0; j=0);
return curr[0]; /* This SHOULD be the largest error value index */
}
/**
* Find the training instance that does nth worst. That is,
* there are nth instance that perform more baddly
* that the index of the instance returned.
* Note that getWorst(dataSet,1) is equivalent to getWorst(dataSet).
*/
public TrainingInstance getWorst(TrainingSet s, int nth)
{
return s.getInstance(worst(s,nth));
}
/**
* Return the training instance which we think is least well
* performed on.
*/
public TrainingInstance getWorst(TrainingSet s){
return s.getInstance(worst(s));
}
/**
* In an asyncronous environement it may be benificial to
* be able to cause the train() method to stop and exit.
* This will set the field learn equal false which will cause
* train() to gracefully exit on its next iteration.
*/
public void stopTraining(){ learn = false; }
/**
* Traing i times.
*/
public void train(TrainingSet s, int i){
for(;i>0;i--){
try {
train(s);
}
catch(TrainingException e){
train(getWorst(s));
}
}
}
/**
* This is intended to be the generic training method for
* a NeuralNet. It trains the NeuralNet until any further training
* will decrease the accuracy.
* Training is done by calling train(TrainingSet s) repeatedly.
*/
public double trainUp(TrainingSet s)
{
try {
train(s);
}
catch(TrainingException e){}
return accuracy(s);
}
/**
* This method will train the neural net once given the TrainingSet s.
* Starting at the first TrainingInstance this will try to train
* that instance. If there is no loss in accuracy, that training is
* accepted and the method returns the current accuracy.
* If the first TrainingInstance decreases the accuracy, then the next
* instance is tried and so on until either the training set is exhausted
* or an instance is found which does not decrease the accuracy.
* If no TrainingInstance will not decrease accuracy, then a
* TrainingException is thrown.
*/
public double train(TrainingSet s) throws TrainingException {
int nth=0;
double accuracy, prevAccuracy;
prevAccuracy=accuracy(s); /* compute our value to beat */
train(getWorst(s, nth++));
accuracy=accuracy(s);
if(prevAccuracy==1) /* we CAN't do better */
return 1;
/* If we LOSE accuracy, try another instance */
while(prevAccuracy>accuracy && nths.size()){ /* If we did NOT acctually train...*/
undo();
throw new TrainingException();
}
return accuracy;
}
/**
* Train n times or until the accuracy is met.
* If the value of n is exceeded and the training level is not met, then
* a TrainingException is thrown.
* Returns the number of iterations acctually taken to reach the accuracy.
*/
public int train(TrainingSet s, double acc, int n)
throws TrainingException
{
int rounds=0; /* how many rounds of training have we been through */
double accuracy=accuracy(s);
//double previousAccuracy;
learn=true; /* keep learning once we start. */
while(learn && accuracyacc.
* @param s a set of training data.
* @param acc lowerbound for accuracy.
*/
public void train(TrainingSet s, double acc)
{
int rounds=0; /* how many rounds of training have we been through */
double accuracy=accuracy(s);
//double previousAccuracy;
learn=true; /* keep learning once we start. */
while(learn && accuracyALL nodes and edges.
* Some times it is desirable to gate a snap shot of a
* Neural net as further training my worsen performance or
* perhaps two nets would like to be trained on seperate sets of data.
* This method is handy for JUST such a purpose!
*/
public NeuralNet copy(){
IngressEdge[] inedge = new IngressEdge[input.length];
EgressEdge[] outedge = new EgressEdge[output.length];
Node[] inNodes = new Node[input.length];
for(int i=0;i