I've had little success, however. Near as I can tell the neural processing is working correctly, but the back propagation isn't. It seems that it always wants the answer to be .5, rather than trying to actually xor the two binary digits. I know it's asking a lot to hope that someone would be willing to go through my neural processor and find what I've fucked up, but I've been beating my head against this particular wall all weekend, and I've reached my wits' end.

**Spoiler:**

Code: Select all

`package trainer;`

import java.io.BufferedWriter;

import java.io.FileOutputStream;

import java.io.IOException;

import java.io.OutputStreamWriter;

import java.util.Random;

public class Trainer

{

public static float fOfX(float x)

{

return (float)(1/(1+Math.exp(x*-1)));

}

public static float fPrimeOfX(float x)

{

return fOfX(x) * (1-fOfX(x));

}

public static float[][] procNode(float[] in, float[][][] net)

{

float sum;

int i;

net[0] = new float[in.length][];

float[][] out = new float[net.length][];

for (i = 1; i < net.length; i++)

{

out[i] = new float[net[i].length];

}

out[0] = new float[in.length];

// assign content to input layer

for(i=0;i<in.length;i++)

out[0][i]=in[i]; // output_from_neuron(i,j) Jth neuron in Ith Layer

// assign output(activation) value

// to each neuron usng sigmoid func

for(i=1;i<net.length;i++)

{ // For each layer

for(int j=0;j<net[i].length;j++)

{ // For each neuron in current layer

sum=0.0f;

for(int k=0;k<net[i-1].length;k++)

{ // For input from each neuron in preceeding layer

sum+= out[i-1][k]*net[i][j][k]; // Apply weight to inputs and add to sum

}

//sum+=net[i][j][net[i-1].length]; // Apply bias

out[i][j]=fOfX(sum); // Apply sigmoid function

}

}

return out;

}

public static float[][][] backProp(float[][] actual, float[] tgt, float[][][] net, float[] input)

{

float sum;

int i;

float[][] delta = new float[net.length][];

float[][] out = new float[net.length][];

float[][][] newNet = new float[net.length][][];

for (i = 0; i < net.length; i++)

{

delta[i] = new float[net[i].length];

out[i] = new float[net[i].length];

if (i > 0)

{

newNet[i] = new float[net[i].length][];

for (int j= 0; j < net[i].length; j++)

{

newNet[i][j] = new float[net[i][j].length];

}

}

}

// find delta for output layer

for(i=0;i<net[net.length-1].length;i++)

{

delta[net.length-1][i]=actual[net.length-1][i]*(1-actual[net.length-1][i])*(tgt[i]-actual[net.length-1][i]);

}

// find delta for hidden layers

for(i=net.length-2;i>0;i--)

{

for(int j=0;j<net[i].length;j++)

{

sum=0.0f;

for(int k=0;k<net[i+1].length;k++)

{

sum+=delta[i+1][k]*net[i+1][k][j];

}

delta[i][j]=actual[i][j]*(1-actual[i][j])*sum;

}

}

float alpha = 0.0f;

// apply momentum ( does nothing if alpha=0 )

for(i=1;i<net.length;i++){

for(int j=0;j<net[i].length;j++){

for(int k=0;k<net[i-1].length;k++){

newNet[i][j][k]+=alpha*net[i][j][k];

}

newNet[i][j][net[i-1].length]+=alpha*net[i][j][net[i-1].length];

}

}

float beta = 1.0f;

// adjust weights usng steepest descent

for(i=1;i<net.length;i++)

{

for(int j=0;j<net[i].length;j++)

{

for(int k=0;k<net[i-1].length;k++)

{

float change=beta*delta[i][j]*actual[i-1][k];

newNet[i][j][k]=net[i][j][k]+change;

}

float change =beta*delta[i][j];

newNet[i][j][net[i-1].length]+=net[i][j][net[i-1].length] + change;

}

}

return newNet;

}

public static float[][][] randomizeInitialNet(int input, int output, int hiddenAmtMin, int hiddenAmtMax, int minHidden, int maxHidden)

{

Random rand = new Random();

int numLayers = rand.nextInt(hiddenAmtMax-hiddenAmtMin) + hiddenAmtMin + 2;

int[] layerNodes = new int[numLayers];

for (int i = 1; i < numLayers-1; i++)

{

layerNodes[i] = rand.nextInt(hiddenAmtMax-hiddenAmtMin)+hiddenAmtMin;

}

layerNodes[0] = input;

layerNodes[numLayers-1] = output;

float[][][] net = new float[numLayers][][];

net[0] = new float[layerNodes[0]][];

for(int i=1;i<numLayers;i++)

{

net[i] = new float[layerNodes[i]][];

for(int j=0;j<layerNodes[i];j++)

{

net[i][j]=new float[layerNodes[i-1]+1];

}

}

for(int i=1;i<numLayers;i++)

{

for(int j=0;j<layerNodes[i];j++)

{

for(int k=0;k<layerNodes[i-1]+1;k++)

{

net[i][j][k]=rand.nextFloat()*2-1;

}

}

}

return net;

}

public static String brainToString(float[][][] output)

{

String out = new String();

for (int i = 0; i < output.length; i++)

{

for (int j = 0; j < output[i].length; j++)

{

for (int k = 0; k < output[i][j].length; k++)

{

out = out + String.valueOf(output[i][j][k]);

if (k < output[i][j].length-1)

{

out = out + ";";

}

}

if (j < output[i].length-1)

{

out = out + ",";

}

}

if (i < output.length-1)

{

out = out + "~";

}

}

return out;

}

public static void main(String[] psvm) throws IOException

{

float[][][] net = randomizeInitialNet(2, 1, 5, 6, 4, 5);

Random rand = new Random();

float[][] inputs = {{0,0}, {1,0}, {0,1}, {1,1}};

float[][] validOuts = {{0}, {1}, {1}, {0}};

for (int i = 0; i < 50000; i++)

{

// float[] nums = {rand.nextFloat()*64.0f, rand.nextFloat()*64.0f};

// float[] exp = {((int)nums[0]^(int)nums[1])/64.0f};

float[][] out = procNode(inputs[i%inputs.length], net);

net = backProp(out, validOuts[i%inputs.length], net, inputs[i%inputs.length]);

//if (i%999 == 0)

System.out.println(i + ": " + validOuts[i%inputs.length][0] + "/" + out[out.length-1][0] +

": " + validOuts[i%inputs.length][0]/out[out.length-1][0]);

}

System.out.println("fail");

}

}