123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229 |
- #include <iostream>
- #include "core/vector/Algorithms.h"
- #include "core/algebra/CholeskyRobust.h"
- #include "core/algebra/CholeskyRobustAuto.h"
- #include "vislearning/math/kernels/OptimKernelParameterGradInterface.h"
- #include "GPLaplaceOptimizationProblem.h"
- using namespace std;
- using namespace NICE;
- using namespace OBJREC;
- GPLaplaceOptimizationProblem::GPLaplaceOptimizationProblem (
- KernelData *_kernelData,
- const NICE::Vector & _y,
- ParameterizedKernel *_kernel,
- const LikelihoodFunction *_likelihoodFunction,
- LaplaceApproximation *_laplaceApproximation,
- bool verbose )
- : OptimizationProblemFirst ( _kernel->getParameterSize() ),
- kernelData(_kernelData),
- kernel(_kernel),
- likelihoodFunction(_likelihoodFunction)
- {
- this->verbose = verbose;
- this->y.push_back ( _y );
- this->kernel->getParameters( parameters() );
- this->laplaceApproximation.push_back ( _laplaceApproximation );
- if ( verbose ) {
- cerr.precision(20);
- cerr << "GPLaplaceOptimizationProblem: initial parameters = " << parameters() << endl;
- }
- bestLooParameters.resize ( parameters().size() );
- bestAvgLooError = numeric_limits<double>::max();
- }
-
- GPLaplaceOptimizationProblem::GPLaplaceOptimizationProblem ( KernelData *_kernelData, const VVector & _y,
- ParameterizedKernel *_kernel, const LikelihoodFunction *_likelihoodFunction,
- const vector<LaplaceApproximation *> & _laplaceApproximation,
- bool verbose ) : OptimizationProblemFirst( _kernel->getParameterSize() ),
- kernelData(_kernelData),
- y(_y),
- kernel(_kernel),
- likelihoodFunction(_likelihoodFunction),
- laplaceApproximation(_laplaceApproximation)
- {
- this->verbose = verbose;
- this->kernel->getParameters( parameters() );
- if ( verbose ) {
- cerr.precision(20);
- cerr << "GPLaplaceOptimizationProblem: initial parameters = " << parameters() << endl;
- }
- if ( y.size() != laplaceApproximation.size() )
- fthrow(Exception, "Number of label vectors and number of Laplace approximation objects do not correspond.");
- bestLooParameters.resize ( parameters().size() );
- bestAvgLooError = numeric_limits<double>::max();
- }
-
- GPLaplaceOptimizationProblem::~GPLaplaceOptimizationProblem()
- {
- }
- void GPLaplaceOptimizationProblem::update ()
- {
- kernel->setParameters( parameters() );
- kernel->updateKernelData ( kernelData );
- kernelData->updateCholeskyFactorization();
- for ( uint i = 0 ; i < y.size(); i++ )
- laplaceApproximation[i]->approximate ( kernelData, y[i], likelihoodFunction );
- }
- double GPLaplaceOptimizationProblem::computeObjective()
- {
- if ( verbose ) {
- cerr << "GPLaplaceOptimizationProblem: computeObjective: " << parameters() << endl;
- }
- try {
- update();
- } catch ( Exception ) {
-
- if ( verbose )
- cerr << "GPLaplaceOptimizationProblem: kernel matrix might be singular" << endl;
- return numeric_limits<double>::max();
- }
-
- double loglikelihood = 0.0;
-
- for ( uint k = 0 ; k < laplaceApproximation.size() ; k++ )
- loglikelihood += - laplaceApproximation[k]->getObjective() + triangleMatrixLogDet ( laplaceApproximation[k]->getCholeskyB() );
- if ( verbose ) {
- cerr << "GPLaplaceOptimizationProblem: negative loglikelihood = " << loglikelihood << endl;
- }
- return loglikelihood;
- }
-
- void GPLaplaceOptimizationProblem::computeGradient( NICE::Vector& newGradient )
- {
- if ( verbose )
- cerr << "GPLaplaceOptimizationProblem: gradient computation : " << parameters() << endl;
- newGradient.resize(parameters().size());
- newGradient.set(0.0);
- for ( uint task = 0 ; task < laplaceApproximation.size(); task++ )
- {
-
-
-
-
-
- const Vector & w = laplaceApproximation[task]->getHessian();
-
- const Matrix & L = laplaceApproximation[task]->getCholeskyB();
-
- const Vector & f = laplaceApproximation[task]->getMode();
-
- const Matrix & kernelMatrix = kernelData->getKernelMatrix();
-
-
-
-
-
-
-
- Matrix R ( w.size(), w.size(), 0.0 );
- for ( uint i = 0 ; i < w.size(); i++ )
- R(i,i) = sqrt( w[i] );
-
- choleskySolveMatrixLargeScale ( L, R );
-
- for ( uint i = 0 ; i < R.rows(); i++ )
- for ( uint j = 0 ; j < R.cols(); j++ )
- R(i,j) *= sqrt( w[i] );
-
-
- Matrix C ( kernelMatrix );
- for ( uint i = 0 ; i < C.rows(); i++ )
- for ( uint j = 0 ; j < C.cols(); j++ )
- C(i,j) *= sqrt( w[i] );
- triangleSolveMatrix ( L, C );
-
-
-
- Vector s2 (w.size());
- for ( uint i = 0 ; i < w.size() ; i++ )
- {
- double nabla3 = likelihoodFunction->thirdgrad ( y[task][i], f[i] );
- Vector cColumn = C.getColumnRef(i);
- s2[i] = 0.5 * (kernelMatrix(i,i) - cColumn.scalarProduct(cColumn)) * nabla3;
- }
-
- const Vector & a = laplaceApproximation[task]->getAVector();
-
-
- const Vector & gradientL = laplaceApproximation[task]->getGradient();
-
-
-
-
-
- for ( uint k = 0 ; k < parameters().size() ; k++ )
- {
-
-
-
-
-
-
- kernel->getKernelJacobi ( k, parameters(), kernelData, C );
-
- double s1 = C.bilinear ( a );
-
- for ( uint i = 0 ; i < R.rows(); i++ )
- for ( uint j = 0 ; j < R.cols(); j++ )
- s1 -= R(i,j) * C(i,j);
- s1 *= 0.5;
-
-
- Vector b = C * gradientL;
-
-
- Vector s3 = b - kernelMatrix*(R*b);
-
-
-
-
- newGradient[k] += - s1 - s2.scalarProduct(s3);
- }
- }
- if ( verbose )
- cerr << "GPLaplaceOptimizationProblem: gradient = " << newGradient << endl;
- }
-
- void GPLaplaceOptimizationProblem::useLooParameters ( )
- {
- parameters() = bestLooParameters;
- update();
- }
|