public void ApplyWeightAdjustments_PropogatesThroughNetwork() { //// SETUP const double ErrorSignal = -2.3d; const float Momentum = 0.9f; const float LearningRate = 0.1f; // Create 2 inbound and 2 outbound mock connections. var mockInbound1 = new Mock<ISupervisedLearnerConnection>(); var mockInbound2 = new Mock<ISupervisedLearnerConnection>(); var mockOutbound1 = new Mock<ISupervisedLearnerConnection>(); var mockOutbound2 = new Mock<ISupervisedLearnerConnection>(); // program the mock outbounds such that both are reporting error signals mockOutbound1.SetupGet(mock => mock.IsReportingError).Returns(true); mockOutbound2.SetupGet(mock => mock.IsReportingError).Returns(true); // Create 2 input nodes and 2 output nodes. var mockInputNode1 = new Mock<ISupervisedLearnerNode>(); var mockInputNode2 = new Mock<ISupervisedLearnerNode>(); var mockOutputNode1 = new Mock<ISupervisedLearnerNode>(); var mockOutputNode2 = new Mock<ISupervisedLearnerNode>(); // Program nodes to report input/output sizes. mockInputNode1.SetupGet(mock => mock.InputSize).Returns(1); mockInputNode2.SetupGet(mock => mock.InputSize).Returns(1); mockOutputNode1.SetupGet(mock => mock.OutputSize).Returns(1); mockOutputNode2.SetupGet(mock => mock.OutputSize).Returns(1); // Program nodes to provide values. mockInputNode1.SetupGet(mock => mock.CachedErrors).Returns(new[] { ErrorSignal }); mockInputNode2.SetupGet(mock => mock.CachedErrors).Returns(new[] { ErrorSignal }); mockOutputNode1.SetupGet(mock => mock.CachedOutputs).Returns(new[] { 0.0d }); mockOutputNode2.SetupGet(mock => mock.CachedOutputs).Returns(new[] { 0.0d }); // Create the test object. var network = new BackpropagationNetwork(new Mock<IErrorCalculator>().Object); network.AddInboundConnection(mockInbound1.Object); network.AddInboundConnection(mockInbound2.Object); network.AddOutboundConnection(mockOutbound1.Object); network.AddOutboundConnection(mockOutbound2.Object); network.AddInputNode(mockInputNode1.Object); network.AddInputNode(mockInputNode2.Object); network.AddOutputNode(mockOutputNode1.Object); network.AddOutputNode(mockOutputNode2.Object); network.Fire(new[] { 0.0d }); network.CalculateError(ErrorSignal); // EXECUTION network.ApplyWeightAdjustments(LearningRate, Momentum); // VERIFICATION mockInputNode1.Verify(mock => mock.ApplyWeightAdjustments(LearningRate, Momentum), Times.Once()); mockInputNode2.Verify(mock => mock.ApplyWeightAdjustments(LearningRate, Momentum), Times.Once()); mockOutbound1.Verify(mock => mock.ApplyWeightAdjustments(LearningRate, Momentum), Times.Once()); mockOutbound2.Verify(mock => mock.ApplyWeightAdjustments(LearningRate, Momentum), Times.Once()); }
public void CalculateError_DoesNotCalculateUntilAllConnectionsReport() { //// SETUP // Create 2 inbound and 2 outbound mock connections. var mockInbound1 = new Mock<ISupervisedLearnerConnection>(); var mockInbound2 = new Mock<ISupervisedLearnerConnection>(); var mockOutboundReporting = new Mock<ISupervisedLearnerConnection>(); var mockOutboundNotReporting = new Mock<ISupervisedLearnerConnection>(); // program the mock outbounds such that one is reporting and one isn't mockOutboundReporting.SetupGet(mock => mock.IsReportingError).Returns(true); mockOutboundNotReporting.SetupGet(mock => mock.IsReportingError).Returns(false); // Create 2 input nodes and 2 output nodes. var mockInputNode1 = new Mock<ISupervisedLearnerNode>(); var mockInputNode2 = new Mock<ISupervisedLearnerNode>(); var mockOutputNode1 = new Mock<ISupervisedLearnerNode>(); var mockOutputNode2 = new Mock<ISupervisedLearnerNode>(); // Create the test object. var network = new BackpropagationNetwork(new Mock<IErrorCalculator>().Object); network.AddInboundConnection(mockInbound1.Object); network.AddInboundConnection(mockInbound2.Object); network.AddOutboundConnection(mockOutboundReporting.Object); network.AddOutboundConnection(mockOutboundNotReporting.Object); network.AddInputNode(mockInputNode1.Object); network.AddInputNode(mockInputNode2.Object); network.AddOutputNode(mockOutputNode1.Object); network.AddOutputNode(mockOutputNode2.Object); // EXECUTION const double ErrorSignal = -2.3d; network.CalculateError(ErrorSignal); // VERIFICATION: The IsReporting signals were checked... mockOutboundReporting.Verify(mock => mock.IsReportingError, Times.Exactly(1)); mockOutboundNotReporting.Verify(mock => mock.IsReportingError, Times.Exactly(1)); // ...but no calculation activities occurred. mockInbound1.Verify(mock => mock.ReportError(It.IsAny<double>()), Times.Never()); mockInbound2.Verify(mock => mock.ReportError(It.IsAny<double>()), Times.Never()); mockOutboundReporting.Verify(mock => mock.ClearReportingFlag(), Times.Never()); mockOutboundNotReporting.Verify(mock => mock.ClearReportingFlag(), Times.Never()); mockInputNode1.VerifyGet(mock => mock.CachedErrors, Times.Never()); mockInputNode2.VerifyGet(mock => mock.CachedErrors, Times.Never()); mockOutputNode1.Verify(mock => mock.CalculateError(It.IsAny<double>()), Times.Never()); mockOutputNode2.Verify(mock => mock.CalculateError(It.IsAny<double>()), Times.Never()); }
public void Train_TrainsTheNetwork() { //// SETUP const int NumEpochs = 3; const float LearningRate = 0.1f; const float Momentum = 0.9f; const double FinalError = 99.99d; var inputs = new[] { new[] { 1.0d, 2.0d }, new[] { 3.0d, 4.0d } }; var ideals = new[] { new[] { 5.0d, 6.0d }, new[] { 7.0d, 8.0d } }; var outputs = new[] { new[] { 3.5d, 5.5d }, new[] { 7.5d, 9.5d } }; var overallErrors = new[] { new[] { ideals[0][0] - outputs[0][0], ideals[0][1] - outputs[0][1] }, new[] { ideals[1][0] - outputs[1][0], ideals[1][1] - outputs[1][1] } }; var finalErrors = new[] { new[] { 1.5d, 2.5d }, new[] { 3.5d, 4.5d } }; var mockErrorCalc = new Mock<IErrorCalculator>(); mockErrorCalc.Setup(mock => mock.Calculate()).Returns(FinalError); // Create 2 input nodes and 2 output nodes. var mockInputNode1 = new Mock<ISupervisedLearnerNode>(); var mockInputNode2 = new Mock<ISupervisedLearnerNode>(); var mockOutputNode1 = new Mock<ISupervisedLearnerNode>(); var mockOutputNode2 = new Mock<ISupervisedLearnerNode>(); // Program nodes to report input/output sizes. mockInputNode1.SetupGet(mock => mock.InputSize).Returns(1); mockInputNode2.SetupGet(mock => mock.InputSize).Returns(1); mockOutputNode1.SetupGet(mock => mock.OutputSize).Returns(1); mockOutputNode2.SetupGet(mock => mock.OutputSize).Returns(1); // Program output nodes to return output values based on inputs. mockInputNode1.Setup(mock => mock.Fire(new[] { inputs[0][0] })).Callback(() => mockOutputNode1.SetupGet(mock => mock.CachedOutputs).Returns(new[] { outputs[0][0] })); mockInputNode2.Setup(mock => mock.Fire(new[] { inputs[0][1] })).Callback(() => mockOutputNode2.SetupGet(mock => mock.CachedOutputs).Returns(new[] { outputs[0][1] })); mockInputNode1.Setup(mock => mock.Fire(new[] { inputs[1][0] })).Callback(() => mockOutputNode1.SetupGet(mock => mock.CachedOutputs).Returns(new[] { outputs[1][0] })); mockInputNode2.Setup(mock => mock.Fire(new[] { inputs[1][1] })).Callback(() => mockOutputNode2.SetupGet(mock => mock.CachedOutputs).Returns(new[] { outputs[1][1] })); // Program input nodes to return final error based on overal errors. mockOutputNode1.Setup(mock => mock.CalculateError(overallErrors[0][0])).Callback( () => mockInputNode1.SetupGet(mock => mock.CachedErrors).Returns(new[] { finalErrors[0][0] })); mockOutputNode1.Setup(mock => mock.CalculateError(overallErrors[1][0])).Callback( () => mockInputNode1.SetupGet(mock => mock.CachedErrors).Returns(new[] { finalErrors[1][0] })); mockOutputNode2.Setup(mock => mock.CalculateError(overallErrors[0][1])).Callback( () => mockInputNode2.SetupGet(mock => mock.CachedErrors).Returns(new[] { finalErrors[0][1] })); mockOutputNode2.Setup(mock => mock.CalculateError(overallErrors[1][1])).Callback( () => mockInputNode2.SetupGet(mock => mock.CachedErrors).Returns(new[] { finalErrors[1][1] })); // Create the network var network = new BackpropagationNetwork(mockErrorCalc.Object); network.AddInputNode(mockInputNode1.Object); network.AddInputNode(mockInputNode2.Object); network.AddOutputNode(mockOutputNode1.Object); network.AddOutputNode(mockOutputNode2.Object); // Execute var actualError = network.Train(NumEpochs, LearningRate, Momentum, inputs, ideals); //// Verify // Use of error calculator mockErrorCalc.Verify(mock => mock.Reset(), Times.Exactly(NumEpochs)); mockErrorCalc.Verify(mock => mock.AddToErrorCalc(overallErrors[0]), Times.Exactly(NumEpochs)); mockErrorCalc.Verify(mock => mock.AddToErrorCalc(overallErrors[1]), Times.Exactly(NumEpochs)); mockErrorCalc.Verify(mock => mock.Calculate(), Times.Once()); // Use of input nodes mockInputNode1.Verify(mock => mock.Fire(new[] { inputs[0][0] }), Times.Exactly(NumEpochs)); mockInputNode1.Verify(mock => mock.Fire(new[] { inputs[1][0] }), Times.Exactly(NumEpochs)); mockInputNode2.Verify(mock => mock.Fire(new[] { inputs[0][1] }), Times.Exactly(NumEpochs)); mockInputNode2.Verify(mock => mock.Fire(new[] { inputs[1][1] }), Times.Exactly(NumEpochs)); mockInputNode1.Verify(mock => mock.ClearCachedErrors(), Times.Exactly(NumEpochs * inputs.Length)); mockInputNode2.Verify(mock => mock.ClearCachedErrors(), Times.Exactly(NumEpochs * inputs.Length)); mockInputNode1.Verify(mock => mock.ApplyWeightAdjustments(LearningRate, Momentum), Times.Exactly(NumEpochs)); mockInputNode2.Verify(mock => mock.ApplyWeightAdjustments(LearningRate, Momentum), Times.Exactly(NumEpochs)); // Use of output nodes mockOutputNode1.VerifyGet(mock => mock.CachedOutputs, Times.AtLeast(NumEpochs)); mockOutputNode2.VerifyGet(mock => mock.CachedOutputs, Times.AtLeast(NumEpochs)); mockOutputNode1.Verify(mock => mock.CalculateError(overallErrors[0][0]), Times.Exactly(NumEpochs)); mockOutputNode1.Verify(mock => mock.CalculateError(overallErrors[1][0]), Times.Exactly(NumEpochs)); mockOutputNode2.Verify(mock => mock.CalculateError(overallErrors[0][1]), Times.Exactly(NumEpochs)); mockOutputNode2.Verify(mock => mock.CalculateError(overallErrors[1][1]), Times.Exactly(NumEpochs)); // Verify Error Assert.AreEqual(FinalError, actualError); }
public void CalculateError_DistributesSignals() { //// SETUP const double ErrorSignal1 = -0.5d; const double ErrorSignal2 = 1.5d; const double DigitizedErrorSignal1 = -1.0d; const double DigitizedErrorSignal2 = 1.0d; const double NetworkErrorSignal1 = -1.0d; const double NetworkErrorSignal2 = 1.0d; var expectedNetworkErrors = new[] { NetworkErrorSignal1, NetworkErrorSignal2 }; // Create 2 inbound and 2 outbound mock connections. var mockInbound1 = new Mock<ISupervisedLearnerConnection>(); var mockInbound2 = new Mock<ISupervisedLearnerConnection>(); var mockOutbound1 = new Mock<ISupervisedLearnerConnection>(); var mockOutbound2 = new Mock<ISupervisedLearnerConnection>(); // program the mock outbounds such that all are reporting their respective errors mockOutbound1.SetupGet(mock => mock.ErrorSignal).Returns(ErrorSignal1); mockOutbound2.SetupGet(mock => mock.ErrorSignal).Returns(ErrorSignal2); mockOutbound1.SetupGet(mock => mock.IsReportingError).Returns(true); mockOutbound2.SetupGet(mock => mock.IsReportingError).Returns(true); // Create 2 input nodes and 5 output nodes. var mockInputNode1 = new Mock<ISupervisedLearnerNode>(); var mockInputNode2 = new Mock<ISupervisedLearnerNode>(); var mockOutputNode1 = new Mock<ISupervisedLearnerNode>(); var mockOutputNode2 = new Mock<ISupervisedLearnerNode>(); var mockOutputNode3 = new Mock<ISupervisedLearnerNode>(); var mockOutputNode4 = new Mock<ISupervisedLearnerNode>(); var mockOutputNode5 = new Mock<ISupervisedLearnerNode>(); // Program nodes to report input/output sizes. mockInputNode1.SetupGet(mock => mock.InputSize).Returns(1); mockInputNode2.SetupGet(mock => mock.InputSize).Returns(1); mockOutputNode1.SetupGet(mock => mock.OutputSize).Returns(1); mockOutputNode2.SetupGet(mock => mock.OutputSize).Returns(1); mockOutputNode3.SetupGet(mock => mock.OutputSize).Returns(1); mockOutputNode4.SetupGet(mock => mock.OutputSize).Returns(1); mockOutputNode5.SetupGet(mock => mock.OutputSize).Returns(1); // Program nodes to provide values. mockInputNode1.SetupGet(mock => mock.CachedErrors).Returns(new[] { NetworkErrorSignal1 }); mockInputNode2.SetupGet(mock => mock.CachedErrors).Returns(new[] { NetworkErrorSignal2 }); mockOutputNode1.SetupGet(mock => mock.CachedOutputs).Returns(new[] { 0.0d }); mockOutputNode2.SetupGet(mock => mock.CachedOutputs).Returns(new[] { 0.0d }); mockOutputNode3.SetupGet(mock => mock.CachedOutputs).Returns(new[] { 0.0d }); mockOutputNode4.SetupGet(mock => mock.CachedOutputs).Returns(new[] { 0.0d }); mockOutputNode5.SetupGet(mock => mock.CachedOutputs).Returns(new[] { 0.0d }); // Create the test object. var network = new BackpropagationNetwork(new Mock<IErrorCalculator>().Object); network.AddInboundConnection(mockInbound1.Object); network.AddInboundConnection(mockInbound2.Object); network.AddOutboundConnection(mockOutbound1.Object); network.AddOutboundConnection(mockOutbound2.Object); network.AddInputNode(mockInputNode1.Object); network.AddInputNode(mockInputNode2.Object); network.AddOutputNode(mockOutputNode1.Object); network.AddOutputNode(mockOutputNode2.Object); network.AddOutputNode(mockOutputNode3.Object); network.AddOutputNode(mockOutputNode4.Object); network.AddOutputNode(mockOutputNode5.Object); // EXECUTION network.Fire(new[] { 0.0d }); network.CalculateError(ErrorSignal1); // VERIFICATION: The IsReporting signals were checked... mockOutbound1.Verify(mock => mock.IsReportingError, Times.Exactly(1)); mockOutbound2.Verify(mock => mock.IsReportingError, Times.Exactly(1)); // ...and calculation activities occurred. mockInbound1.Verify(mock => mock.ReportError(NetworkErrorSignal1), Times.Once()); mockInbound2.Verify(mock => mock.ReportError(NetworkErrorSignal2), Times.Once()); mockOutbound1.VerifyGet(mock => mock.ErrorSignal, Times.Once()); mockOutbound1.Verify(mock => mock.ClearReportingFlag(), Times.Once()); mockOutbound2.VerifyGet(mock => mock.ErrorSignal, Times.Once()); mockOutbound2.Verify(mock => mock.ClearReportingFlag(), Times.Once()); mockInputNode1.VerifyGet(mock => mock.CachedErrors, Times.AtLeastOnce()); mockInputNode2.VerifyGet(mock => mock.CachedErrors, Times.AtLeastOnce()); mockOutputNode1.Verify(mock => mock.CalculateError(DigitizedErrorSignal1), Times.Once()); mockOutputNode2.Verify(mock => mock.CalculateError(DigitizedErrorSignal1), Times.Once()); mockOutputNode3.Verify(mock => mock.CalculateError(DigitizedErrorSignal1), Times.Once()); mockOutputNode4.Verify(mock => mock.CalculateError(DigitizedErrorSignal2), Times.Once()); mockOutputNode5.Verify(mock => mock.CalculateError(DigitizedErrorSignal2), Times.Once()); Assert.AreEqual(2, network.CachedErrors.Length); Assert.AreEqual(expectedNetworkErrors, network.CachedErrors); }