/*
* File: ThreeLayerFeedforwardNeuralNetworkTest.java
* Authors: Kevin R. Dixon
* Company: Sandia National Laboratories
* Project: Cognitive Foundry
*
* Copyright Apr 16, 2009, Sandia Corporation.
* Under the terms of Contract DE-AC04-94AL85000, there is a non-exclusive
* license for use of this work by or on behalf of the U.S. Government.
* Export of this program may require a license from the United States
* Government. See CopyrightHistory.txt for complete details.
*
*/
package gov.sandia.cognition.learning.function.vector;
import gov.sandia.cognition.learning.algorithm.gradient.GradientDescendableApproximator;
import gov.sandia.cognition.learning.function.scalar.AtanFunction;
import gov.sandia.cognition.learning.function.scalar.SigmoidFunction;
import gov.sandia.cognition.math.DifferentiableUnivariateScalarFunction;
import gov.sandia.cognition.math.matrix.Matrix;
import gov.sandia.cognition.math.matrix.Vector;
import gov.sandia.cognition.math.matrix.VectorFactory;
import java.util.Random;
import junit.framework.TestCase;
/**
* Unit tests for {@name}.
*
* @author krdixon
*/
public class ThreeLayerFeedforwardNeuralNetworkTest
extends TestCase
{
public Random random = new Random( 1 );
public static final double EPS = 1e-5;
public ThreeLayerFeedforwardNeuralNetworkTest(
String testName)
{
super(testName);
}
public void testConstructors()
{
System.out.println( "constructors" );
ThreeLayerFeedforwardNeuralNetwork ann = new ThreeLayerFeedforwardNeuralNetwork();
assertEquals( ThreeLayerFeedforwardNeuralNetwork.DEFAULT_INITIALIZATION_RANGE, ann.getInitializationRange() );
assertSame( ThreeLayerFeedforwardNeuralNetwork.DEFAULT_SQUASHING_FUNCTION, ann.getSquashingFunction() );
assertEquals( 1, ann.getInputDimensionality() );
assertEquals( 1, ann.getHiddenDimensionality() );
assertEquals( 1, ann.getOutputDimensionality() );
assertEquals( 4, ann.convertToVector().getDimensionality() );
int numInputs = random.nextInt( 10 ) + 1;
int numHidden = random.nextInt( 10 ) + 1;
int numOutput = random.nextInt( 10 ) + 1;
double range = random.nextDouble();
int seed = random.nextInt();
DifferentiableUnivariateScalarFunction f = new SigmoidFunction();
ann = new ThreeLayerFeedforwardNeuralNetwork(
numInputs, numHidden, numOutput, f, seed, range );
assertEquals( numInputs, ann.getInputDimensionality() );
assertEquals( numHidden, ann.getHiddenDimensionality() );
assertEquals( numOutput, ann.getOutputDimensionality() );
assertSame( f, ann.getSquashingFunction() );
assertEquals( range, ann.getInitializationRange() );
}
/**
* Test of clone method, of class ThreeLayerFeedforwardNeuralNetwork.
*/
public void testClone()
{
System.out.println("clone");
int numInputs = random.nextInt( 10 ) + 1;
int numHidden = random.nextInt( 10 ) + 1;
int numOutput = random.nextInt( 10 ) + 1;
ThreeLayerFeedforwardNeuralNetwork instance = new ThreeLayerFeedforwardNeuralNetwork(
numInputs, numHidden, numOutput );
ThreeLayerFeedforwardNeuralNetwork clone = instance.clone();
assertNotSame( instance, clone );
assertNotSame( instance.getSquashingFunction(), clone.getSquashingFunction() );
Vector p1 = instance.convertToVector();
Vector p2 = clone.convertToVector();
assertEquals( p1, p2 );
Vector p3 = p2.scale(random.nextGaussian());
clone.convertFromVector(p3);
Vector p4 = clone.convertToVector();
assertEquals( p3, p4 );
// Make sure fiddling with the clone's parameters didn't duff up
// the original instance's parameters.
Vector p5 = instance.convertToVector();
assertEquals( p1, p5 );
}
/**
* Test of computeParameterGradient method, of class ThreeLayerFeedforwardNeuralNetwork.
*/
public void testComputeParameterGradient()
{
System.out.println("computeParameterGradient");
Vector input = VectorFactory.getDefault().copyValues(1.0,2.0);
ThreeLayerFeedforwardNeuralNetwork instance = new ThreeLayerFeedforwardNeuralNetwork();
instance.setRandom(random);
instance.setInitializationRange(10.0);
instance.initializeWeights(2, 2, 2);
Matrix result = instance.computeParameterGradient(input);
System.out.println( "Result:\n" + result );
GradientDescendableApproximator approx = new GradientDescendableApproximator(instance);
Matrix estimate = approx.computeParameterGradient(input);
System.out.println( "Estimte:\n" + estimate );
System.out.println( "Difference:\n" + estimate.minus(result) );
if( !estimate.equals(result,EPS) )
{
assertEquals(estimate,result);
}
}
/**
* Test of convertToVector method, of class ThreeLayerFeedforwardNeuralNetwork.
*/
public void testConvertToVector()
{
System.out.println("convertToVector");
int numInputs = random.nextInt( 10 ) + 1;
int numHidden = random.nextInt( 10 ) + 1;
int numOutput = random.nextInt( 10 ) + 1;
ThreeLayerFeedforwardNeuralNetwork ann =
new ThreeLayerFeedforwardNeuralNetwork( numInputs, numHidden, numOutput );
Vector p = ann.convertToVector();
assertEquals( numInputs*numHidden + numHidden + numHidden*numOutput + numOutput,
p.getDimensionality() );
// Make sure the values aren't all zeros
boolean nonzero = false;
for( int i = 0; i < p.getDimensionality(); i++ )
{
if( p.getElement(i) != 0.0 )
{
nonzero = true;
break;
}
}
assertTrue( nonzero );
}
/**
* Test of convertFromVector method, of class ThreeLayerFeedforwardNeuralNetwork.
*/
public void testConvertFromVector()
{
System.out.println("convertFromVector");
int numInputs = random.nextInt( 10 ) + 1;
int numHidden = random.nextInt( 10 ) + 1;
int numOutput = random.nextInt( 10 ) + 1;
ThreeLayerFeedforwardNeuralNetwork ann =
new ThreeLayerFeedforwardNeuralNetwork( numInputs, numHidden, numOutput );
Vector p1 = ann.convertToVector();
Vector p2 = p1.scale( random.nextGaussian() );
ann.convertFromVector(p2);
Vector p3 = ann.convertToVector();
assertEquals( p2, p3 );
}
/**
* Test of evaluate method, of class ThreeLayerFeedforwardNeuralNetwork.
*/
public void testEvaluate()
{
System.out.println("evaluate");
int numInputs = 1;
int numHidden = 2;
int numOutput = 1;
ThreeLayerFeedforwardNeuralNetwork ann =
new ThreeLayerFeedforwardNeuralNetwork( numInputs, numHidden, numOutput );
Vector p = VectorFactory.getDefault().copyValues( 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0 );
ann.convertFromVector(p);
// I found this by manually computing the output in octave...
Vector x1 = VectorFactory.getDefault().copyValues(2.0);
Vector y1 = ann.evaluate(x1);
System.out.println( "Y1: " + y1 );
assertEquals( 1, y1.getDimensionality() );
assertEquals( 22.545652, y1.getElement(0), EPS );
}
/**
* Test of initializeWeights method, of class ThreeLayerFeedforwardNeuralNetwork.
*/
public void testInitializeWeights()
{
System.out.println("initializeWeights");
ThreeLayerFeedforwardNeuralNetwork instance = new ThreeLayerFeedforwardNeuralNetwork();
int numInputs = random.nextInt( 10 ) + 1;
int numHidden = random.nextInt( 10 ) + 1;
int numOutput = random.nextInt( 10 ) + 1;
instance.initializeWeights(numInputs, numHidden, numOutput);
assertEquals( numInputs, instance.getInputDimensionality() );
assertEquals( numHidden, instance.getHiddenDimensionality() );
assertEquals( numOutput, instance.getOutputDimensionality() );
try
{
instance.initializeWeights(0, numHidden, numOutput );
fail( "numInputs must be >= 1" );
}
catch (Exception e)
{
System.out.println( "Good: " + e );
}
try
{
instance.initializeWeights(numInputs, 0, numOutput );
fail( "numHidden must be >= 1" );
}
catch (Exception e)
{
System.out.println( "Good: " + e );
}
try
{
instance.initializeWeights(numInputs, numHidden, 0 );
fail( "numOutput must be >= 1" );
}
catch (Exception e)
{
System.out.println( "Good: " + e );
}
}
/**
* Test of getOutputDimensionality method, of class ThreeLayerFeedforwardNeuralNetwork.
*/
public void testGetOutputDimensionality()
{
System.out.println("getOutputDimensionality");
int numInputs = random.nextInt( 10 ) + 1;
int numHidden = random.nextInt( 10 ) + 1;
int numOutput = random.nextInt( 10 ) + 1;
ThreeLayerFeedforwardNeuralNetwork instance = new ThreeLayerFeedforwardNeuralNetwork(
numInputs, numHidden, numOutput );
assertEquals( numOutput, instance.getOutputDimensionality() );
}
/**
* Test of setOutputDimensionality method, of class ThreeLayerFeedforwardNeuralNetwork.
*/
public void testSetOutputDimensionality()
{
System.out.println("setOutputDimensionality");
int numInputs = random.nextInt( 10 ) + 1;
int numHidden = random.nextInt( 10 ) + 1;
int numOutput = random.nextInt( 10 ) + 1;
ThreeLayerFeedforwardNeuralNetwork instance = new ThreeLayerFeedforwardNeuralNetwork(
numInputs, numHidden, numOutput );
assertEquals( numOutput, instance.getOutputDimensionality() );
Vector p1 = instance.convertToVector();
// This should reset the parameters
instance.setOutputDimensionality(numOutput);
Vector p2 = instance.convertToVector();
assertEquals( p1.getDimensionality(), p2.getDimensionality() );
assertFalse( p1.equals( p2 ) );
int n2 = numOutput+1;
instance.setOutputDimensionality(n2);
assertEquals( n2, instance.getOutputDimensionality() );
Vector p3 = instance.convertToVector();
// Adding another output means an addition connection from each
// of the hidden units PLUS the bias term
assertEquals( p2.getDimensionality() + numHidden + 1, p3.getDimensionality() );
try
{
instance.setOutputDimensionality(0);
fail( "Dimensionality must be > 0" );
}
catch (Exception e)
{
System.out.println( "Good: " + e );
}
}
/**
* Test of getHiddenDimensionality method, of class ThreeLayerFeedforwardNeuralNetwork.
*/
public void testGetHiddenDimensionality()
{
System.out.println("getHiddenDimensionality");
int numInputs = random.nextInt( 10 ) + 1;
int numHidden = random.nextInt( 10 ) + 1;
int numOutput = random.nextInt( 10 ) + 1;
ThreeLayerFeedforwardNeuralNetwork instance = new ThreeLayerFeedforwardNeuralNetwork(
numInputs, numHidden, numOutput );
assertEquals( numHidden, instance.getHiddenDimensionality() );
}
/**
* Test of setHiddenDimensionality method, of class ThreeLayerFeedforwardNeuralNetwork.
*/
public void testSetHiddenDimensionality()
{
System.out.println("setHiddenDimensionality");
int numInputs = random.nextInt( 10 ) + 1;
int numHidden = random.nextInt( 10 ) + 1;
int numOutput = random.nextInt( 10 ) + 1;
ThreeLayerFeedforwardNeuralNetwork instance = new ThreeLayerFeedforwardNeuralNetwork(
numInputs, numHidden, numOutput );
assertEquals( numHidden, instance.getHiddenDimensionality() );
Vector p1 = instance.convertToVector();
// This should reset the parameters
instance.setHiddenDimensionality(numHidden);
Vector p2 = instance.convertToVector();
assertEquals( p1.getDimensionality(), p2.getDimensionality() );
assertFalse( p1.equals( p2 ) );
int n2 = numHidden+1;
instance.setHiddenDimensionality(n2);
assertEquals( n2, instance.getHiddenDimensionality() );
Vector p3 = instance.convertToVector();
assertEquals( p2.getDimensionality() + numInputs + 1 + numOutput, p3.getDimensionality() );
try
{
instance.setHiddenDimensionality(0);
fail( "Dimensionality must be > 0" );
}
catch (Exception e)
{
System.out.println( "Good: " + e );
}
}
/**
* Test of getInputDimensionality method, of class ThreeLayerFeedforwardNeuralNetwork.
*/
public void testGetInputDimensionality()
{
System.out.println("getInputDimensionality");
int numInputs = random.nextInt( 10 ) + 1;
int numHidden = random.nextInt( 10 ) + 1;
int numOutput = random.nextInt( 10 ) + 1;
ThreeLayerFeedforwardNeuralNetwork instance = new ThreeLayerFeedforwardNeuralNetwork(
numInputs, numHidden, numOutput );
assertEquals( numInputs, instance.getInputDimensionality() );
}
/**
* Test of setInputDimensionality method, of class ThreeLayerFeedforwardNeuralNetwork.
*/
public void testSetInputDimensionality()
{
System.out.println("setInputDimensionality");
int numInputs = random.nextInt( 10 ) + 1;
int numHidden = random.nextInt( 10 ) + 1;
int numOutput = random.nextInt( 10 ) + 1;
ThreeLayerFeedforwardNeuralNetwork instance = new ThreeLayerFeedforwardNeuralNetwork(
numInputs, numHidden, numOutput );
assertEquals( numInputs, instance.getInputDimensionality() );
Vector p1 = instance.convertToVector();
// This should reset the parameters
instance.setInputDimensionality(numInputs);
Vector p2 = instance.convertToVector();
assertEquals( p1.getDimensionality(), p2.getDimensionality() );
assertFalse( p1.equals( p2 ) );
int n2 = numInputs+1;
instance.setInputDimensionality(n2);
assertEquals( n2, instance.getInputDimensionality() );
Vector p3 = instance.convertToVector();
assertEquals( p2.getDimensionality() + numHidden, p3.getDimensionality() );
try
{
instance.setInputDimensionality(0);
fail( "Dimensionality must be > 0" );
}
catch (Exception e)
{
System.out.println( "Good: " + e );
}
}
/**
* Test of getSquashingFunction method, of class ThreeLayerFeedforwardNeuralNetwork.
*/
public void testGetSquashingFunction()
{
System.out.println("getSquashingFunction");
ThreeLayerFeedforwardNeuralNetwork instance = new ThreeLayerFeedforwardNeuralNetwork();
assertSame( ThreeLayerFeedforwardNeuralNetwork.DEFAULT_SQUASHING_FUNCTION, instance.getSquashingFunction() );
}
/**
* Test of setSquashingFunction method, of class ThreeLayerFeedforwardNeuralNetwork.
*/
public void testSetSquashingFunction()
{
System.out.println("setSquashingFunction");
DifferentiableUnivariateScalarFunction squashingFunction =
new AtanFunction( random.nextDouble() );
ThreeLayerFeedforwardNeuralNetwork instance = new ThreeLayerFeedforwardNeuralNetwork();
assertSame( ThreeLayerFeedforwardNeuralNetwork.DEFAULT_SQUASHING_FUNCTION, instance.getSquashingFunction() );
instance.setSquashingFunction(squashingFunction);
assertSame( squashingFunction, instance.getSquashingFunction() );
}
/**
* Test of getInitializationRange method, of class ThreeLayerFeedforwardNeuralNetwork.
*/
public void testGetInitializationRange()
{
System.out.println("getInitializationRange");
ThreeLayerFeedforwardNeuralNetwork instance = new ThreeLayerFeedforwardNeuralNetwork();
assertEquals( ThreeLayerFeedforwardNeuralNetwork.DEFAULT_INITIALIZATION_RANGE, instance.getInitializationRange() );
}
/**
* Test of setInitializationRange method, of class ThreeLayerFeedforwardNeuralNetwork.
*/
public void testSetInitializationRange()
{
System.out.println("setInitializationRange");
double initializationRange = random.nextDouble();
ThreeLayerFeedforwardNeuralNetwork instance = new ThreeLayerFeedforwardNeuralNetwork();
assertEquals( ThreeLayerFeedforwardNeuralNetwork.DEFAULT_INITIALIZATION_RANGE, instance.getInitializationRange() );
instance.setInitializationRange(initializationRange);
assertEquals( initializationRange, instance.getInitializationRange() );
instance.setInitializationRange(0.0);
assertEquals( 0.0, instance.getInitializationRange() );
try
{
instance.setInitializationRange(-1.0 );
fail( "Range must be >= 0.0" );
}
catch (Exception e)
{
System.out.println( "Good: " + e );
}
}
}