diff --git a/src/test/java/com/syncleus/grail/neural/backprop/ActionTriggerXor3InputTest.java b/src/test/java/com/syncleus/grail/neural/backprop/ActionTriggerXor3InputTest.java index 44fa804b1f3a87a5cf73ee58d234ce6c0fc3d67c..73120c1d3909b1d1c4a2dfb483f5d3dff6fa3c96 100644 --- a/src/test/java/com/syncleus/grail/neural/backprop/ActionTriggerXor3InputTest.java +++ b/src/test/java/com/syncleus/grail/neural/backprop/ActionTriggerXor3InputTest.java @@ -10,6 +10,8 @@ import java.lang.reflect.UndeclaredThrowableException; import java.util.*; public class ActionTriggerXor3InputTest { + private static final ActivationFunction ACTIVATION_FUNCTION = new SineActivationFunction(); + @Test public void testXor() { final FramedTransactionalGraph<?> graph = BlankGraphFactory.makeTinkerGraph(); @@ -27,6 +29,8 @@ public class ActionTriggerXor3InputTest { newHiddenNeurons.add(ActionTriggerXor3InputTest.createNeuron(graph, "hidden")); newHiddenNeurons.add(ActionTriggerXor3InputTest.createNeuron(graph, "hidden")); final BackpropNeuron newOutputNeuron = ActionTriggerXor3InputTest.createNeuron(graph, "output"); + final BackpropNeuron biasNeuron = ActionTriggerXor3InputTest.createNeuron(graph, "bias"); + biasNeuron.setSignal(1.0); //connect all input neurons to hidden neurons for( final BackpropNeuron inputNeuron : newInputNeurons ) { @@ -39,13 +43,9 @@ public class ActionTriggerXor3InputTest { graph.addEdge(null, hiddenNeuron.asVertex(), newOutputNeuron.asVertex(), "signals", BackpropSynapse.class); //create bias neuron - final BackpropNeuron biasNeuron = ActionTriggerXor3InputTest.createNeuron(graph, "bias"); - biasNeuron.setSignal(1.0); graph.addEdge(null, biasNeuron.asVertex(), hiddenNeuron.asVertex(), "signals", BackpropSynapse.class); } //create bias neuron for output neuron - final BackpropNeuron biasNeuron = ActionTriggerXor3InputTest.createNeuron(graph, "bias"); - biasNeuron.setSignal(1.0); graph.addEdge(null, biasNeuron.asVertex(), newOutputNeuron.asVertex(), "signals", BackpropSynapse.class); // @@ -82,6 +82,10 @@ public class ActionTriggerXor3InputTest { newEdge.setTriggerPriority(0); newEdge.setTriggerAction("backpropagate"); } + //also connect it to all the bias neurons + final PrioritySerialTriggerEdge biasTriggerBackpropEdge = graph.addEdge(null, backpropInputTrigger.asVertex(), biasNeuron.asVertex(), "triggers", PrioritySerialTriggerEdge.class); + biasTriggerBackpropEdge.setTriggerPriority(0); + biasTriggerBackpropEdge.setTriggerAction("backpropagate"); //create backpropagation trigger for the hidden layer final PrioritySerialTrigger backpropHiddenTrigger = ActionTriggerXor3InputTest.createPrioritySerialTrigger(graph); @@ -93,7 +97,7 @@ public class ActionTriggerXor3InputTest { newEdge.setTriggerAction("backpropagate"); } - //finally chain the hidden layers back propagation to the input layers trigger + //chain the hidden layers back propagation to the input layers trigger final PrioritySerialTriggerEdge chainTriggerBackpropEdge = graph.addEdge(null, backpropHiddenTrigger.asVertex(), backpropInputTrigger.asVertex(), "triggers", PrioritySerialTriggerEdge.class); chainTriggerBackpropEdge.setTriggerPriority(1000); chainTriggerBackpropEdge.setTriggerAction("actionTrigger"); @@ -105,7 +109,7 @@ public class ActionTriggerXor3InputTest { // Graph is constructed, just need to train and test our network now. // - for(int i = 0; i < 1000; i++) { + for(int i = 0; i < 10000; i++) { ActionTriggerXor3InputTest.train(graph, 1.0, 1.0, 1.0, -1.0); ActionTriggerXor3InputTest.train(graph, -1.0, 1.0, 1.0, -1.0); ActionTriggerXor3InputTest.train(graph, 1.0, -1.0, 1.0, -1.0); @@ -114,6 +118,8 @@ public class ActionTriggerXor3InputTest { ActionTriggerXor3InputTest.train(graph, -1.0, 1.0, -1.0, 1.0); ActionTriggerXor3InputTest.train(graph, 1.0, -1.0, -1.0, 1.0); ActionTriggerXor3InputTest.train(graph, -1.0, -1.0, -1.0, -1.0); + if( i%50 == 0 && ActionTriggerXor3InputTest.calculateError(graph) < 0.1 ) + break; } Assert.assertTrue(ActionTriggerXor3InputTest.propagate(graph, 1.0, 1.0, 1.0) < 0.0); Assert.assertTrue(ActionTriggerXor3InputTest.propagate(graph, -1.0, 1.0, 1.0) < 0.0); @@ -125,7 +131,33 @@ public class ActionTriggerXor3InputTest { Assert.assertTrue(ActionTriggerXor3InputTest.propagate(graph, -1.0, -1.0, -1.0) < 0.0); } - private static final ActivationFunction activationFunction = new SineActivationFunction(); + private static double calculateError(FramedTransactionalGraph<?> graph) { + double actual = ActionTriggerXor3InputTest.propagate(graph, 1.0, 1.0, 1.0); + double error = Math.abs(actual + 1.0) / Math.abs(actual); + + actual = ActionTriggerXor3InputTest.propagate(graph, -1.0, 1.0, 1.0); + error += Math.abs(actual + 1.0) / 2.0; + + actual = ActionTriggerXor3InputTest.propagate(graph, 1.0, -1.0, 1.0); + error += Math.abs(actual + 1.0) / 2.0; + + actual = ActionTriggerXor3InputTest.propagate(graph, 1.0, 1.0, -1.0); + error += Math.abs(actual + 1.0) / 2.0; + + actual = ActionTriggerXor3InputTest.propagate(graph, 1.0, -1.0, -1.0); + error += Math.abs(actual - 1.0) / 2.0; + + actual = ActionTriggerXor3InputTest.propagate(graph, -1.0, 1.0, -1.0); + error += Math.abs(actual - 1.0) / 2.0; + + actual = ActionTriggerXor3InputTest.propagate(graph, -1.0, -1.0, 1.0); + error += Math.abs(actual - 1.0) / 2.0; + + actual = ActionTriggerXor3InputTest.propagate(graph, -1.0, -1.0, -1.0); + error += Math.abs(actual + 1.0) / 2.0; + + return error / 8.0; + } private static void train(final FramedTransactionalGraph<?> graph, final double input1, final double input2, final double input3, final double expected) { ActionTriggerXor3InputTest.propagate(graph, input1, input2, input3); @@ -133,7 +165,7 @@ public class ActionTriggerXor3InputTest { final Iterator<BackpropNeuron> outputNeurons = graph.getVertices("layer", "output", BackpropNeuron.class).iterator(); final BackpropNeuron outputNeuron = outputNeurons.next(); Assert.assertTrue(!outputNeurons.hasNext()); - outputNeuron.setDeltaTrain((expected - outputNeuron.getSignal()) * activationFunction.activateDerivative(outputNeuron.getActivity()) ); + outputNeuron.setDeltaTrain((expected - outputNeuron.getSignal()) * ACTIVATION_FUNCTION.activateDerivative(outputNeuron.getActivity())); graph.commit(); final Iterator<PrioritySerialTrigger> backpropTriggers = graph.getVertices("triggerPointer", "backpropagate", PrioritySerialTrigger.class).iterator(); diff --git a/src/test/java/com/syncleus/grail/neural/backprop/SimpleOrTest.java b/src/test/java/com/syncleus/grail/neural/backprop/SimpleOrTest.java index b0144243b1b93c1d372edea4fc0a34ee96d65135..79cc09a4c205017375321ef2782f6c2c2595ceea 100644 --- a/src/test/java/com/syncleus/grail/neural/backprop/SimpleOrTest.java +++ b/src/test/java/com/syncleus/grail/neural/backprop/SimpleOrTest.java @@ -7,7 +7,10 @@ import org.junit.*; import java.util.*; public class SimpleOrTest { - @Test + + private static final ActivationFunction ACTIVATION_FUNCTION = new SineActivationFunction(); + + @Test public void testOr() { final FramedTransactionalGraph<?> graph = BlankGraphFactory.makeTinkerGraph(); @@ -26,11 +29,13 @@ public class SimpleOrTest { graph.addEdge(null, biasNeuron.asVertex(), newOutputNeuron.asVertex(), "signals", BackpropSynapse.class);//.asEdge().setProperty("type", "BackpropSynapse"); graph.commit(); - for(int i = 0; i < 1000; i++) { + for(int i = 0; i < 10000; i++) { SimpleOrTest.train(graph, -1.0, 1.0, 1.0); SimpleOrTest.train(graph, 1.0, -1.0, 1.0); SimpleOrTest.train(graph, 1.0, 1.0, 1.0); SimpleOrTest.train(graph, -1.0, -1.0, -1.0); + if( i%50 == 0 && SimpleOrTest.calculateError(graph) < 0.2 ) + break; } Assert.assertTrue("expected >0.0, got: " + SimpleOrTest.propagate(graph, 1.0, 1.0), SimpleOrTest.propagate(graph, 1.0, 1.0) > 0.0); @@ -39,7 +44,21 @@ public class SimpleOrTest { Assert.assertTrue("expected >0.0, got: " + SimpleOrTest.propagate(graph, -1.0, 1.0), SimpleOrTest.propagate(graph, -1.0, 1.0) > 0.0); } - private static final ActivationFunction activationFunction = new SineActivationFunction(); + private static double calculateError(FramedTransactionalGraph<?> graph) { + double actual = SimpleOrTest.propagate(graph, 1.0, 1.0); + double error = Math.abs(actual - 1.0) / 2.0; + + actual = SimpleOrTest.propagate(graph, -1.0, -1.0); + error += Math.abs(actual + 1.0) / 2.0; + + actual = SimpleOrTest.propagate(graph, 1.0, -1.0); + error += Math.abs(actual - 1.0) / 2.0; + + actual = SimpleOrTest.propagate(graph, -1.0, 1.0); + error += Math.abs(actual - 1.0) / 2.0; + + return error/4.0; + } private static void train(final FramedTransactionalGraph<?> graph, final double input1, final double input2, final double expected) { SimpleOrTest.propagate(graph, input1, input2); @@ -47,7 +66,7 @@ public class SimpleOrTest { final Iterator<BackpropNeuron> outputNeurons = graph.getVertices("layer", "output", BackpropNeuron.class).iterator(); final BackpropNeuron outputNeuron = outputNeurons.next(); Assert.assertTrue(!outputNeurons.hasNext()); - outputNeuron.setDeltaTrain((expected - outputNeuron.getSignal()) * activationFunction.activateDerivative(outputNeuron.getActivity()) ); + outputNeuron.setDeltaTrain((expected - outputNeuron.getSignal()) * ACTIVATION_FUNCTION.activateDerivative(outputNeuron.getActivity())); graph.commit(); final Iterator<BackpropNeuron> inputNeurons = graph.getVertices("layer", "input", BackpropNeuron.class).iterator(); diff --git a/src/test/java/com/syncleus/grail/neural/backprop/SimpleXor2InputTest.java b/src/test/java/com/syncleus/grail/neural/backprop/SimpleXor2InputTest.java index d4a7f1af5c7a7a4ce45d4574a5813c3a8fdd7db1..08bd7d3f8618a1c12f3d6a47bc7c37c556eef7c2 100644 --- a/src/test/java/com/syncleus/grail/neural/backprop/SimpleXor2InputTest.java +++ b/src/test/java/com/syncleus/grail/neural/backprop/SimpleXor2InputTest.java @@ -7,6 +7,8 @@ import org.junit.*; import java.util.*; public class SimpleXor2InputTest { + private static final ActivationFunction ACTIVATION_FUNCTION = new HyperbolicTangentActivationFunction(); + @Test public void testXor() { final FramedTransactionalGraph<?> graph = BlankGraphFactory.makeTinkerGraph(); @@ -22,6 +24,10 @@ public class SimpleXor2InputTest { final BackpropNeuron newOutputNeuron = SimpleXor2InputTest.createNeuron(graph, "output"); newOutputNeuron.setActivationFunctionClass(HyperbolicTangentActivationFunction.class); newOutputNeuron.setLearningRate(0.09); + final BackpropNeuron biasNeuron = SimpleXor2InputTest.createNeuron(graph, "bias"); + biasNeuron.setSignal(1.0); + biasNeuron.setActivationFunctionClass(HyperbolicTangentActivationFunction.class); + biasNeuron.setLearningRate(0.09); //connect all input neurons to hidden neurons for( BackpropNeuron inputNeuron : newInputNeurons ) { @@ -41,25 +47,19 @@ public class SimpleXor2InputTest { hiddenNeuron.setLearningRate(0.09); //create bias neuron - final BackpropNeuron biasNeuron = SimpleXor2InputTest.createNeuron(graph, "bias"); - biasNeuron.setSignal(1.0); - biasNeuron.setActivationFunctionClass(HyperbolicTangentActivationFunction.class); - biasNeuron.setLearningRate(0.09); graph.addEdge(null, biasNeuron.asVertex(), hiddenNeuron.asVertex(), "signals", BackpropSynapse.class); } //create bias neuron for output neuron - final BackpropNeuron biasNeuron = SimpleXor2InputTest.createNeuron(graph, "bias"); - biasNeuron.setSignal(1.0); - biasNeuron.setLearningRate(0.09); - biasNeuron.setActivationFunctionClass(HyperbolicTangentActivationFunction.class); graph.addEdge(null, biasNeuron.asVertex(), newOutputNeuron.asVertex(), "signals", BackpropSynapse.class); graph.commit(); - for(int i = 0; i < 1000; i++) { + for(int i = 0; i < 10000; i++) { SimpleXor2InputTest.train(graph, -1.0, 1.0, 1.0); SimpleXor2InputTest.train(graph, 1.0, -1.0, 1.0); SimpleXor2InputTest.train(graph, 1.0, 1.0, -1.0); SimpleXor2InputTest.train(graph, -1.0, -1.0, -1.0); + if( i%50 == 0 && SimpleXor2InputTest.calculateError(graph) < 0.1 ) + break; } Assert.assertTrue(SimpleXor2InputTest.propagate(graph, 1.0, 1.0) < 0.0); Assert.assertTrue(SimpleXor2InputTest.propagate(graph, -1.0, -1.0) < 0.0); @@ -67,7 +67,21 @@ public class SimpleXor2InputTest { Assert.assertTrue(SimpleXor2InputTest.propagate(graph, -1.0, 1.0) > 0.0); } - private static final ActivationFunction activationFunction = new SineActivationFunction(); + private static double calculateError(FramedTransactionalGraph<?> graph) { + double actual = SimpleXor2InputTest.propagate(graph, 1.0, 1.0); + double error = Math.abs(actual + 1.0) / 2.0; + + actual = SimpleXor2InputTest.propagate(graph, -1.0, -1.0); + error += Math.abs(actual + 1.0) / 2.0; + + actual = SimpleXor2InputTest.propagate(graph, 1.0, -1.0); + error += Math.abs(actual - 1.0) / 2.0; + + actual = SimpleXor2InputTest.propagate(graph, -1.0, 1.0); + error += Math.abs(actual - 1.0) / 2.0; + + return error/4.0; + } private static void train(final FramedTransactionalGraph<?> graph, final double input1, final double input2, final double expected) { SimpleXor2InputTest.propagate(graph, input1, input2); @@ -75,7 +89,7 @@ public class SimpleXor2InputTest { final Iterator<BackpropNeuron> outputNeurons = graph.getVertices("layer", "output", BackpropNeuron.class).iterator(); final BackpropNeuron outputNeuron = outputNeurons.next(); Assert.assertTrue(!outputNeurons.hasNext()); - outputNeuron.setDeltaTrain((expected - outputNeuron.getSignal()) * activationFunction.activateDerivative(outputNeuron.getActivity()) ); + outputNeuron.setDeltaTrain((expected - outputNeuron.getSignal()) * ACTIVATION_FUNCTION.activateDerivative(outputNeuron.getActivity())); graph.commit(); final Iterator<BackpropNeuron> hiddenNeurons = graph.getVertices("layer", "hidden", BackpropNeuron.class).iterator(); @@ -94,10 +108,6 @@ public class SimpleXor2InputTest { final Iterator<BackpropNeuron> biasNeurons = graph.getVertices("layer", "bias", BackpropNeuron.class).iterator(); biasNeurons.next().backpropagate(); - biasNeurons.next().backpropagate(); - biasNeurons.next().backpropagate(); - biasNeurons.next().backpropagate(); - biasNeurons.next().backpropagate(); Assert.assertTrue(!biasNeurons.hasNext()); graph.commit(); } diff --git a/src/test/java/com/syncleus/grail/neural/backprop/SimpleXor3InputTest.java b/src/test/java/com/syncleus/grail/neural/backprop/SimpleXor3InputTest.java index df052b0b7285ef3c409a4e633d3559b2f2248b57..9e48852dc9bbb252703a1c76c3cf1d1e87af3ca5 100644 --- a/src/test/java/com/syncleus/grail/neural/backprop/SimpleXor3InputTest.java +++ b/src/test/java/com/syncleus/grail/neural/backprop/SimpleXor3InputTest.java @@ -8,6 +8,8 @@ import org.junit.*; import java.util.*; public class SimpleXor3InputTest { + private static final ActivationFunction activationFunction = new SineActivationFunction(); + @Test public void testXor() { final FramedTransactionalGraph<?> graph = BlankGraphFactory.makeTinkerGraph(); @@ -21,6 +23,8 @@ public class SimpleXor3InputTest { newHiddenNeurons.add(SimpleXor3InputTest.createNeuron(graph, "hidden")); newHiddenNeurons.add(SimpleXor3InputTest.createNeuron(graph, "hidden")); final BackpropNeuron newOutputNeuron = SimpleXor3InputTest.createNeuron(graph, "output"); + final BackpropNeuron biasNeuron = SimpleXor3InputTest.createNeuron(graph, "bias"); + biasNeuron.setSignal(1.0); //connect all input neurons to hidden neurons for( BackpropNeuron inputNeuron : newInputNeurons ) { @@ -32,18 +36,14 @@ public class SimpleXor3InputTest { for( BackpropNeuron hiddenNeuron : newHiddenNeurons ) { graph.addEdge(null, hiddenNeuron.asVertex(), newOutputNeuron.asVertex(), "signals", BackpropSynapse.class); - //create bias neuron - final BackpropNeuron biasNeuron = SimpleXor3InputTest.createNeuron(graph, "bias"); - biasNeuron.setSignal(1.0); + //create bias connection graph.addEdge(null, biasNeuron.asVertex(), hiddenNeuron.asVertex(), "signals", BackpropSynapse.class); } //create bias neuron for output neuron - final BackpropNeuron biasNeuron = SimpleXor3InputTest.createNeuron(graph, "bias"); - biasNeuron.setSignal(1.0); graph.addEdge(null, biasNeuron.asVertex(), newOutputNeuron.asVertex(), "signals", BackpropSynapse.class); graph.commit(); - for(int i = 0; i < 1000; i++) { + for(int i = 0; i < 10000 ; i++) { SimpleXor3InputTest.train(graph, 1.0, 1.0, 1.0, -1.0); SimpleXor3InputTest.train(graph, -1.0, 1.0, 1.0, -1.0); SimpleXor3InputTest.train(graph, 1.0, -1.0, 1.0, -1.0); @@ -52,6 +52,8 @@ public class SimpleXor3InputTest { SimpleXor3InputTest.train(graph, -1.0, 1.0, -1.0, 1.0); SimpleXor3InputTest.train(graph, 1.0, -1.0, -1.0, 1.0); SimpleXor3InputTest.train(graph, -1.0, -1.0, -1.0, -1.0); + if( i%50 == 0 && SimpleXor3InputTest.calculateError(graph) < 0.1 ) + break; } Assert.assertTrue(SimpleXor3InputTest.propagate(graph, 1.0, 1.0, 1.0) < 0.0); Assert.assertTrue(SimpleXor3InputTest.propagate(graph, -1.0, 1.0, 1.0) < 0.0); @@ -63,7 +65,33 @@ public class SimpleXor3InputTest { Assert.assertTrue(SimpleXor3InputTest.propagate(graph, -1.0, -1.0, -1.0) < 0.0); } - private static final ActivationFunction activationFunction = new SineActivationFunction(); + private static double calculateError(FramedTransactionalGraph<?> graph) { + double actual = SimpleXor3InputTest.propagate(graph, 1.0, 1.0, 1.0); + double error = Math.abs(actual + 1.0) / Math.abs(actual); + + actual = SimpleXor3InputTest.propagate(graph, -1.0, 1.0, 1.0); + error += Math.abs(actual + 1.0) / 2.0; + + actual = SimpleXor3InputTest.propagate(graph, 1.0, -1.0, 1.0); + error += Math.abs(actual + 1.0) / 2.0; + + actual = SimpleXor3InputTest.propagate(graph, 1.0, 1.0, -1.0); + error += Math.abs(actual + 1.0) / 2.0; + + actual = SimpleXor3InputTest.propagate(graph, 1.0, -1.0, -1.0); + error += Math.abs(actual - 1.0) / 2.0; + + actual = SimpleXor3InputTest.propagate(graph, -1.0, 1.0, -1.0); + error += Math.abs(actual - 1.0) / 2.0; + + actual = SimpleXor3InputTest.propagate(graph, -1.0, -1.0, 1.0); + error += Math.abs(actual - 1.0) / 2.0; + + actual = SimpleXor3InputTest.propagate(graph, -1.0, -1.0, -1.0); + error += Math.abs(actual + 1.0) / 2.0; + + return error/8.0; + } private static void train(final FramedTransactionalGraph<?> graph, final double input1, final double input2, final double input3, final double expected) { SimpleXor3InputTest.propagate(graph, input1, input2, input3); @@ -90,9 +118,6 @@ public class SimpleXor3InputTest { final Iterator<BackpropNeuron> biasNeurons = graph.getVertices("layer", "bias", BackpropNeuron.class).iterator(); biasNeurons.next().backpropagate(); - biasNeurons.next().backpropagate(); - biasNeurons.next().backpropagate(); - biasNeurons.next().backpropagate(); Assert.assertTrue(!biasNeurons.hasNext()); graph.commit(); }