00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include "freSPSASOOptimizerController.h"
00024 #include "freSPSAOptimizerController.h"
00025 #include "freExceptions.h"
00026
00027 namespace FREE
00028 {
00029
00033
00034
00035
00036 DefineParameterMacro(SPSASOOptimizerController,MinimumNumberOfIteration,"MinimumNumberOfIteration","Minimum number of iteration the optimizer will compute.");
00037 DefineParameterMacro(SPSASOOptimizerController,MaximumNumberOfIteration,"MaximumNumberOfIteration","Maximum number of iterations the optimizer will compute before terminating, even if no convergence is achieved.");
00038 DefineParameterMacro(SPSASOOptimizerController,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.");
00039 DefineParameterMacro(SPSASOOptimizerController,A,"A","A is a non-negative coefficient used to calculate the a of the next iteration step. Can be estimated via GuessParameters.");
00040 DefineParameterMacro(SPSASOOptimizerController,c,"c","c is a factor that scales the pertubation vector, which will be added to the current position to estimate the gradient");
00041 DefineParameterMacro(SPSASOOptimizerController,Alpha,"Alpha","Alpha is used to calculate the gain sequence a k.");
00042 DefineParameterMacro(SPSASOOptimizerController,Gamma,"Gamma","Gamma is used to calculate the gain sequence c k.");
00043 DefineParameterMacro(SPSASOOptimizerController,NumberOfPertubations,"NumberOfPertubations","Number of pertubations used to estimate the gradient at the current position.");
00044 DefineParameterMacro(SPSASOOptimizerController,ConvergenceDecayRate,"ConvergenceDecayRate","The convergence value (magnitute of the gradient) will be multiplied every iteration step with this factor.");
00045 DefineParameterMacro(SPSASOOptimizerController,Tolerance,"Tolerance","if the convergence value is below the tolerance the optimizer will terminate.");
00046 DefineParameterMacro(SPSASOOptimizerController,GuessParameters,"GuessParameters","Indicates if the parameters a and A will be guessed (in this case any given value for both will be ignored).");
00047 DefineParameterMacro(SPSASOOptimizerController,Guess_GradientEstimates,"Guess_GradientEstimates","Number of gradient estimations used to guess the parameters.");
00048 DefineParameterMacro(SPSASOOptimizerController,Guess_InitialStepSize,"Guess_InitialStepSize","Maximum of the absolute values of the parameter update.");
00049 DefineParameterMacro(SPSASOOptimizerController,ValueUpdateRate,"ValueUpdateRate","Because the value of the current position is not calculated explicitly by SPSA, Updating the actual optimizer value cost the evaluation of the objective function. Hence it can be adjusted how often the value should be updated (1 = every step; 5 = every fifth step etc.)");
00050
00051 SPSASOOptimizerController::
00052 SPSASOOptimizerController()
00053 {
00054
00055 this->UpdateControllerID(ControllerID::SPSASOOptimizerController);
00056 this->m_Description = "Optimizes registration setups by SPSA optimizer approach using Brent line search.";
00057 };
00058
00059 void
00060 SPSASOOptimizerController::
00061 GenerateProfile(CtrlProfile::ControllerProfile& profile,
00062 const SessionComponentCache* pComponentCache,
00063 bool bRegardOldSetup) const
00064 {
00065 Superclass::GenerateProfile(profile,pComponentCache,bRegardOldSetup);
00066
00067
00068 profile.Parameters().AddParameter(cParam_MinimumNumberOfIteration,Parameter::PVTULong,cParamDsc_MinimumNumberOfIteration,1,"10",-1,true);
00069 profile.Parameters().AddParameter(cParam_MaximumNumberOfIteration,Parameter::PVTULong,cParamDsc_MaximumNumberOfIteration,1,"100",-1,true);
00070 profile.Parameters().AddParameter(cParam_ValueUpdateRate,Parameter::PVTLong,cParamDsc_ValueUpdateRate,1,"10",-1,true);
00071 profile.Parameters().AddParameter(cParam_a,Parameter::PVTDouble,cParamDsc_a,1,"1.0",-1,true);
00072 profile.Parameters().AddParameter(cParam_A,Parameter::PVTDouble,cParamDsc_A,1,"10",-1,true);
00073 profile.Parameters().AddParameter(cParam_c,Parameter::PVTDouble,cParamDsc_c,1,"1.0",-1,true);
00074 profile.Parameters().AddParameter(cParam_Alpha,Parameter::PVTDouble,cParamDsc_Alpha,1,"0.602",-1,true);
00075 profile.Parameters().AddParameter(cParam_Gamma,Parameter::PVTDouble,cParamDsc_Gamma,1,"0.101",-1,true);
00076 profile.Parameters().AddParameter(cParam_NumberOfPertubations,Parameter::PVTLong,cParamDsc_NumberOfPertubations,1,"1",-1,true);
00077 profile.Parameters().AddParameter(cParam_ConvergenceDecayRate,Parameter::PVTDouble,cParamDsc_ConvergenceDecayRate,1,"0.9",-1,true);
00078 profile.Parameters().AddParameter(cParam_Tolerance,Parameter::PVTDouble,cParamDsc_Tolerance,1,"1e-06",-1,true);
00079 profile.Parameters().AddParameter(cParam_GuessParameters,Parameter::PVTBool,cParamDsc_GuessParameters,1,"false",1);
00080 profile.Parameters().AddParameter(cParam_Guess_GradientEstimates,Parameter::PVTULong,cParamDsc_Guess_GradientEstimates,1,"2",-1,true);
00081 profile.Parameters().AddParameter(cParam_Guess_InitialStepSize,Parameter::PVTDouble,cParamDsc_Guess_InitialStepSize,1,"1.0",-1,true);
00082 };
00083
00084 long
00085 SPSASOOptimizerController::
00086 GetMaxIterationCount(const SessionComponentCache* pComponentCache, unsigned int iResolutionLevel) const
00087 {
00088 if (!pComponentCache) throwCtrlExceptionMacro("","Passed pComponentCache is NULL.");
00089 if (!pComponentCache->SetupIsAssigned()) throwCtrlExceptionMacro("","Cache has no setup assigned.");
00090
00091 long lResult = 1;
00092 try
00093 {
00094 SessionAccessor::GetParameterValue(pComponentCache,cParam_Iterations,lResult);
00095 }
00096 catchAllNPassMacro("Unknown error while retrieving max interation count.")
00097
00098 return lResult;
00099 };
00100
00101 void
00102 SPSASOOptimizerController::
00103 ActualizeMainComponent(ComponentType* pMainComponent,
00104 SessionComponentCache* pComponentCache, SessionInfo* pSessionInfo,
00105 const unsigned int& iActLevel) const
00106 {
00107 Superclass::ActualizeMainComponent(pMainComponent, pComponentCache,
00108 pSessionInfo, iActLevel);
00109
00110 unsigned long lMinIterations;
00111 unsigned long lMaxIterations;
00112 long lValueUpdateRate;
00113 double da;
00114 double dA;
00115 double dc;
00116 double dAlpha;
00117 double dGamma;
00118 long lNrOfPertubations;
00119 double dDecayRate;
00120 double dTolerance;
00121
00122 try
00123 {
00124 SessionAccessor::GetParameterValue(pComponentCache,cParam_ValueUpdateRate,lValueUpdateRate,0,iActLevel,true);
00125 SessionAccessor::GetParameterValue(pComponentCache,cParam_MinimumNumberOfIteration,lMinIterations,0,iActLevel,true);
00126 SessionAccessor::GetParameterValue(pComponentCache,cParam_MaximumNumberOfIteration,lMaxIterations,0,iActLevel,true);
00127 SessionAccessor::GetParameterValue(pComponentCache,cParam_a,da,0,iActLevel,true);
00128 SessionAccessor::GetParameterValue(pComponentCache,cParam_A,dA,0,iActLevel,true);
00129 SessionAccessor::GetParameterValue(pComponentCache,cParam_c,dc,0,iActLevel,true);
00130 SessionAccessor::GetParameterValue(pComponentCache,cParam_Alpha,dAlpha,0,iActLevel,true);
00131 SessionAccessor::GetParameterValue(pComponentCache,cParam_Gamma,dGamma,0,iActLevel,true);
00132 SessionAccessor::GetParameterValue(pComponentCache,cParam_NumberOfPertubations,lNrOfPertubations,0,iActLevel,true);
00133 SessionAccessor::GetParameterValue(pComponentCache,cParam_ConvergenceDecayRate,dDecayRate,0,iActLevel,true);
00134 SessionAccessor::GetParameterValue(pComponentCache,cParam_Tolerance,dTolerance,0,iActLevel,true);
00135 }
00136 catchAllNPassMacro("Error while retrieving parameter values.");
00137
00138 pMainComponent->SetMinimumNumberOfIterations(lMinIterations);
00139 pMainComponent->SetMaximumNumberOfIterations(lMaxIterations);
00140 pMainComponent->Seta(da);
00141 pMainComponent->SetA(dA);
00142 pMainComponent->Setc(dc);
00143 pMainComponent->SetAlpha(dAlpha);
00144 pMainComponent->SetGamma(dGamma);
00145 pMainComponent->SetNumberOfPerturbations(lNrOfPertubations);
00146 pMainComponent->SetStateOfConvergenceDecayRate(dDecayRate);
00147 pMainComponent->SetTolerance(dTolerance);
00148 pMainComponent->SetValueUpdateRate(lValueUpdateRate);
00149
00150
00151 Parameter::Pointer param = SessionAccessor::GetParameterByIDPath(pComponentCache,cIDPParent+IDPath(cComp_MainMetric+std::string("/@")+std::string(cParam_MetricMinimize)));
00152 bool bMin = true;
00153 if (param.IsNotNull())
00154 {
00155 param->GetParameterValue(bMin);
00156 }
00157 pMainComponent->SetMaximize(!bMin);
00158 };
00159
00160 void
00161 SPSASOOptimizerController::
00162 SetStatisticEntryMainComponent(StatisticEntry& rStatisticEntry,
00163 ComponentType* pMainComponent,
00164 SessionComponentCache* pMainComponentCache,
00165 SessionInfo* pSessionInfo,
00166 StatisticDictionary& rDictionary) const
00167 {
00168 ParameterArrayType parameters = pMainComponent->GetCurrentPosition();
00169
00170 std::string sName = "Position #";
00171 std::string sIDPath = pMainComponentCache->GetIDPath();
00172 std::string sCommment = "Optimizer current position. Meaning depends on chosen transformation";
00173 StatisticValueDefinition* pEntry = rDictionary.GetValueDefinitionByName(sIDPath,sName+"0");
00174
00175 if (!pEntry)
00176 {
00177 std::string sName = "Position #";
00178 pEntry = rDictionary.AddValueDefinition(sIDPath,sName+"0", sCommment);
00179 for (unsigned int i = 1; i<parameters.Size(); i++)
00180 {
00181 rDictionary.AddValueDefinition(sIDPath,sName+Convert::ToStr(i),sCommment);
00182 }
00183 rDictionary.AddValueDefinition(sIDPath,"LearningRate","The current a_k");
00184 rDictionary.AddValueDefinition(sIDPath,"GradientMagnitude","GradientMagnitude of the latest computed gradient.");
00185 rDictionary.AddValueDefinition(sIDPath,"StateOfConvergence","Get the state of convergence in the last iteration. When the StateOfConvergence is lower than the Tolerance the optimization stops.");
00186 rDictionary.AddValueDefinition(sIDPath,"OptimizerValue","Composed value of the current optimizer position");
00187 }
00188
00189 for (unsigned int i = 0; i<parameters.Size(); i++)
00190 {
00191 rStatisticEntry.AddValue(Convert::ToStr(parameters.GetElement(i)),pEntry->GetRefID()+i);
00192 }
00193
00194 rStatisticEntry.AddValue(Convert::ToStr(pMainComponent->GetLearningRate()),pEntry->GetRefID()+parameters.Size());
00195 rStatisticEntry.AddValue(Convert::ToStr(pMainComponent->GetGradientMagnitude()),pEntry->GetRefID()+parameters.Size()+1);
00196 rStatisticEntry.AddValue(Convert::ToStr(pMainComponent->GetStateOfConvergence()),pEntry->GetRefID()+parameters.Size()+2);
00197 rStatisticEntry.AddValue(Convert::ToStr(pMainComponent->GetCurrentValue()),pEntry->GetRefID()+parameters.Size()+3);
00198 };
00199
00200 void
00201 SPSASOOptimizerController::
00202 ActualizeFinalization(ComponentType* pMainComponent, SessionComponentCache* pComponentCache,
00203 SessionInfo* pSessionInfo, const unsigned int& iActLevel) const
00204 {
00205 if (!pComponentCache->SetupIsAssigned()) throwCtrlExceptionMacro("","Error. Cannot finalize component actualization; setup is missing in cache.");
00206 ComponentSetup* pComponentSetup = pComponentCache->Setup();
00207
00208
00209 bool bGuess;
00210 unsigned long lGuess_NrOfEstimates;
00211 double dGuess_StepSize;
00212
00213 try
00214 {
00215 SessionAccessor::GetParameterValue(pComponentCache,cParam_GuessParameters,bGuess);
00216 SessionAccessor::GetParameterValue(pComponentCache,cParam_Guess_GradientEstimates,lGuess_NrOfEstimates);
00217 SessionAccessor::GetParameterValue(pComponentCache,cParam_Guess_InitialStepSize,dGuess_StepSize);
00218 }
00219 catchAllNPassMacro("Error while retrieving parameter values.");
00220
00221 if (bGuess)
00222 {
00223 pMainComponent->GuessParameters(lGuess_NrOfEstimates,dGuess_StepSize);
00224 }
00225 };
00226
00227 }