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