/* * File: ImportanceSamplingTest.java * Authors: Kevin R. Dixon * Company: Sandia National Laboratories * Project: Cognitive Foundry * * Copyright Mar 3, 2010, 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.statistics.bayesian; import gov.sandia.cognition.statistics.bayesian.conjugate.BernoulliBayesianEstimator; import gov.sandia.cognition.statistics.ProbabilityFunction; import gov.sandia.cognition.statistics.DataDistribution; import gov.sandia.cognition.statistics.distribution.BernoulliDistribution; import gov.sandia.cognition.statistics.distribution.BetaDistribution; import gov.sandia.cognition.statistics.distribution.GammaDistribution; import gov.sandia.cognition.statistics.distribution.LogNormalDistribution; import gov.sandia.cognition.statistics.distribution.UniformDistribution; import gov.sandia.cognition.statistics.distribution.UnivariateGaussian; import gov.sandia.cognition.util.AbstractCloneableSerializable; import gov.sandia.cognition.util.DefaultWeightedValue; import gov.sandia.cognition.util.WeightedValue; import java.util.ArrayList; import junit.framework.TestCase; import java.util.Random; /** * Unit tests for ImportanceSamplingTest. * * @author krdixon */ public class ImportanceSamplingTest extends TestCase { /** * Random number generator to use for a fixed random seed. */ public final Random RANDOM = new Random( 1 ); /** * Default tolerance of the regression tests, {@value}. */ public final double TOLERANCE = 1e-5; /** * Tests for class ImportanceSamplingTest. * @param testName Name of the test. */ public ImportanceSamplingTest( String testName) { super(testName); } /** * Tests the constructors of class ImportanceSamplingTest. */ public void testConstructors() { System.out.println( "Constructors" ); ImportanceSampling<Integer,Double> instance = new ImportanceSampling<Integer,Double>(); assertEquals( ImportanceSampling.DEFAULT_NUM_SAMPLES, instance.getNumSamples() ); assertNull( instance.getUpdater() ); assertNull( instance.getRandom() ); } /** * Test of clone method, of class ImportanceSampling. */ public void testClone() { System.out.println("clone"); ImportanceSampling<Integer,Double> instance = new ImportanceSampling<Integer,Double>(); instance.setRandom(RANDOM); instance.setNumSamples(1000); instance.setUpdater( new ImportanceSampling.DefaultUpdater<Integer,Double>() ); ImportanceSampling<Integer,Double> clone = instance.clone(); assertNotSame( instance, clone ); assertNotSame( instance.getUpdater(), clone.getUpdater() ); assertNotNull( clone.getUpdater() ); } /** * Bernoulli Inference */ public void testBernoulliInference() { System.out.println( "Bernoulli Inference" ); double p = 0.75; BernoulliDistribution.PMF target = new BernoulliDistribution.PMF(p); final int numSamples = 1000; ArrayList<? extends Number> samples = target.sample(RANDOM, numSamples); ImportanceSampling<Number,Double> instance = new ImportanceSampling<Number, Double>(); instance.setNumSamples(1000); instance.setRandom(RANDOM); BernoulliDistribution.PMF pmf = new BernoulliDistribution.PMF(); ProbabilityFunction<Double> prior = new UniformDistribution.PDF( 0.0, 1.0 ); ImportanceSampling.DefaultUpdater<Number,Double> updater = new ImportanceSampling.DefaultUpdater<Number,Double>( new DefaultBayesianParameter<Double,BernoulliDistribution.PMF,ProbabilityFunction<Double>>( pmf, "p", prior ) ); assertNotNull( updater.getConjuctive() ); instance.setUpdater( updater ); DataDistribution<Double> result = instance.learn(samples); ArrayList<WeightedValue<Double>> ps = new ArrayList<WeightedValue<Double>>( result.getDomain().size() ); for( Double pvalue : result.getDomain() ) { ps.add( new DefaultWeightedValue<Double>( pvalue, result.get(pvalue) ) ); } System.out.println( "Nonzero = " + result.getDomain().size() ); UnivariateGaussian presult = UnivariateGaussian.WeightedMaximumLikelihoodEstimator.learn(ps, 0.0); System.out.println( "Presult: " + presult ); BernoulliBayesianEstimator bbe = new BernoulliBayesianEstimator(); BetaDistribution posterior = bbe.learn(samples); System.out.println( "Beta: Mean = " + posterior.getMean() + ", Variance = " + posterior.getVariance() ); } /** * Test Gamma Distribution */ public void testGammaInference() { System.out.println( "Gamma Distribution Inference" ); double shape = 5.0; double scale = 2.0; GammaDistribution.PDF target = new GammaDistribution.PDF( shape, scale ); final int numSamples = 1000; ArrayList<Double> samples = target.sample(RANDOM, numSamples); ImportanceSampling<Double,GammaDistribution.PDF> instance = new ImportanceSampling<Double, GammaDistribution.PDF>(); instance.setRandom(RANDOM); instance.setNumSamples(1000); instance.setUpdater(new GammaUpdater() ); DataDistribution<GammaDistribution.PDF> result = instance.learn(samples); ArrayList<WeightedValue<Double>> shapes = new ArrayList<WeightedValue<Double>>( result.getDomain().size() ); ArrayList<WeightedValue<Double>> scales = new ArrayList<WeightedValue<Double>>( result.getDomain().size() ); for( GammaDistribution.PDF gamma : result.getDomain() ) { shapes.add( new DefaultWeightedValue<Double>( gamma.getShape(), result.get(gamma) ) ); scales.add( new DefaultWeightedValue<Double>( gamma.getScale(), result.get(gamma) ) ); } System.out.println( "Nonzero = " + result.getDomain().size() ); UnivariateGaussian shapeResult = UnivariateGaussian.WeightedMaximumLikelihoodEstimator.learn(shapes, 0.0); UnivariateGaussian scaleResult = UnivariateGaussian.WeightedMaximumLikelihoodEstimator.learn(scales, 0.0); System.out.println( "Shape: " + shapeResult ); System.out.println( "Scale: " + scaleResult ); System.out.println( "Target: " + target ); } public class GammaUpdater extends AbstractCloneableSerializable implements ImportanceSampling.Updater<Double,GammaDistribution.PDF> { private ProbabilityFunction<Double> tweaker; public GammaUpdater() { this.tweaker = new LogNormalDistribution.PDF(1.0, 1.0); } public GammaDistribution.PDF update( GammaDistribution.PDF previousParameter) { double sf1 = this.tweaker.sample(RANDOM); double sf2 = this.tweaker.sample(RANDOM); return new GammaDistribution.PDF( sf1 * previousParameter.getShape(), sf2 * previousParameter.getScale() ); } public double computeLogLikelihood( GammaDistribution.PDF parameter, Iterable<? extends Double> data) { return BayesianUtil.logLikelihood(parameter, data); } public double computeLogImportanceValue( GammaDistribution.PDF parameter) { return this.tweaker.logEvaluate(parameter.getShape()) + this.tweaker.logEvaluate( parameter.getScale() ); } public GammaDistribution.PDF makeProposal( Random random) { return new GammaDistribution.PDF( this.tweaker.sample(random), this.tweaker.sample(random) ); } } }