/**
* Title: Neural_2H<p>
* Description: Two hidden layer back propagtion neural network model<p>
* Copyright: Copyright (c) 2000 Mark Watson. Artisitic Open Source License<p>
* @author Mark Watson
* @version 1.2
*/
import java.util.*;
import java.io.*;
public class Neural_2H_momentum implements Serializable {
private static final long serialVersionUID = 5869773395153615662L;
protected int numInputs;
protected int numHidden1;
protected int numHidden2;
protected int numOutputs;
protected int numTraining;
public float inputs[];
protected float hidden1[];
protected float hidden2[];
public float outputs[];
protected float W1[][];
protected float W2[][];
protected float W3[][];
// last delta weights for momentum term:
protected float W1_last_delta[][];
protected float W2_last_delta[][];
protected float W3_last_delta[][];
protected float output_errors[];
protected float hidden1_errors[];
protected float hidden2_errors[];
transient protected ArrayList inputTraining = new ArrayList();
transient protected ArrayList outputTraining = new ArrayList();
public float TRAINING_RATE = 0.5f;
private float alpha = 0f; // momentum scaling term that is applied to last delta weight
Neural_2H_momentum(int num_in, int num_hidden1, int num_hidden2, int num_output,
float alpha) {
this.alpha = alpha;
numInputs = num_in;
numHidden1 = num_hidden1;
numHidden2 = num_hidden2;
numOutputs = num_output;
inputs = new float[numInputs];
hidden1 = new float[numHidden1];
hidden2 = new float[numHidden2];
outputs = new float[numOutputs];
W1 = new float[numInputs][numHidden1];
W2 = new float[numHidden1][numHidden2];
W3 = new float[numHidden2][numOutputs];
W1_last_delta = new float[numInputs][numHidden1];
W2_last_delta = new float[numHidden1][numHidden2];
W3_last_delta = new float[numHidden2][numOutputs];
randomizeWeights();
output_errors = new float[numOutputs];
hidden1_errors = new float[numHidden1];
hidden2_errors = new float[numHidden2];
}
public void addTrainingExample(float[] inputs, float[] outputs) {
if (inputs.length != numInputs || outputs.length != numOutputs) {
System.out.println("addTrainingExample(): array size is wrong");
return;
}
inputTraining.add(inputs);
outputTraining.add(outputs);
}
public static Neural_2H_momentum Factory(String serialized_file_name) {
Neural_2H_momentum nn = null;
try {
InputStream ins = ClassLoader.getSystemResourceAsStream(serialized_file_name);
if (ins == null) {
System.out.println("CachedExamples(): failed to open 'cache.dat' in JAR file");
System.exit(1);
} else {
ObjectInputStream p = new ObjectInputStream(ins);
nn = (Neural_2H_momentum) p.readObject();
nn.inputTraining = new ArrayList();
nn.outputTraining = new ArrayList();
ins.close();
}
} catch (Exception e) {
e.printStackTrace();
return null;
}
return nn;
}
public void save(String file_name) {
try {
FileOutputStream ostream = new FileOutputStream(file_name);
ObjectOutputStream p = new ObjectOutputStream(ostream);
p.writeObject(this);
p.flush();
ostream.close();
} catch (Exception e) {
e.printStackTrace();
}
}
public void randomizeWeights() {
// Randomize weights here:
for (int ii = 0; ii < numInputs; ii++)
for (int hh = 0; hh < numHidden1; hh++)
W1[ii][hh] =
2f * (float) Math.random() - 1f;
for (int ii = 0; ii < numHidden1; ii++)
for (int hh = 0; hh < numHidden2; hh++)
W2[ii][hh] =
2f * (float) Math.random() - 1f;
for (int hh = 0; hh < numHidden2; hh++)
for (int oo = 0; oo < numOutputs; oo++)
W3[hh][oo] =
2f * (float) Math.random() - 1f;
}
public void slightlyRandomizeWeights() {
// Randomize weights here:
for (int ii = 0; ii < numInputs; ii++)
for (int hh = 0; hh < numHidden1; hh++)
W1[ii][hh] +=
0.2f * (float) Math.random() - 0.1f;
for (int ii = 0; ii < numHidden1; ii++)
for (int hh = 0; hh < numHidden2; hh++)
W2[ii][hh] +=
0.2f * (float) Math.random() - 0.1f;
for (int hh = 0; hh < numHidden2; hh++)
for (int oo = 0; oo < numOutputs; oo++)
W3[hh][oo] +=
0.2f * (float) Math.random() - 0.1f;
}
public float[] recall(float[] in) {
for (int i = 0; i < numInputs; i++) inputs[i] = in[i];
forwardPass();
float[] ret = new float[numOutputs];
for (int i = 0; i < numOutputs; i++) ret[i] = outputs[i];
return ret;
}
public void forwardPass() {
int i, h, o;
for (h = 0; h < numHidden1; h++) {
hidden1[h] = 0.0f;
}
for (h = 0; h < numHidden2; h++) {
hidden2[h] = 0.0f;
}
for (i = 0; i < numInputs; i++) {
for (h = 0; h < numHidden1; h++) {
hidden1[h] +=
inputs[i] * W1[i][h];
}
}
for (i = 0; i < numHidden1; i++) {
for (h = 0; h < numHidden2; h++) {
hidden2[h] +=
hidden1[i] * W2[i][h];
}
}
for (o = 0; o < numOutputs; o++)
outputs[o] = 0.0f;
for (h = 0; h < numHidden2; h++) {
for (o = 0; o < numOutputs; o++) {
outputs[o] +=
sigmoid(hidden2[h]) * W3[h][o];
}
}
}
public float train() {
return train(inputTraining, outputTraining);
}
private int current_example = 0;
public float train(ArrayList ins, ArrayList v_outs) {
int i, h, o;
float error = 0.0f;
int num_cases = ins.size();
//for (int example=0; example<num_cases; example++) {
// zero out error arrays:
for (h = 0; h < numHidden1; h++)
hidden1_errors[h] = 0.0f;
for (h = 0; h < numHidden2; h++)
hidden2_errors[h] = 0.0f;
for (o = 0; o < numOutputs; o++)
output_errors[o] = 0.0f;
// copy the input values:
for (i = 0; i < numInputs; i++) {
inputs[i] = ((float[]) ins.get(current_example))[i];
}
// copy the output values:
float[] outs = (float[]) v_outs.get(current_example);
// perform a forward pass through the network:
forwardPass();
for (o = 0; o < numOutputs; o++) {
output_errors[o] =
(outs[o] -
outputs[o])
* sigmoidP(outputs[o]);
}
for (h = 0; h < numHidden2; h++) {
hidden2_errors[h] = 0.0f;
for (o = 0; o < numOutputs; o++) {
hidden2_errors[h] +=
output_errors[o] * W3[h][o];
}
}
for (h = 0; h < numHidden1; h++) {
hidden1_errors[h] = 0.0f;
for (o = 0; o < numHidden2; o++) {
hidden1_errors[h] +=
hidden2_errors[o] * W2[h][o];
}
}
for (h = 0; h < numHidden2; h++) {
hidden2_errors[h] =
hidden2_errors[h] * sigmoidP(hidden2[h]);
}
for (h = 0; h < numHidden1; h++) {
hidden1_errors[h]