package aima.test.core.unit.learning.neural;
import org.junit.Assert;
import org.junit.Test;
import aima.core.learning.neural.BackPropLearning;
import aima.core.learning.neural.Layer;
import aima.core.learning.neural.LayerSensitivity;
import aima.core.learning.neural.LogSigActivationFunction;
import aima.core.learning.neural.PureLinearActivationFunction;
import aima.core.util.math.Matrix;
import aima.core.util.math.Vector;
public class LayerTests {
@Test
public void testFeedForward() {
// example 11.14 of Neural Network Design by Hagan, Demuth and Beale
// lots of tedious tests necessary to ensure nn is fundamentally correct
Matrix weightMatrix1 = new Matrix(2, 1);
weightMatrix1.set(0, 0, -0.27);
weightMatrix1.set(1, 0, -0.41);
Vector biasVector1 = new Vector(2);
biasVector1.setValue(0, -0.48);
biasVector1.setValue(1, -0.13);
Layer layer1 = new Layer(weightMatrix1, biasVector1,
new LogSigActivationFunction());
Vector inputVector1 = new Vector(1);
inputVector1.setValue(0, 1);
Vector expected = new Vector(2);
expected.setValue(0, 0.321);
expected.setValue(1, 0.368);
Vector result1 = layer1.feedForward(inputVector1);
Assert.assertEquals(expected.getValue(0), result1.getValue(0), 0.001);
Assert.assertEquals(expected.getValue(1), result1.getValue(1), 0.001);
Matrix weightMatrix2 = new Matrix(1, 2);
weightMatrix2.set(0, 0, 0.09);
weightMatrix2.set(0, 1, -0.17);
Vector biasVector2 = new Vector(1);
biasVector2.setValue(0, 0.48);
Layer layer2 = new Layer(weightMatrix2, biasVector2,
new PureLinearActivationFunction());
Vector inputVector2 = layer1.getLastActivationValues();
Vector result2 = layer2.feedForward(inputVector2);
Assert.assertEquals(0.446, result2.getValue(0), 0.001);
}
@Test
public void testSensitivityMatrixCalculationFromErrorVector() {
Matrix weightMatrix1 = new Matrix(2, 1);
weightMatrix1.set(0, 0, -0.27);
weightMatrix1.set(1, 0, -0.41);
Vector biasVector1 = new Vector(2);
biasVector1.setValue(0, -0.48);
biasVector1.setValue(1, -0.13);
Layer layer1 = new Layer(weightMatrix1, biasVector1,
new LogSigActivationFunction());
Vector inputVector1 = new Vector(1);
inputVector1.setValue(0, 1);
layer1.feedForward(inputVector1);
Matrix weightMatrix2 = new Matrix(1, 2);
weightMatrix2.set(0, 0, 0.09);
weightMatrix2.set(0, 1, -0.17);
Vector biasVector2 = new Vector(1);
biasVector2.setValue(0, 0.48);
Layer layer2 = new Layer(weightMatrix2, biasVector2,
new PureLinearActivationFunction());
Vector inputVector2 = layer1.getLastActivationValues();
layer2.feedForward(inputVector2);
Vector errorVector = new Vector(1);
errorVector.setValue(0, 1.261);
LayerSensitivity layer2Sensitivity = new LayerSensitivity(layer2);
layer2Sensitivity.sensitivityMatrixFromErrorMatrix(errorVector);
Matrix sensitivityMatrix = layer2Sensitivity.getSensitivityMatrix();
Assert.assertEquals(-2.522, sensitivityMatrix.get(0, 0), 0.0001);
}
@Test
public void testSensitivityMatrixCalculationFromSucceedingLayer() {
Matrix weightMatrix1 = new Matrix(2, 1);
weightMatrix1.set(0, 0, -0.27);
weightMatrix1.set(1, 0, -0.41);
Vector biasVector1 = new Vector(2);
biasVector1.setValue(0, -0.48);
biasVector1.setValue(1, -0.13);
Layer layer1 = new Layer(weightMatrix1, biasVector1,
new LogSigActivationFunction());
LayerSensitivity layer1Sensitivity = new LayerSensitivity(layer1);
Vector inputVector1 = new Vector(1);
inputVector1.setValue(0, 1);
layer1.feedForward(inputVector1);
Matrix weightMatrix2 = new Matrix(1, 2);
weightMatrix2.set(0, 0, 0.09);
weightMatrix2.set(0, 1, -0.17);
Vector biasVector2 = new Vector(1);
biasVector2.setValue(0, 0.48);
Layer layer2 = new Layer(weightMatrix2, biasVector2,
new PureLinearActivationFunction());
Vector inputVector2 = layer1.getLastActivationValues();
layer2.feedForward(inputVector2);
Vector errorVector = new Vector(1);
errorVector.setValue(0, 1.261);
LayerSensitivity layer2Sensitivity = new LayerSensitivity(layer2);
layer2Sensitivity.sensitivityMatrixFromErrorMatrix(errorVector);
layer1Sensitivity
.sensitivityMatrixFromSucceedingLayer(layer2Sensitivity);
Matrix sensitivityMatrix = layer1Sensitivity.getSensitivityMatrix();
Assert.assertEquals(2, sensitivityMatrix.getRowDimension());
Assert.assertEquals(1, sensitivityMatrix.getColumnDimension());
Assert.assertEquals(-0.0495, sensitivityMatrix.get(0, 0), 0.001);
Assert.assertEquals(0.0997, sensitivityMatrix.get(1, 0), 0.001);
}
@Test
public void testWeightUpdateMatrixesFormedCorrectly() {
Matrix weightMatrix1 = new Matrix(2, 1);
weightMatrix1.set(0, 0, -0.27);
weightMatrix1.set(1, 0, -0.41);
Vector biasVector1 = new Vector(2);
biasVector1.setValue(0, -0.48);
biasVector1.setValue(1, -0.13);
Layer layer1 = new Layer(weightMatrix1, biasVector1,
new LogSigActivationFunction());
LayerSensitivity layer1Sensitivity = new LayerSensitivity(layer1);
Vector inputVector1 = new Vector(1);
inputVector1.setValue(0, 1);
layer1.feedForward(inputVector1);
Matrix weightMatrix2 = new Matrix(1, 2);
weightMatrix2.set(0, 0, 0.09);
weightMatrix2.set(0, 1, -0.17);
Vector biasVector2 = new Vector(1);
biasVector2.setValue(0, 0.48);
Layer layer2 = new Layer(weightMatrix2, biasVector2,
new PureLinearActivationFunction());
Vector inputVector2 = layer1.getLastActivationValues();
layer2.feedForward(inputVector2);
Vector errorVector = new Vector(1);
errorVector.setValue(0, 1.261);
LayerSensitivity layer2Sensitivity = new LayerSensitivity(layer2);
layer2Sensitivity.sensitivityMatrixFromErrorMatrix(errorVector);
layer1Sensitivity
.sensitivityMatrixFromSucceedingLayer(layer2Sensitivity);
Matrix weightUpdateMatrix2 = BackPropLearning.calculateWeightUpdates(
layer2Sensitivity, layer1.getLastActivationValues(), 0.1);
Assert.assertEquals(0.0809, weightUpdateMatrix2.get(0, 0), 0.001);
Assert.assertEquals(0.0928, weightUpdateMatrix2.get(0, 1), 0.001);
Matrix lastWeightUpdateMatrix2 = layer2.getLastWeightUpdateMatrix();
Assert.assertEquals(0.0809, lastWeightUpdateMatrix2.get(0, 0), 0.001);
Assert.assertEquals(0.0928, lastWeightUpdateMatrix2.get(0, 1), 0.001);
Matrix penultimateWeightUpdatematrix2 = layer2
.getPenultimateWeightUpdateMatrix();
Assert.assertEquals(0.0, penultimateWeightUpdatematrix2.get(0, 0),
0.001);
Assert.assertEquals(0.0, penultimateWeightUpdatematrix2.get(0, 1),
0.001);
Matrix weightUpdateMatrix1 = BackPropLearning.calculateWeightUpdates(
layer1Sensitivity, inputVector1, 0.1);
Assert.assertEquals(0.0049, weightUpdateMatrix1.get(0, 0), 0.001);
Assert.assertEquals(-0.00997, weightUpdateMatrix1.get(1, 0), 0.001);
Matrix lastWeightUpdateMatrix1 = layer1.getLastWeightUpdateMatrix();
Assert.assertEquals(0.0049, lastWeightUpdateMatrix1.get(0, 0), 0.001);
Assert.assertEquals(-0.00997, lastWeightUpdateMatrix1.get(1, 0), 0.001);
Matrix penultimateWeightUpdatematrix1 = layer1
.getPenultimateWeightUpdateMatrix();
Assert.assertEquals(0.0, penultimateWeightUpdatematrix1.get(0, 0),
0.001);
Assert.assertEquals(0.0, penultimateWeightUpdatematrix1.get(1, 0),
0.001);
}
@Test
public void testBiasUpdateMatrixesFormedCorrectly() {
Matrix weightMatrix1 = new Matrix(2, 1);
weightMatrix1.set(0, 0, -0.27);
weightMatrix1.set(1, 0, -0.41);
Vector biasVector1 = new Vector(2);
biasVector1.setValue(0, -0.48);
biasVector1.setValue(1, -0.13);
Layer layer1 = new Layer(weightMatrix1, biasVector1,
new LogSigActivationFunction());
LayerSensitivity layer1Sensitivity = new LayerSensitivity(layer1);
Vector inputVector1 = new Vector(1);
inputVector1.setValue(0, 1);
layer1.feedForward(inputVector1);
Matrix weightMatrix2 = new Matrix(1, 2);
weightMatrix2.set(0, 0, 0.09);
weightMatrix2.set(0, 1, -0.17);
Vector biasVector2 = new Vector(1);
biasVector2.setValue(0, 0.48);
Layer layer2 = new Layer(weightMatrix2, biasVector2,
new PureLinearActivationFunction());
LayerSensitivity layer2Sensitivity = new LayerSensitivity(layer2);
Vector inputVector2 = layer1.getLastActivationValues();
layer2.feedForward(inputVector2);
Vector errorVector = new Vector(1);
errorVector.setValue(0, 1.261);
layer2Sensitivity.sensitivityMatrixFromErrorMatrix(errorVector);
layer1Sensitivity
.sensitivityMatrixFromSucceedingLayer(layer2Sensitivity);
Vector biasUpdateVector2 = BackPropLearning.calculateBiasUpdates(
layer2Sensitivity, 0.1);
Assert.assertEquals(0.2522, biasUpdateVector2.getValue(0), 0.001);
Vector lastBiasUpdateVector2 = layer2.getLastBiasUpdateVector();
Assert.assertEquals(0.2522, lastBiasUpdateVector2.getValue(0), 0.001);
Vector penultimateBiasUpdateVector2 = layer2
.getPenultimateBiasUpdateVector();
Assert.assertEquals(0.0, penultimateBiasUpdateVector2.getValue(0),
0.001);
Vector biasUpdateVector1 = BackPropLearning.calculateBiasUpdates(
layer1Sensitivity, 0.1);
Assert.assertEquals(0.00495, biasUpdateVector1.getValue(0), 0.001);
Assert.assertEquals(-0.00997, biasUpdateVector1.getValue(1), 0.001);
Vector lastBiasUpdateVector1 = layer1.getLastBiasUpdateVector();
Assert.assertEquals(0.00495, lastBiasUpdateVector1.getValue(0), 0.001);
Assert.assertEquals(-0.00997, lastBiasUpdateVector1.getValue(1), 0.001);
Vector penultimateBiasUpdateVector1 = layer1
.getPenultimateBiasUpdateVector();
Assert.assertEquals(0.0, penultimateBiasUpdateVector1.getValue(0),
0.001);
Assert.assertEquals(0.0, penultimateBiasUpdateVector1.getValue(1),
0.001);
}
@Test
public void testWeightsAndBiasesUpdatedCorrectly() {
Matrix weightMatrix1 = new Matrix(2, 1);
weightMatrix1.set(0, 0, -0.27);
weightMatrix1.set(1, 0, -0.41);
Vector biasVector1 = new Vector(2);
biasVector1.setValue(0, -0.48);
biasVector1.setValue(1, -0.13);
Layer layer1 = new Layer(weightMatrix1, biasVector1,
new LogSigActivationFunction());
LayerSensitivity layer1Sensitivity = new LayerSensitivity(layer1);
Vector inputVector1 = new Vector(1);
inputVector1.setValue(0, 1);
layer1.feedForward(inputVector1);
Matrix weightMatrix2 = new Matrix(1, 2);
weightMatrix2.set(0, 0, 0.09);
weightMatrix2.set(0, 1, -0.17);
Vector biasVector2 = new Vector(1);
biasVector2.setValue(0, 0.48);
Layer layer2 = new Layer(weightMatrix2, biasVector2,
new PureLinearActivationFunction());
Vector inputVector2 = layer1.getLastActivationValues();
layer2.feedForward(inputVector2);
Vector errorVector = new Vector(1);
errorVector.setValue(0, 1.261);
LayerSensitivity layer2Sensitivity = new LayerSensitivity(layer2);
layer2Sensitivity.sensitivityMatrixFromErrorMatrix(errorVector);
layer1Sensitivity
.sensitivityMatrixFromSucceedingLayer(layer2Sensitivity);
BackPropLearning.calculateWeightUpdates(layer2Sensitivity,
layer1.getLastActivationValues(), 0.1);
BackPropLearning.calculateBiasUpdates(layer2Sensitivity, 0.1);
BackPropLearning.calculateWeightUpdates(layer1Sensitivity,
inputVector1, 0.1);
BackPropLearning.calculateBiasUpdates(layer1Sensitivity, 0.1);
layer2.updateWeights();
Matrix newWeightMatrix2 = layer2.getWeightMatrix();
Assert.assertEquals(0.171, newWeightMatrix2.get(0, 0), 0.001);
Assert.assertEquals(-0.0772, newWeightMatrix2.get(0, 1), 0.001);
layer2.updateBiases();
Vector newBiasVector2 = layer2.getBiasVector();
Assert.assertEquals(0.7322, newBiasVector2.getValue(0), 0.00001);
layer1.updateWeights();
Matrix newWeightMatrix1 = layer1.getWeightMatrix();
Assert.assertEquals(-0.265, newWeightMatrix1.get(0, 0), 0.001);
Assert.assertEquals(-0.419, newWeightMatrix1.get(1, 0), 0.001);
layer1.updateBiases();
Vector newBiasVector1 = layer1.getBiasVector();
Assert.assertEquals(-0.475, newBiasVector1.getValue(0), 0.001);
Assert.assertEquals(-0.139, newBiasVector1.getValue(1), 0.001);
}
}