RegGaussianProcess.cpp 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181
  1. /**
  2. * @file RegGaussianProcess.cpp
  3. * @brief Regression using Gaussian Processes
  4. * @author Erik Rodner
  5. * @date 12/09/2009
  6. */
  7. #include <iostream>
  8. #include <sstream>
  9. #include "core/optimization/gradientBased/OptimizationAlgorithmFirst.h"
  10. #include "core/optimization/gradientBased/FirstOrderTrustRegion.h"
  11. #include "core/optimization/gradientBased/FirstOrderRasmussen.h"
  12. #include "core/vector/Algorithms.h"
  13. #include "core/algebra/CholeskyRobust.h"
  14. #include "core/algebra/CholeskyRobustAuto.h"
  15. #include "RegGaussianProcess.h"
  16. #include "GPRegressionOptimizationProblem.h"
  17. using namespace std;
  18. using namespace NICE;
  19. using namespace OBJREC;
  20. RegGaussianProcess::RegGaussianProcess( const Config *conf, Kernel *kernelFunction, const string & section ) : RegressionAlgorithmKernel ( conf, kernelFunction )
  21. {
  22. this->verbose = conf->gB(section, "verbose", false );
  23. this->optimizeParameters = conf->gB(section, "optimize_parameters", true );
  24. this->maxIterations = conf->gI( section, "optimization_maxiterations", 30 );
  25. string optimizationMethod_s = conf->gS(section, "optimization_method", "rasmussen" );
  26. if ( optimizationMethod_s == "rasmussen" )
  27. optimizationMethod = OPTIMIZATION_METHOD_RASMUSSEN;
  28. else if ( optimizationMethod_s == "trustregion" )
  29. optimizationMethod = OPTIMIZATION_METHOD_TRUSTREGION;
  30. else
  31. fthrow(Exception, "Optimization method " << optimizationMethod_s << " is unknown.");
  32. ParameterizedKernel *pkernelFunction = dynamic_cast< ParameterizedKernel * > ( kernelFunction );
  33. if ( optimizeParameters && (pkernelFunction == NULL) )
  34. {
  35. cerr << "RegGaussianProcess: Unable to optimize hyperparameters with no specified kernel function" << endl;
  36. cerr << "RegGaussianProcess: Switching to non-optimization mode" << endl;
  37. optimizeParameters = false;
  38. }
  39. bool approximateTraceTerm = conf->gB(section, "approximate_trace_term", false);
  40. if ( approximateTraceTerm )
  41. traceApproximation = new TraceApproximation ( conf, section );
  42. else
  43. traceApproximation = NULL;
  44. useLooParameters = conf->gB(section, "use_loo_parameters", true );
  45. modelselcrit = NULL;
  46. if ( useLooParameters ) {
  47. string modelselcrit_s = conf->gS("section", "loo_crit", "loo_pred_prob" );
  48. modelselcrit = GenericGPModelSelection::selectModelSel ( conf, modelselcrit_s );
  49. }
  50. }
  51. RegGaussianProcess::RegGaussianProcess ( const RegGaussianProcess & src ) :
  52. RegressionAlgorithmKernel ( src )
  53. {
  54. kInvY = src.kInvY;
  55. verbose = src.verbose;
  56. maxIterations = src.maxIterations;
  57. optimizeParameters = src.optimizeParameters;
  58. optimizationMethod = src.optimizationMethod;
  59. traceApproximation = src.traceApproximation;
  60. modelselcrit = src.modelselcrit;
  61. }
  62. RegGaussianProcess::~RegGaussianProcess()
  63. {
  64. if ( traceApproximation != NULL )
  65. delete traceApproximation;
  66. if ( modelselcrit != NULL )
  67. delete modelselcrit;
  68. }
  69. void RegGaussianProcess::teachKernel ( KernelData *kernelData, const NICE::Vector & y )
  70. {
  71. if ( optimizeParameters )
  72. {
  73. if ( (kernelFunction != NULL) )
  74. {
  75. ParameterizedKernel *kernelPara = dynamic_cast< ParameterizedKernel * > ( kernelFunction );
  76. if ( kernelPara == NULL ) {
  77. fthrow(Exception, "RegGaussianProcess: you have to specify a parameterized kernel !");
  78. }
  79. GPRegressionOptimizationProblem gpopt ( kernelData, y, kernelPara,
  80. verbose, modelselcrit, traceApproximation );
  81. cout << "RegGaussianProcess: Hyperparameter optimization ..." << endl;
  82. if ( optimizationMethod == OPTIMIZATION_METHOD_TRUSTREGION )
  83. {
  84. if ( verbose )
  85. cerr << "RegGaussianProcess: using trust region optimizer" << endl;
  86. FirstOrderTrustRegion *optimizer = new FirstOrderTrustRegion(0.1 /*typical gradient*/, verbose);
  87. optimizer->setEpsilonG ( 0.01 );
  88. optimizer->setMaxIterations ( maxIterations );
  89. optimizer->optimizeFirst ( gpopt );
  90. delete optimizer;
  91. } else if ( optimizationMethod == OPTIMIZATION_METHOD_RASMUSSEN ) {
  92. if ( verbose )
  93. cerr << "RegGaussianProcess: using conjugate gradient optimizer" << endl;
  94. FirstOrderRasmussen *optimizer = new FirstOrderRasmussen( verbose );
  95. optimizer->setEpsilonG ( 0.01 );
  96. optimizer->setMaxIterations ( -maxIterations );
  97. optimizer->optimizeFirst ( gpopt );
  98. delete optimizer;
  99. } else {
  100. fthrow(Exception, "Unknown optimization method " << optimizationMethod );
  101. }
  102. cout << "RegGaussianProcess: Hyperparameter optimization ...done" << endl;
  103. if ( useLooParameters )
  104. {
  105. cerr << "RegGaussianProcess: using best loo parameters" << endl;
  106. gpopt.useLooParameters();
  107. }
  108. gpopt.update();
  109. Vector parameters;
  110. kernelPara->getParameters ( parameters );
  111. cout << "RegGaussianProcess: Optimization finished: " << parameters << endl << endl;
  112. } else {
  113. fthrow(Exception, "KCGPRegression: you have to specify a kernel function !" );
  114. }
  115. } else {
  116. if ( !kernelData->hasCholeskyFactorization() )
  117. kernelData->updateCholeskyFactorization();
  118. }
  119. this->y.resize ( y.size() );
  120. this->y = y;
  121. this->kInvY.resize ( this->y.size() );
  122. kernelData->computeInverseKernelMultiply ( y, this->kInvY );
  123. }
  124. double RegGaussianProcess::predictKernel ( const NICE::Vector & kernelVector, double kernelSelf )
  125. {
  126. // kernelSelf is not needed for the regression type of GP
  127. if ( kernelVector.size() != this->y.size() )
  128. fthrow(Exception, "RegGaussianProcess::predictKernel: size of kernel value vector " <<
  129. kernelVector.size() << " does not match number of training points " << this->y.size() );
  130. double yEstimate = kernelVector.scalarProduct ( kInvY );
  131. return yEstimate;
  132. }
  133. RegGaussianProcess *RegGaussianProcess::clone(void) const
  134. {
  135. return new RegGaussianProcess ( *this );
  136. }
  137. void RegGaussianProcess::store(std::ostream& ofs, int type) const
  138. {
  139. ofs << kInvY << endl;
  140. ofs << this->y << endl;
  141. }
  142. void RegGaussianProcess::restore(std::istream& ifs, int type)
  143. {
  144. ifs >> kInvY;
  145. ifs >> this->y;
  146. }