RegGaussianProcess.cpp 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182
  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. useLooParameters = src.useLooParameters;
  57. maxIterations = src.maxIterations;
  58. optimizeParameters = src.optimizeParameters;
  59. optimizationMethod = src.optimizationMethod;
  60. traceApproximation = src.traceApproximation;
  61. modelselcrit = src.modelselcrit;
  62. }
  63. RegGaussianProcess::~RegGaussianProcess()
  64. {
  65. if ( traceApproximation != NULL )
  66. delete traceApproximation;
  67. if ( modelselcrit != NULL )
  68. delete modelselcrit;
  69. }
  70. void RegGaussianProcess::teach ( KernelData *kernelData, const NICE::Vector & y )
  71. {
  72. if ( optimizeParameters )
  73. {
  74. if ( (kernelFunction != NULL) )
  75. {
  76. ParameterizedKernel *kernelPara = dynamic_cast< ParameterizedKernel * > ( kernelFunction );
  77. if ( kernelPara == NULL ) {
  78. fthrow(Exception, "RegGaussianProcess: you have to specify a parameterized kernel !");
  79. }
  80. GPRegressionOptimizationProblem gpopt ( kernelData, y, kernelPara,
  81. verbose, modelselcrit, traceApproximation );
  82. cout << "RegGaussianProcess: Hyperparameter optimization ..." << endl;
  83. if ( optimizationMethod == OPTIMIZATION_METHOD_TRUSTREGION )
  84. {
  85. if ( verbose )
  86. cerr << "RegGaussianProcess: using trust region optimizer" << endl;
  87. FirstOrderTrustRegion *optimizer = new FirstOrderTrustRegion(0.1 /*typical gradient*/, verbose);
  88. optimizer->setEpsilonG ( 0.01 );
  89. optimizer->setMaxIterations ( maxIterations );
  90. optimizer->optimizeFirst ( gpopt );
  91. delete optimizer;
  92. } else if ( optimizationMethod == OPTIMIZATION_METHOD_RASMUSSEN ) {
  93. if ( verbose )
  94. cerr << "RegGaussianProcess: using conjugate gradient optimizer" << endl;
  95. FirstOrderRasmussen *optimizer = new FirstOrderRasmussen( verbose );
  96. optimizer->setEpsilonG ( 0.01 );
  97. optimizer->setMaxIterations ( -maxIterations );
  98. optimizer->optimizeFirst ( gpopt );
  99. delete optimizer;
  100. } else {
  101. fthrow(Exception, "Unknown optimization method " << optimizationMethod );
  102. }
  103. cout << "RegGaussianProcess: Hyperparameter optimization ...done" << endl;
  104. if ( useLooParameters )
  105. {
  106. cerr << "RegGaussianProcess: using best loo parameters" << endl;
  107. gpopt.useLooParameters();
  108. }
  109. gpopt.update();
  110. Vector parameters;
  111. kernelPara->getParameters ( parameters );
  112. cout << "RegGaussianProcess: Optimization finished: " << parameters << endl << endl;
  113. } else {
  114. fthrow(Exception, "KCGPRegression: you have to specify a kernel function !" );
  115. }
  116. } else {
  117. if ( !kernelData->hasCholeskyFactorization() )
  118. kernelData->updateCholeskyFactorization();
  119. }
  120. this->y.resize ( y.size() );
  121. this->y = y;
  122. this->kInvY.resize ( this->y.size() );
  123. kernelData->computeInverseKernelMultiply ( y, this->kInvY );
  124. }
  125. double RegGaussianProcess::predictKernel ( const NICE::Vector & kernelVector, double kernelSelf )
  126. {
  127. // kernelSelf is not needed for the regression type of GP
  128. if ( kernelVector.size() != this->y.size() )
  129. fthrow(Exception, "RegGaussianProcess::predictKernel: size of kernel value vector " <<
  130. kernelVector.size() << " does not match number of training points " << this->y.size() );
  131. double yEstimate = kernelVector.scalarProduct ( kInvY );
  132. return yEstimate;
  133. }
  134. RegGaussianProcess *RegGaussianProcess::clone(void) const
  135. {
  136. return new RegGaussianProcess ( *this );
  137. }
  138. void RegGaussianProcess::store(std::ostream& ofs, int type) const
  139. {
  140. ofs << kInvY << endl;
  141. ofs << this->y << endl;
  142. }
  143. void RegGaussianProcess::restore(std::istream& ifs, int type)
  144. {
  145. ifs >> kInvY;
  146. ifs >> this->y;
  147. }