123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246 |
- #ifdef NICE_USELIB_CPPUNIT
- #include "TestLaplace.h"
- #include <string>
- #include <iostream>
- #include <stdexcept>
- #include <core/basics/cppunitex.h>
- #include <core/basics/numerictools.h>
- #include <vislearning/classifier/kernelclassifier/LikelihoodFunction.h>
- #include <vislearning/classifier/kernelclassifier/GPLaplaceOptimizationProblem.h>
- #include <vislearning/classifier/kernelclassifier/LaplaceApproximation.h>
- #include <vislearning/classifier/kernelclassifier/LHCumulativeGauss.h>
- #include <vislearning/math/kernels/KernelLinearCombination.h>
- using namespace NICE;
- using namespace OBJREC;
- using namespace std;
- CPPUNIT_TEST_SUITE_REGISTRATION( TestLaplace );
- void TestLaplace::setUp() {
- }
- void TestLaplace::tearDown() {
- }
- void TestLaplace::testLikelihoodDiff()
- {
- uint numSteps = 10000;
- double lengthScale = 1.3;
- double bias = 0.4;
- LHCumulativeGauss l (lengthScale, bias);
-
- for ( uint degree = 0 ; degree < 3 ; degree++ )
- {
- // test gradient
- double oldv = 0.0;
- double error = 0.0;
- for ( uint i = 0 ; i < numSteps; i++ )
- {
- double f = i / (double)numSteps;
- double v;
- if ( degree == 2 )
- v = l.hessian(1.0,f);
- else if ( degree == 1 )
- v = l.gradient(1.0,f);
- else
- v = l.logLike(1.0,f);
- if ( i > 0 )
- {
- double d = 0.0;
- d = (v - oldv)*numSteps;
- double diff = 0.0;
-
- if ( degree == 2 )
- diff = l.thirdgrad(1.0,f);
- else if ( degree == 1 )
- diff = l.hessian(1.0,f);
- else
- diff = l.gradient(1.0,f);
- error += fabs(d-diff);
- }
- oldv = v;
- }
- error /= numSteps;
- CPPUNIT_ASSERT_DOUBLES_EQUAL(0.0, error, 1e-4);
- }
- }
- void TestLaplace::testCumGaussPredict()
- {
- // test integral stuff
- uint numSteps = 100000;
-
- double lengthScale = 1.3;
- double bias = 0.4;
- LHCumulativeGauss l (lengthScale, bias);
- double mean = 0.0;
- double variance = 1.0;
- double sum = 0.0;
- for ( uint i = 0 ; i < numSteps ; i++ )
- {
- double f = randGaussDouble( sqrt(variance) ) + mean;
- sum += l.likelihood(1.0,f);
- }
- sum /= numSteps;
- double fActual= l.predictAnalytically( mean, variance );
- CPPUNIT_ASSERT_DOUBLES_EQUAL(sum, fActual , 1e-2);
- }
- void TestLaplace::testHyperParameterOptGradients()
- {
- double step = 0.00001;
- double interval = 1.0;
- double a_max = 0.0;
- bool firstIteration = true;
- double oldObj = 0.0;
- Vector iparameters (1);
- iparameters[0] = log(1.0);
- Vector y (6, 1.0);
- for ( uint i = 0 ; i < 3 ; i++ )
- y[i] = -1.0;
- Matrix X (6, 2);
- X(0,0) = 1.0; X(0,1) = 0.0;
- X(1,0) = 0.3; X(1,1) = 0.4;
- X(2,0) = 0.8; X(2,1) = 0.1;
- X(3,0) = -1.0; X(3,1) = 0.2;
- X(4,0) = -0.8; X(4,1) = 0.1;
- X(5,0) = -0.3; X(5,1) = 0.5;
- Matrix kernelMatrix (6,6);
- for ( uint i = 0 ; i < X.rows(); i++ )
- for ( uint j = 0 ; j < X.rows(); j++ )
- kernelMatrix(i,j) = exp(- (X.getRow(i) - X.getRow(j)).normL2());
-
- KernelData kernelData;
- kernelData.setCachedMatrix ( 0, &kernelMatrix );
- KernelLinearCombination kernelFunction ( 1 );
- kernelFunction.updateKernelData( &kernelData );
-
- LHCumulativeGauss likelihood;
- LaplaceApproximation laplaceApproximation;
- GPLaplaceOptimizationProblem gp_problem ( &kernelData, y, &kernelFunction, &likelihood, &laplaceApproximation, false );
- for ( double s = -interval ; s <= interval ; s+=step )
- {
- Vector parameters ( iparameters );
- parameters[0] += s;
- gp_problem.setParameters( parameters );
- double obj = gp_problem.computeObjective ( );
- Vector gradient;
- CPPUNIT_ASSERT_NO_THROW(gp_problem.computeGradient( gradient ) );
- double deriv = gradient[0];
- if ( ! firstIteration )
- {
- double derivApprox = ( obj - oldObj ) / step;
- double a = fabs(deriv - derivApprox);
- if ( a > a_max )
- a_max = a;
- // DEBUGGING:
- // cerr << "EVAL: " << parameters[0] << " objective " << obj << " D(closedform) " << deriv << " D(approximated) " << derivApprox << endl;
- }
- firstIteration = false;
- oldObj = obj;
- }
- CPPUNIT_ASSERT_DOUBLES_EQUAL(0.0, a_max, 1e-5);
-
- }
- void TestLaplace::testModeFinding()
- {
- Config conf;
- //conf.sB("LaplaceApproximation", "laplace_verbose", true );
- LHCumulativeGauss likelihood;
- Vector y (6, 1.0);
- for ( uint i = 0 ; i < 3 ; i++ )
- y[i] = -1.0;
- /** Test 1: Check the special case of a diagonal kernel matrix */
- {
- Matrix K (6,6);
- K.setIdentity();
- KernelData kernelData ( &conf, K );
- /* Due to the diagonal kernel matrix
- * mode finding is really simple
- *
- * objective function:
- * log L(y_i, f_i) - 0.5 * f_i^2
- * = log ( ( ::erf(y*f)+1 ) / 2.0 ) - 0.5 * f_i^2
- * gnuplot:
- * plot [-1:1] log ((erf(x)+1) / 2.0) - 0.5*x**2
- *
- *
- * and the mode f should obey the
- * equation:
- * L'(y_i, f_i) - f_i = 0
- *
- * L'(y_i, f_i) = y_i*exp(-f_i^2)/(L(y,f)*sqrt(Pi)) ;
- * L(y_i, f_i) = ( ::erf(y*f)+1 ) / 2.0
- *
- * y_i = 1 ->
- * exp(-f_i^2)/sqrt(PI) = f_i * (erf(f)+1) / 2.0
- * gnuplot
- * plot [-1:1] exp(-x**2)/sqrt(pi), x * (erf(x)+1) / 2.0
- *
- * -> intersection at f = 0.541132
- *
- */
-
- LaplaceApproximation laplaceApproximation ( &conf );
- laplaceApproximation.approximate ( &kernelData, y, &likelihood );
- const Vector & mode = laplaceApproximation.getMode();
- for ( uint k = 0 ; k < mode.size(); k++ )
- {
- double fActual = y[k] * mode[k];
- CPPUNIT_ASSERT_DOUBLES_EQUAL( 0.541132, fActual, 1e-5 );
- }
- }
-
- /** Test 2: Check the self-consistent equation of the Mode */
- {
- Matrix X (6, 2);
- X(0,0) = 1.0; X(0,1) = 0.0;
- X(1,0) = 0.3; X(1,1) = 0.4;
- X(2,0) = 0.8; X(2,1) = 0.1;
- X(3,0) = -1.0; X(3,1) = 0.2;
- X(4,0) = -0.8; X(4,1) = 0.1;
- X(5,0) = -0.3; X(5,1) = 0.5;
- Matrix K (6,6);
- for ( uint i = 0 ; i < X.rows(); i++ )
- for ( uint j = 0 ; j < X.rows(); j++ )
- K(i,j) = exp(- (X.getRow(i) - X.getRow(j)).normL2());
-
- KernelData kernelData ( &conf, K );
- LaplaceApproximation laplaceApproximation ( &conf );
- laplaceApproximation.approximate ( &kernelData, y, &likelihood );
- const Vector & mode = laplaceApproximation.getMode();
- Vector gradLikelihood ( mode.size() );
- for ( uint i = 0; i < mode.size(); i++ )
- gradLikelihood[i] = likelihood.gradient ( y[i], mode[i] );
- // the mode should obey the following equation: mode = K gradLikelihood
- // (cf. eq. 3.17 Rasmussen and Williams)
- double fActual = ( mode - K * gradLikelihood ).normL2();
- CPPUNIT_ASSERT_DOUBLES_EQUAL ( 0.0,fActual, 1e-10 );
- }
- }
- #endif
|