freSPSAOptimizerController.cxx

Go to the documentation of this file.
00001 /*=========================================================================
00002 
00003   Program:   F.R.E.E. - flexible registration evaluation engine
00004   Version:   v.1.0.0
00005   Date:      $Date: 2006/09/01 12:00:00 $
00006   Module:    $RCSfile: freSPSAOptimizerController.cxx,v $
00007   Language:  C++
00008 
00009 
00010   Copyright (c) 2007 Ralf o Floca (Department of Medical Informatics,
00011   Institute for Medical Biometry and Informatics, University of Heidelberg,
00012   Germany). All rights reserved.
00013   See FREECopyright.txt or http://www.mi.med.uni-hd.de/free/copyright.htm
00014   for details.
00015 
00016      This software is distributed WITHOUT ANY WARRANTY; without even 
00017      the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
00018      PURPOSE.  See the above copyright notices for more information.
00019 
00020 =========================================================================*/
00021 
00022 #include "freSPSAOptimizerController.h"
00023 #include "freExceptions.h"
00024 
00025 namespace FREE
00026 {
00027 
00031 
00032 
00033 
00034 DefineParameterMacro(SPSAOptimizerController,MinimumNumberOfIteration,"MinimumNumberOfIteration","Minimum number of iteration the optimizer will compute.");
00035 DefineParameterMacro(SPSAOptimizerController,MaximumNumberOfIteration,"MaximumNumberOfIteration","Maximum number of iterations the optimizer will compute before terminating, even if no convergence is achieved.");
00036 DefineParameterMacro(SPSAOptimizerController,a,"a","a is a factor that scales the estimated gradient before substracting it from the current position to achive the next position. Should be non-negative. Can be estimated via GuessParameters.");
00037 DefineParameterMacro(SPSAOptimizerController,A,"A","A is a non-negative coefficient used to calculate the a of the next iteration step. Can be estimated via GuessParameters.");
00038 DefineParameterMacro(SPSAOptimizerController,c,"c","c is a factor that scales the pertubation vector, which will be added to the current position to estimate the gradient");
00039 DefineParameterMacro(SPSAOptimizerController,Alpha,"Alpha","Alpha is used to calculate the gain sequence a k.");
00040 DefineParameterMacro(SPSAOptimizerController,Gamma,"Gamma","Gamma is used to calculate the gain sequence c k.");
00041 DefineParameterMacro(SPSAOptimizerController,NumberOfPertubations,"NumberOfPertubations","Number of pertubations used to estimate the gradient at the current position.");
00042 DefineParameterMacro(SPSAOptimizerController,ConvergenceDecayRate,"ConvergenceDecayRate","The convergence value (magnitute of the gradient) will be multiplied every iteration step with this factor.");
00043 DefineParameterMacro(SPSAOptimizerController,Tolerance,"Tolerance","if the convergence value is below the tolerance the optimizer will terminate.");
00044 DefineParameterMacro(SPSAOptimizerController,GuessParameters,"GuessParameters","Indicates if the parameters a and A will be guessed (in this case any given value for both will be ignored).");
00045 DefineParameterMacro(SPSAOptimizerController,Guess_GradientEstimates,"Guess_GradientEstimates","Number of gradient estimations used to guess the parameters.");
00046 DefineParameterMacro(SPSAOptimizerController,Guess_InitialStepSize,"Guess_InitialStepSize","Maximum of the absolute values of the parameter update.");
00047 
00048 SPSAOptimizerController::
00049 SPSAOptimizerController()
00050 {
00051   //Profile settings
00052   this->UpdateControllerID(ControllerID::SPSAOptimizerController);
00053   this->m_Description = "Optimizes by using a SPSA optimizer with Brent line search.";
00054         
00055 };
00056 
00057 void
00058 SPSAOptimizerController::
00059 GenerateProfile(CtrlProfile::ControllerProfile& profile,
00060                 const SessionComponentCache* pComponentCache,
00061                 bool bRegardOldSetup) const
00062 {
00063   Superclass::GenerateProfile(profile,pComponentCache,bRegardOldSetup);
00064 
00065         //Parameters
00066   profile.Parameters().AddParameter(cParam_MinimumNumberOfIteration,Parameter::PVTULong,cParamDsc_MinimumNumberOfIteration,1,"10",-1,true);
00067   profile.Parameters().AddParameter(cParam_MaximumNumberOfIteration,Parameter::PVTULong,cParamDsc_MaximumNumberOfIteration,1,"100",-1,true);
00068   profile.Parameters().AddParameter(cParam_a,Parameter::PVTDouble,cParamDsc_a,1,"1.0",-1,true);
00069   profile.Parameters().AddParameter(cParam_A,Parameter::PVTDouble,cParamDsc_A,1,"10",-1,true);
00070   profile.Parameters().AddParameter(cParam_c,Parameter::PVTDouble,cParamDsc_c,1,"1.0",-1,true);
00071   profile.Parameters().AddParameter(cParam_Alpha,Parameter::PVTDouble,cParamDsc_Alpha,1,"0.602",-1,true);
00072   profile.Parameters().AddParameter(cParam_Gamma,Parameter::PVTDouble,cParamDsc_Gamma,1,"0.101",-1,true);
00073   profile.Parameters().AddParameter(cParam_NumberOfPertubations,Parameter::PVTLong,cParamDsc_NumberOfPertubations,1,"1",-1,true);
00074   profile.Parameters().AddParameter(cParam_ConvergenceDecayRate,Parameter::PVTDouble,cParamDsc_ConvergenceDecayRate,1,"0.9",-1,true);
00075   profile.Parameters().AddParameter(cParam_Tolerance,Parameter::PVTDouble,cParamDsc_Tolerance,1,"1e-06",-1,true);
00076         profile.Parameters().AddParameter(cParam_GuessParameters,Parameter::PVTBool,cParamDsc_GuessParameters,1,"false",1);
00077   profile.Parameters().AddParameter(cParam_Guess_GradientEstimates,Parameter::PVTULong,cParamDsc_Guess_GradientEstimates,1,"2",-1,true);
00078   profile.Parameters().AddParameter(cParam_Guess_InitialStepSize,Parameter::PVTDouble,cParamDsc_Guess_InitialStepSize,1,"1.0",-1,true);
00079 };
00080 
00081 void
00082 SPSAOptimizerController::
00083 ActualizeMainComponent(ComponentType* pMainComponent,
00084                        SessionComponentCache* pComponentCache, SessionInfo* pSessionInfo,
00085                                                                                          const unsigned int& iActLevel) const
00086 {
00087         unsigned long lMinIterations;
00088         unsigned long lMaxIterations;
00089   double da;
00090   double dA;
00091   double dc;
00092   double dAlpha;
00093   double dGamma;
00094         long lNrOfPertubations;
00095   double dDecayRate;
00096         double dTolerance;
00097   
00098   try
00099   {
00100     SessionAccessor::GetParameterValue(pComponentCache,cParam_MinimumNumberOfIteration,lMinIterations,0,iActLevel,true);
00101     SessionAccessor::GetParameterValue(pComponentCache,cParam_MaximumNumberOfIteration,lMaxIterations,0,iActLevel,true);
00102     SessionAccessor::GetParameterValue(pComponentCache,cParam_a,da,0,iActLevel,true);
00103     SessionAccessor::GetParameterValue(pComponentCache,cParam_A,dA,0,iActLevel,true);
00104     SessionAccessor::GetParameterValue(pComponentCache,cParam_c,dc,0,iActLevel,true);
00105     SessionAccessor::GetParameterValue(pComponentCache,cParam_Alpha,dAlpha,0,iActLevel,true);
00106     SessionAccessor::GetParameterValue(pComponentCache,cParam_Gamma,dGamma,0,iActLevel,true);
00107     SessionAccessor::GetParameterValue(pComponentCache,cParam_NumberOfPertubations,lNrOfPertubations,0,iActLevel,true);
00108     SessionAccessor::GetParameterValue(pComponentCache,cParam_ConvergenceDecayRate,dDecayRate,0,iActLevel,true);
00109     SessionAccessor::GetParameterValue(pComponentCache,cParam_Tolerance,dTolerance,0,iActLevel,true);
00110   }
00111   catchAllNPassMacro("Error while retrieving parameter values.");
00112 
00113   ParameterArrayType scales = this->GetTransformScales(pComponentCache,iActLevel);
00114   pMainComponent->SetScales(scales);
00115   
00116   pMainComponent->SetMinimumNumberOfIterations(lMinIterations);
00117         pMainComponent->SetMaximumNumberOfIterations(lMaxIterations);
00118         pMainComponent->Seta(da);
00119         pMainComponent->SetA(dA);
00120         pMainComponent->Setc(dc);
00121         pMainComponent->SetAlpha(dAlpha);
00122         pMainComponent->SetGamma(dGamma);
00123         pMainComponent->SetNumberOfPerturbations(lNrOfPertubations);
00124         pMainComponent->SetStateOfConvergenceDecayRate(dDecayRate);
00125         pMainComponent->SetTolerance(dTolerance);
00126   
00127   Parameter::Pointer smpDirection = pComponentCache->GetParentCache()->Controller()->GetParameter(pComponentCache->GetParentCache(),OptimizerOwnerControllerInterface::cParam_MinimizeToOptimize);
00128   if (smpDirection.IsNull()) throwCtrlExceptionMacro("","Cannot retrieve optimization direction via optimizer owner. Parameter \"MinimizeToOptimize\" is unknown. Please ensure valid session and setup");
00129   bool bMinimize;
00130   smpDirection->GetParameterValue(bMinimize);
00131   pMainComponent->SetMaximize( !bMinimize);
00132 };
00133 
00134 void
00135 SPSAOptimizerController::
00136 SetStatisticEntryMainComponent(StatisticEntry& rStatisticEntry,
00137                                ComponentType* pMainComponent,
00138                                SessionComponentCache* pMainComponentCache,
00139                                SessionInfo* pSessionInfo,
00140                                StatisticDictionary& rDictionary) const
00141 {
00142   Superclass::SetStatisticEntryMainComponent(rStatisticEntry,pMainComponent,
00143                                             pMainComponentCache,pSessionInfo,
00144                                             rDictionary);
00145   
00146   std::string sName = "LearningRate";
00147   std::string sIDPath = pMainComponentCache->GetIDPath();
00148   StatisticValueDefinition* pEntry = rDictionary.GetValueDefinitionByName(sIDPath, sName);
00149     
00150   if (!pEntry) //Entry is not recorded yet, so do so.
00151   {
00152     pEntry = rDictionary.AddValueDefinition(sIDPath,sName,"The current a_k");
00153     rDictionary.AddValueDefinition(sIDPath,"GradientMagnitude","GradientMagnitude of the latest computed gradient.");
00154     rDictionary.AddValueDefinition(sIDPath,"StateOfConvergence","Get the state of convergence in the last iteration. When the StateOfConvergence is lower than the Tolerance the optimization stops.");
00155     rDictionary.AddValueDefinition(sIDPath,"OptimizerValue","Value of the Optimizer");
00156   }
00157 
00158   rStatisticEntry.AddValue(Convert::ToStr(pMainComponent->GetLearningRate()),pEntry->GetRefID());
00159   rStatisticEntry.AddValue(Convert::ToStr(pMainComponent->GetGradientMagnitude()),pEntry->GetRefID()+1);
00160   rStatisticEntry.AddValue(Convert::ToStr(pMainComponent->GetStateOfConvergence()),pEntry->GetRefID()+2);
00161   rStatisticEntry.AddValue(Convert::ToStr(pMainComponent->GetValue()),pEntry->GetRefID()+3);
00162 };
00163 
00164 void
00165 SPSAOptimizerController::
00166 ActualizeFinalization(ComponentType* pMainComponent, SessionComponentCache* pComponentCache,
00167                       SessionInfo* pSessionInfo, const unsigned int& iActLevel) const
00168 {
00169   if (!pComponentCache->SetupIsAssigned()) throwCtrlExceptionMacro("","Error. Cannot finalize component actualization; setup is missing in cache.");
00170   ComponentSetup* pComponentSetup = pComponentCache->Setup();
00171 
00172   // now all subcomponents are build and setup with there parameters, so parameters of spsa can be guessed if wanted.
00173   bool bGuess;
00174         unsigned long lGuess_NrOfEstimates;
00175         double dGuess_StepSize;
00176   
00177   try
00178   {
00179     SessionAccessor::GetParameterValue(pComponentCache,cParam_GuessParameters,bGuess);
00180     SessionAccessor::GetParameterValue(pComponentCache,cParam_Guess_GradientEstimates,lGuess_NrOfEstimates);
00181     SessionAccessor::GetParameterValue(pComponentCache,cParam_Guess_InitialStepSize,dGuess_StepSize);
00182   }
00183   catchAllNPassMacro("Error while retrieving parameter values.");
00184 
00185         if (bGuess)
00186         {
00187                 pMainComponent->GuessParameters(lGuess_NrOfEstimates,dGuess_StepSize);
00188         }
00189 };
00190 
00191 SPSAOptimizerController::MeasuresType
00192 SPSAOptimizerController::
00193 GetCurrentValue(ComponentType* pOptimizer) const
00194 {
00195         MeasuresType values(1);
00196         values.Fill(pOptimizer->GetValue());
00197         return values;
00198 };
00199 
00200 } //end of namespace free

Generated at Sat Oct 13 17:41:41 2007 for f.r.e.e. - Flexible Registration and Evaluation Engine by doxygen 1.5.3 written by Dimitri van Heesch, © 1997-2000