AutomaticParameterTuner.cpp

00001 #include "AutomaticParameterTuner.h"
00002 
00003 extern StreamOutput cout;
00004 
00008 AutomaticParameterTuner::AutomaticParameterTuner()
00009 {
00010     // first enable both optimizers
00011     m_optimizeProbeRMSE = true;
00012     m_optimizeBlendRMSE = true;
00013 
00014     m_expSearchMaxEpochsBlend = -1;
00015 
00016     m_enableDebug = true;
00017 
00018     m_epochParamBreak = false;
00019 }
00020 
00024 AutomaticParameterTuner::~AutomaticParameterTuner()
00025 {
00026 }
00027 
00035 void AutomaticParameterTuner::addEpochParameter ( int *param, string name )
00036 {
00037     m_epochParam.push_back ( param );
00038     m_epochName.push_back ( name );
00039 }
00040 
00049 void AutomaticParameterTuner::addIntegerParameter ( int *param, string name, int min, int max )
00050 {
00051     m_intParam.push_back ( param );
00052     m_intMin.push_back ( min );
00053     m_intMax.push_back ( max );
00054     m_intName.push_back ( name );
00055 }
00056 
00065 void AutomaticParameterTuner::addDoubleParameter ( double *param, string name, double min, double max )
00066 {
00067     m_doubleParam.push_back ( param );
00068     m_doubleMin.push_back ( min );
00069     m_doubleMax.push_back ( max );
00070     m_doubleName.push_back ( name );
00071 }
00072 
00078 void AutomaticParameterTuner::removeEpochParameter ( string name )
00079 {
00080     int pos = -1;
00081     for ( int i=0;i<m_epochName.size();i++ )
00082         if ( m_epochName[i] == name )
00083             pos = i;
00084     if ( pos != -1 )
00085     {
00086         //cout<<"Remove epoch parameter:"<<name<<endl;
00087         m_epochName.erase ( m_epochName.begin() +pos );
00088         m_epochParam.erase ( m_epochParam.begin() +pos );
00089     }
00090     else
00091         cout<<"Warning: epoch parameter:"<<name<<" cannot be removed"<<endl;
00092 }
00093 
00099 void AutomaticParameterTuner::removeIntegerParameter ( string name )
00100 {
00101     int pos = -1;
00102     for ( int i=0;i<m_intName.size();i++ )
00103         if ( m_intName[i] == name )
00104             pos = i;
00105     if ( pos != -1 )
00106     {
00107         //cout<<"Remove int parameter:"<<name<<endl;
00108         m_intName.erase ( m_intName.begin() +pos );
00109         m_intParam.erase ( m_intParam.begin() +pos );
00110         m_intMin.erase ( m_intMin.begin() +pos );
00111         m_intMax.erase ( m_intMax.begin() +pos );
00112     }
00113     else
00114         cout<<"Warning: int parameter:"<<name<<" cannot be removed"<<endl;
00115 }
00116 
00122 void AutomaticParameterTuner::removeDoubleParameter ( string name )
00123 {
00124     int pos = -1;
00125     for ( int i=0;i<m_doubleName.size();i++ )
00126         if ( m_doubleName[i] == name )
00127             pos = i;
00128     if ( pos != -1 )
00129     {
00130         //cout<<"Remove double parameter:"<<name<<endl;
00131         m_doubleName.erase ( m_doubleName.begin() +pos );
00132         m_doubleParam.erase ( m_doubleParam.begin() +pos );
00133         m_doubleMin.erase ( m_doubleMin.begin() +pos );
00134         m_doubleMax.erase ( m_doubleMax.begin() +pos );
00135     }
00136     else
00137         cout<<"Warning: double parameter:"<<name<<" cannot be removed"<<endl;
00138 }
00139 
00151 void AutomaticParameterTuner::simpleStochasticParameterFinder ( double minProbeImpro, int maxProbeEpochsWithoutImpro, double minBlendImpro, int maxBlendEpochsWithoutImpro, double stdDev )
00152 {
00153     vector<double> bestDoubleParam;
00154     vector<int> bestIntParam;
00155 
00156     bestDoubleParam.resize ( m_doubleParam.size() );
00157     for ( int i=0; i < m_doubleParam.size(); i++ )
00158         bestDoubleParam[i] = *m_doubleParam[i];
00159     bestIntParam.resize ( m_intParam.size() );
00160     for ( int i=0; i < m_intParam.size(); i++ )
00161         bestIntParam[i] = *m_intParam[i];
00162 
00163 
00164     int cnt=0;
00165     double bestRmse = 10.0;
00166 
00167     if ( m_optimizeProbeRMSE == true )
00168     {
00169         while ( cnt < maxProbeEpochsWithoutImpro )
00170         {
00171             for ( int i=0; i < m_doubleParam.size(); i++ )
00172                 *m_doubleParam[i] = bestDoubleParam[i];
00173             for ( int i=0; i < m_intParam.size(); i++ )
00174                 *m_intParam[i] = bestIntParam[i];
00175 
00176             long ticks = clock();
00177             int sel = rand() % ( m_doubleParam.size() + m_intParam.size() );
00178 
00179             if ( sel < m_doubleParam.size() )
00180             {
00181                 *m_doubleParam[sel] = ( double ) NumericalTools::getNormRandomNumber ( bestDoubleParam[sel], max ( fabs ( bestDoubleParam[sel] ) * stdDev, 0.001 ) );
00182                 *m_doubleParam[sel] = NumericalTools::clipValue ( *m_doubleParam[sel], m_doubleMin[sel], m_doubleMax[sel] );
00183             }
00184             else
00185             {
00186                 sel -= m_doubleParam.size();
00187 
00188                 *m_intParam[sel] = ( int ) NumericalTools::getNormRandomNumber ( ( double ) bestIntParam[sel], max ( fabs ( ( double ) bestIntParam[sel] ) * stdDev, 1.0 ) );
00189 
00190                 if ( *m_intParam[sel] < m_intMin[sel] )
00191                     *m_intParam[sel] = m_intMin[sel];
00192                 if ( *m_intParam[sel] > m_intMax[sel] )
00193                     *m_intParam[sel] = m_intMax[sel];
00194             }
00195 
00196 
00197             double rmse = calcRMSEonProbe();
00198 
00199             if ( rmse < bestRmse )
00200             {
00201                 if ( bestRmse - rmse > minProbeImpro )
00202                 {
00203                     cout<<"*";
00204                     cnt=0;
00205                 }
00206 
00207                 bestRmse = rmse;
00208                 for ( int i=0; i < m_doubleParam.size(); i++ )
00209                     bestDoubleParam[i] = *m_doubleParam[i];
00210                 for ( int i=0; i < m_intParam.size(); i++ )
00211                     bestIntParam[i] = *m_intParam[i];
00212                 cout<<"* ";
00213             }
00214 
00215             ticks = clock() - ticks;
00216 
00217             cnt++;
00218 
00219             // output
00220             cout<< ( float ) ticks / ( float ) CLOCKS_PER_SEC<<" s | ERR: "<<rmse;
00221             for ( int i=0; i < m_doubleParam.size(); i++ )
00222                 cout<<" | "<<m_doubleName[i]<<": "<<*m_doubleParam[i];
00223             for ( int i=0; i < m_intParam.size(); i++ )
00224                 cout<<" | "<<m_intName[i]<<": "<<*m_intParam[i];
00225             cout<<endl;
00226         }
00227 
00228         for ( int i=0; i < m_doubleParam.size(); i++ )
00229             *m_doubleParam[i] = bestDoubleParam[i];
00230         for ( int i=0; i < m_intParam.size(); i++ )
00231             *m_intParam[i] = bestIntParam[i];
00232 
00233         cout<<"bestParameters on Probe: ERR: "<<bestRmse<<" ";
00234         for ( int i=0; i < m_doubleParam.size(); i++ )
00235             cout<<" | "<<m_doubleName[i]<<": "<<*m_doubleParam[i];
00236         for ( int i=0; i < m_intParam.size(); i++ )
00237             cout<<" | "<<m_intName[i]<<": "<<*m_intParam[i];
00238         cout<<endl;
00239     }
00240 
00241 
00242 
00243     // ============== find the best Parameters on the blend =================
00244     cnt=0;
00245     bestRmse = 10.0;
00246     if ( m_optimizeBlendRMSE == true )
00247     {
00248         while ( cnt < maxBlendEpochsWithoutImpro )
00249         {
00250             for ( int i=0; i < m_doubleParam.size(); i++ )
00251                 *m_doubleParam[i] = bestDoubleParam[i];
00252             for ( int i=0; i < m_intParam.size(); i++ )
00253                 *m_intParam[i] = bestIntParam[i];
00254 
00255             long ticks = clock();
00256             int sel = rand() % ( m_doubleParam.size() + m_intParam.size() );
00257 
00258             if ( sel < m_doubleParam.size() )
00259             {
00260                 *m_doubleParam[sel] = ( double ) NumericalTools::getNormRandomNumber ( bestDoubleParam[sel], max ( fabs ( bestDoubleParam[sel] ) * stdDev, 0.001 ) );
00261                 *m_doubleParam[sel] = NumericalTools::clipValue ( *m_doubleParam[sel], m_doubleMin[sel], m_doubleMax[sel] );
00262             }
00263             else
00264             {
00265                 sel -= m_doubleParam.size();
00266 
00267                 *m_intParam[sel] = ( int ) NumericalTools::getNormRandomNumber ( ( double ) bestIntParam[sel], max ( fabs ( ( double ) bestIntParam[sel] ) * stdDev, 1.0 ) );
00268 
00269                 if ( *m_intParam[sel] < m_intMin[sel] )
00270                     *m_intParam[sel] = m_intMin[sel];
00271                 if ( *m_intParam[sel] > m_intMax[sel] )
00272                     *m_intParam[sel] = m_intMax[sel];
00273             }
00274 
00275 
00276             double rmse = calcRMSEonBlend();
00277 
00278             if ( rmse < bestRmse )
00279             {
00280                 if ( bestRmse - rmse > minBlendImpro )
00281                 {
00282                     cout<<"*";
00283                     cnt=0;
00284                 }
00285 
00286                 bestRmse = rmse;
00287                 for ( int i=0; i < m_doubleParam.size(); i++ )
00288                     bestDoubleParam[i] = *m_doubleParam[i];
00289                 for ( int i=0; i < m_intParam.size(); i++ )
00290                     bestIntParam[i] = *m_intParam[i];
00291                 cout<<"* ";
00292             }
00293 
00294             ticks = clock() - ticks;
00295 
00296             cnt++;
00297 
00298             // output
00299             cout<< ( float ) ticks / ( float ) CLOCKS_PER_SEC<<" s | ERR: "<<rmse;
00300             for ( int i=0; i < m_doubleParam.size(); i++ )
00301                 cout<<" | "<<m_doubleName[i]<<": "<<*m_doubleParam[i];
00302             for ( int i=0; i < m_intParam.size(); i++ )
00303                 cout<<" | "<<m_intName[i]<<": "<<*m_intParam[i];
00304             cout<<endl;
00305         }
00306 
00307         for ( int i=0; i < m_doubleParam.size(); i++ )
00308             *m_doubleParam[i] = bestDoubleParam[i];
00309         for ( int i=0; i < m_intParam.size(); i++ )
00310             *m_intParam[i] = bestIntParam[i];
00311 
00312         cout<<"bestParameters on Blend: ERR: "<<bestRmse<<" ";
00313         for ( int i=0; i < m_doubleParam.size(); i++ )
00314             cout<<" | "<<m_doubleName[i]<<": "<<*m_doubleParam[i];
00315         for ( int i=0; i < m_intParam.size(); i++ )
00316             cout<<" | "<<m_intName[i]<<": "<<*m_intParam[i];
00317         cout<<endl;
00318     }
00319 }
00320 
00326 void AutomaticParameterTuner::setOptimizeProbeRmse ( bool enable )
00327 {
00328     m_optimizeProbeRMSE = enable;
00329 }
00330 
00336 void AutomaticParameterTuner::setOptimizeBlendRmse ( bool enable )
00337 {
00338     m_optimizeBlendRMSE = enable;
00339 }
00340 
00346 void AutomaticParameterTuner::setDebug ( bool en )
00347 {
00348     m_enableDebug = en;
00349     //cout<<"Debug: "<<m_enableDebug<<endl;
00350 }
00351 
00362 void AutomaticParameterTuner::expSearchParams ( int minEpochs, int maxEpochs, int paramEpochs, int accelerationEpochs, double expInit )
00363 {
00364     m_expSearchMinEpochs = minEpochs;
00365     m_expSearchMaxEpochs = maxEpochs;
00366     m_expSearchParamEpochs = paramEpochs;
00367     m_expSearchParamAccelerationEpochs = accelerationEpochs;
00368     m_expSearchEpoch = 0;
00369     m_expSearchVariationCnt = 0;
00370 
00371     m_epochParamPos = 0;
00372     m_expSearchDoubleParamPos = 0;
00373     m_expSearchIntParamPos = 0;
00374     m_expSearchErrorBest = 1e10;
00375     m_expSearchAcceleration = 0.8;
00376     m_expSearchAccelerationEpoch = 0;
00377 
00378     m_epochParamBest.clear();
00379     m_expSearchExponent.clear();
00380     m_expSearchDoubleParamBest.clear();
00381     m_expSearchIntParamBest.clear();
00382     m_expSearchParamDirection.clear();
00383 
00384     m_expInit = expInit;
00385 
00386     for ( int i=0;i<m_epochParam.size();i++ )
00387         m_epochParamBest.push_back ( *m_epochParam[i] );
00388     for ( int i=0;i<m_doubleParam.size();i++ )
00389     {
00390         m_expSearchExponent.push_back ( expInit );
00391         m_expSearchParamDirection.push_back ( false );
00392         m_expSearchDoubleParamBest.push_back ( *m_doubleParam[i] );
00393     }
00394     for ( int i=0;i<m_intParam.size();i++ )
00395     {
00396         m_expSearchExponent.push_back ( expInit );
00397         m_expSearchParamDirection.push_back ( false );
00398         m_expSearchIntParamBest.push_back ( *m_intParam[i] );
00399     }
00400 }
00401 
00407 bool AutomaticParameterTuner::expSearchChangeParams()
00408 {
00409     m_expSearchTime = time ( 0 );
00410     m_expSearchEpoch++;
00411 
00412     if ( m_enableDebug )
00413         cout<<"(epoch="<<m_expSearchEpoch-1<<") "<<flush;
00414 
00415     // break training if error rises on epoch tuninig and larger as minEpochs
00416     if ( m_epochParamBreak &&  m_expSearchEpoch >= m_expSearchMinEpochs )
00417     {
00418         if ( m_enableDebug )
00419             cout<<"epoch training error rises. (#minEpochs:"<<m_expSearchMinEpochs<<", )"<<endl;
00420         return false;
00421     }
00422 
00423     // in the first epoch do nothing
00424     if ( m_expSearchEpoch==1 )
00425     {
00426         for ( int i=0;i<m_epochParam.size();i++ )
00427             if ( m_enableDebug )
00428                 cout<<m_epochName[i]<<"="<< ( *m_epochParam[i] ) <<" ";
00429         for ( int i=0;i<m_doubleParam.size();i++ )
00430             if ( m_enableDebug )
00431                 cout<<m_doubleName[i]<<"="<< ( *m_doubleParam[i] ) <<" ";
00432         for ( int i=0;i<m_intParam.size();i++ )
00433             if ( m_enableDebug )
00434                 cout<<m_intName[i]<<"="<< ( *m_intParam[i] ) <<" ";
00435         return true;
00436     }
00437 
00438     // change a epoch parameter
00439     if ( m_epochParamPos < m_epochParam.size() )
00440     {
00441         // do the change
00442         *m_epochParam[m_epochParamPos] = *m_epochParam[m_epochParamPos] + 1;
00443     }
00444 
00445     // change a double parameter
00446     if ( m_expSearchDoubleParamPos < m_doubleParam.size() && m_epochParamPos == m_epochParam.size() )
00447     {
00448         int pos = m_expSearchDoubleParamPos;
00449         double exp = m_expSearchExponent[pos];
00450         bool dir = m_expSearchParamDirection[pos];
00451         double best = m_expSearchDoubleParamBest[pos];
00452 
00453         // do the change
00454         *m_doubleParam[pos] = best * ( dir? ( 1.0/exp ) : exp );
00455 
00456         // check boundaries
00457         if ( *m_doubleParam[pos] > m_doubleMax[pos] )
00458             *m_doubleParam[pos] = m_doubleMax[pos];
00459         if ( *m_doubleParam[pos] < m_doubleMin[pos] )
00460             *m_doubleParam[pos] = m_doubleMin[pos];
00461     }
00462 
00463     // change a int parameter
00464     if ( m_expSearchIntParamPos < m_intParam.size() && m_expSearchDoubleParamPos == m_doubleParam.size() )
00465     {
00466         int pos = m_expSearchIntParamPos;
00467         double exp = m_expSearchExponent[pos + m_doubleParam.size() ];
00468         bool dir = m_expSearchParamDirection[pos + m_doubleParam.size() ];
00469         int best = m_expSearchIntParamBest[pos];
00470 
00471         // do the change
00472         *m_intParam[pos] = ( int ) ( round ( ( double ) ( best ) * ( dir? ( 1.0/exp ) : exp ) ) );
00473 
00474         // if no change, force the change
00475         if ( best == *m_intParam[pos] )
00476             *m_intParam[pos] = dir? best+1 : best-1;
00477 
00478         // check boundaries
00479         if ( *m_intParam[pos] > m_intMax[pos] )
00480             *m_intParam[pos] = m_intMax[pos];
00481         if ( *m_intParam[pos] < m_intMin[pos] )
00482             *m_intParam[pos] = m_intMin[pos];
00483     }
00484 
00485     for ( int i=0;i<m_epochParam.size();i++ )
00486         if ( m_enableDebug )
00487             cout<<m_epochName[i]<<"="<< ( *m_epochParam[i] ) <<" ";
00488     for ( int i=0;i<m_doubleParam.size();i++ )
00489         if ( m_enableDebug )
00490             cout<<m_doubleName[i]<<"="<< ( *m_doubleParam[i] ) <<" ";
00491     for ( int i=0;i<m_intParam.size();i++ )
00492         if ( m_enableDebug )
00493             cout<<m_intName[i]<<"="<< ( *m_intParam[i] ) <<" ";
00494 
00495     // break, if maxEpochs is reached
00496     if ( m_expSearchEpoch > m_expSearchMaxEpochs )
00497     {
00498         m_expSearchEpoch = 0;
00499         // apply best
00500         for ( int i=0;i<m_epochParam.size();i++ )
00501             *m_epochParam[i] = m_epochParamBest[i];
00502         for ( int i=0;i<m_doubleParam.size();i++ )
00503             *m_doubleParam[i] = m_expSearchDoubleParamBest[i];
00504         for ( int i=0;i<m_intParam.size();i++ )
00505             *m_intParam[i] = m_expSearchIntParamBest[i];
00506         if ( m_enableDebug )
00507             cout<<"max. epochs reached."<<endl;
00508         return false;
00509     }
00510 
00511     return true;
00512 }
00513 
00520 void AutomaticParameterTuner::expSearchCheckErr ( double error )
00521 {
00522     if ( m_enableDebug )
00523         cout<<"ERR="<<error;
00524 
00525     if ( m_enableDebug )
00526         cout<<" "<<time ( 0 )-m_expSearchTime<<"[s]";
00527 
00528     // in the first epoch do nothing
00529     if ( m_expSearchEpoch==1 )
00530     {
00531         saveBestPrediction();
00532         for ( int i=0;i<m_epochParam.size();i++ )
00533             m_epochParamBest[i] = *m_epochParam[i];
00534         for ( int i=0;i<m_doubleParam.size();i++ )
00535             m_expSearchDoubleParamBest[i] = *m_doubleParam[i];
00536         for ( int i=0;i<m_intParam.size();i++ )
00537             m_expSearchIntParamBest[i] = *m_intParam[i];
00538         m_expSearchErrorBest = error;
00539         if ( m_enableDebug )
00540             cout<<endl;
00541         return;
00542     }
00543 
00544     // if the error is lower than the old
00545     if ( error<m_expSearchErrorBest )
00546     {
00547         m_expSearchErrorBest = error;
00548         //cout<<"bestUpdate:"<<m_expSearchErrorBest<<" ";
00549 
00550         m_epochParamBreak = 0;
00551 
00552         if ( m_enableDebug )
00553             cout<<" !min! ";
00554         saveBestPrediction();
00555 
00556         // current in a epoch parameter
00557         if ( m_epochParamPos < m_epochParam.size() )
00558         {
00559             m_epochParamBest[m_epochParamPos] = *m_epochParam[m_epochParamPos];
00560         }
00561 
00562         // current in a double parameter
00563         if ( m_expSearchDoubleParamPos < m_doubleParam.size() && m_epochParamPos == m_epochParam.size() )
00564         {
00565             int pos = m_expSearchDoubleParamPos;
00566             double exp = m_expSearchExponent[pos];
00567             bool dir = m_expSearchParamDirection[pos];
00568 
00569             // new best value
00570             m_expSearchDoubleParamBest[pos] = *m_doubleParam[pos];
00571 
00572             // if we go in the right direction, increase step size
00573             if ( m_expSearchAccelerationEpoch >= m_expSearchParamAccelerationEpochs )
00574             {
00575                 if ( m_enableDebug )
00576                     cout<<" accelerate ";
00577                 m_expSearchExponent[pos] = pow ( m_expSearchExponent[pos], 1.0/m_expSearchAcceleration );
00578             }
00579 
00580         }
00581 
00582         // current in a int parameter
00583         if ( m_expSearchIntParamPos < m_intParam.size() && m_expSearchDoubleParamPos == m_doubleParam.size() )
00584         {
00585             int pos = m_expSearchIntParamPos;
00586             double exp = m_expSearchExponent[pos + m_doubleParam.size() ];
00587             bool dir = m_expSearchParamDirection[pos + m_doubleParam.size() ];
00588 
00589             // new best value
00590             m_expSearchIntParamBest[pos] = *m_intParam[pos];
00591 
00592             // if we go in the right direction, increase step size
00593             if ( m_expSearchAccelerationEpoch >= m_expSearchParamAccelerationEpochs )
00594             {
00595                 if ( m_enableDebug )
00596                     cout<<" accelerate ";
00597                 m_expSearchExponent[pos] = pow ( m_expSearchExponent[pos], 1.0/m_expSearchAcceleration );
00598             }
00599         }
00600 
00601         m_expSearchAccelerationEpoch++;
00602     }
00603     else  // error gets higher, so change search direction and decrease step size
00604     {
00605         // current in a epoch parameter
00606         if ( m_epochParamPos < m_epochParam.size() )
00607         {
00608             // break training
00609             m_epochParamBreak = true;
00610         }
00611 
00612         // current in a double parameter
00613         if ( m_expSearchDoubleParamPos < m_doubleParam.size() && m_epochParamPos == m_epochParam.size() )
00614         {
00615             int pos = m_expSearchDoubleParamPos;
00616             bool dir = m_expSearchParamDirection[pos];
00617             m_expSearchParamDirection[pos] = !m_expSearchParamDirection[pos];
00618             m_expSearchExponent[pos] = pow ( m_expSearchExponent[pos], m_expSearchAcceleration );
00619         }
00620 
00621         // current in a int parameter
00622         if ( m_expSearchIntParamPos < m_intParam.size() && m_expSearchDoubleParamPos == m_doubleParam.size() )
00623         {
00624             int pos = m_expSearchIntParamPos;
00625             bool dir = m_expSearchParamDirection[pos + m_doubleParam.size() ];
00626             m_expSearchParamDirection[pos + m_doubleParam.size() ] = !m_expSearchParamDirection[pos + m_doubleParam.size() ];
00627             m_expSearchExponent[pos + m_doubleParam.size() ] = pow ( m_expSearchExponent[pos + m_doubleParam.size() ], m_expSearchAcceleration );
00628         }
00629 
00630         m_expSearchAccelerationEpoch = 0;
00631     }
00632 
00633 
00634     // goto next parameter, current in a epoch parameter
00635     if ( m_epochParamPos < m_epochParam.size() )
00636     {
00637         m_epochParamPos++;
00638 
00639         // if no integer and no double parameter available
00640         if ( m_doubleParam.size() == 0 && m_intParam.size() == 0 && m_epochParamPos == m_epochParam.size() )
00641             m_epochParamPos = 0;
00642     }
00643 
00644     // goto next parameter, current in a double parameter
00645     if ( m_expSearchDoubleParamPos < m_doubleParam.size() && m_epochParamPos == m_epochParam.size() )
00646     {
00647         // change to next parameter
00648         m_expSearchVariationCnt++;
00649         if ( m_expSearchVariationCnt==m_expSearchParamEpochs )
00650         {
00651             m_expSearchAccelerationEpoch = 0;
00652             m_expSearchVariationCnt = 0;
00653             *m_doubleParam[m_expSearchDoubleParamPos] = m_expSearchDoubleParamBest[m_expSearchDoubleParamPos];  // apply best
00654             m_expSearchDoubleParamPos++;
00655         }
00656 
00657         // if no integer parameter available
00658         if ( m_intParam.size() == 0 && m_expSearchDoubleParamPos == m_doubleParam.size() )
00659             m_expSearchDoubleParamPos = 0;
00660     }
00661 
00662     // goto next parameter, current in a int parameter
00663     if ( m_expSearchIntParamPos < m_intParam.size() && m_expSearchDoubleParamPos == m_doubleParam.size() )
00664     {
00665         // change to next parameter
00666         m_expSearchVariationCnt++;
00667         if ( m_expSearchVariationCnt==m_expSearchParamEpochs )
00668         {
00669             m_expSearchAccelerationEpoch = 0;
00670             m_expSearchVariationCnt = 0;
00671             *m_intParam[m_expSearchIntParamPos] = m_expSearchIntParamBest[m_expSearchIntParamPos];  // apply best
00672             m_expSearchIntParamPos++;
00673         }
00674 
00675         if ( m_expSearchIntParamPos == m_intParam.size() )
00676         {
00677             m_epochParamPos = 0;
00678             m_expSearchIntParamPos = 0;
00679             m_expSearchDoubleParamPos = 0;
00680         }
00681     }
00682 
00683     if ( m_enableDebug )
00684         cout<<endl;
00685 }
00686 
00700 void AutomaticParameterTuner::expSearcher ( int minEpochs, int maxEpochs, int paramEpochs, int accelerationEpochs, double expInit, bool enableProbe, bool enableBlend )
00701 {
00702     if ( enableProbe==0 && enableBlend==0 )
00703     {
00704         cout<<"Warning: both enableProbe and enableBlend are 0"<<endl;
00705         cout<<"Skip tuning"<<endl;
00706     }
00707 
00708     if ( maxEpochs == 0 )
00709         return;
00710 
00711     m_epochParamBreak = false;
00712 
00713     expSearchParams ( minEpochs, maxEpochs, paramEpochs, accelerationEpochs, expInit );
00714     m_optimizeProbeRMSE = enableProbe;
00715     m_optimizeBlendRMSE = enableBlend;
00716 
00717     // minimize on probe
00718     if ( m_optimizeProbeRMSE )
00719     {
00720         double error;
00721         while ( expSearchChangeParams() )
00722         {
00723             error = calcRMSEonProbe();
00724             expSearchCheckErr ( error );
00725         }
00726         if ( m_enableDebug )
00727             cout<<"expSearchErrorBest:"<<m_expSearchErrorBest<<"  error:"<<error<<endl;
00728     }
00729     // minimize on blend
00730     if ( m_optimizeBlendRMSE )
00731     {
00732         // if no explicit specified
00733         if ( m_expSearchMaxEpochsBlend == -1 )
00734             m_expSearchMaxEpochsBlend = m_expSearchMaxEpochs;
00735 
00736         expSearchParams ( m_expSearchMinEpochs, m_expSearchMaxEpochsBlend, paramEpochs, accelerationEpochs, expInit );
00737 
00738         if ( m_enableDebug )
00739             cout<<endl<<endl<<"==================== auto-optimize ===================="<<endl<<endl;
00740 
00741         double error;
00742         while ( expSearchChangeParams() )
00743         {
00744             error = calcRMSEonBlend();
00745             expSearchCheckErr ( error );
00746         }
00747         if ( m_enableDebug )
00748             cout<<"expSearchErrorBest:"<<m_expSearchErrorBest<<"  error:"<<error<<endl;
00749     }
00750 }
00751 
00756 void AutomaticParameterTuner::expSearchReinitStepSize()
00757 {
00758     if ( m_enableDebug )
00759         cout<<"Reinit exp search step to "<<m_expInit<<endl;
00760     m_expSearchDoubleParamPos = 0;
00761     m_expSearchIntParamPos = 0;
00762     m_expSearchErrorBest = 1e10;
00763     m_expSearchAcceleration = 0.8;
00764     m_expSearchAccelerationEpoch = 0;
00765     for ( int i=0;i<m_expSearchExponent.size();i++ )
00766         m_expSearchExponent[i] = m_expInit;
00767 }
00768 
00775 void AutomaticParameterTuner::expSearchSetEpochsToMinimizeBlend ( int epochs )
00776 {
00777     m_expSearchMaxEpochsBlend = epochs;
00778 }
00779 
00785 double AutomaticParameterTuner::expSearchGetLowestError()
00786 {
00787     return m_expSearchErrorBest;
00788 }
00789 
00790 
00791 // ====================== nelder-mead tuner ======================
00792 
00798 void AutomaticParameterTuner::NelderMeadSearch ( int maxEpochs )
00799 {
00800     int N = m_doubleParam.size() + m_intParam.size();
00801     vector<pair<double,vector<double> > > simplexPoints ( N+1 );
00802 
00803     // set the initial simplex
00804     for ( int i=0; i < N+1; i++ )
00805     {
00806         simplexPoints[i].second.resize ( N );
00807         for ( int j=0; j < m_doubleParam.size(); j++ )
00808             ( simplexPoints[i].second ) [j] = *m_doubleParam[j];
00809         for ( int j=0; j < m_intParam.size(); j++ )
00810             ( simplexPoints[i].second ) [j+m_doubleParam.size() ] = *m_intParam[j];
00811 
00812         if ( i < N )
00813             //(simplexPoints[i].second)[i] = (simplexPoints[i].second)[i] + fabs((simplexPoints[i].second)[i]) * 2.0;
00814             ( simplexPoints[i].second ) [i] = ( simplexPoints[i].second ) [i] + max ( 1.0,fabs ( ( simplexPoints[i].second ) [i] ) *2.0 );
00815     }
00816 
00817     for ( int i=0; i < N+1; i++ )
00818         simplexPoints[i].first = calcError ( simplexPoints[i].second );
00819 
00820     for ( int epoch =0; epoch < maxEpochs; epoch++ )
00821     {
00822         vector<double> center ( N );
00823 
00824         sort ( simplexPoints.begin(),simplexPoints.end() );
00825         calcCenter ( simplexPoints, center );
00826         plotParameters ( epoch, simplexPoints );
00827 
00828         // refelction
00829         vector<double> reflectionPoint ( N );
00830         double reflectionError = getReflectionPoint ( center,simplexPoints[N].second,reflectionPoint,1.0 );
00831 
00832         if ( ( reflectionError <= simplexPoints[N-1].first ) && ( reflectionError >= simplexPoints[0].first ) )
00833         {
00834             simplexPoints[N].second = reflectionPoint;
00835             simplexPoints[N].first = reflectionError;
00836             continue;
00837         }
00838 
00839         // expansion (the new point is the best so far)
00840         if ( reflectionError < simplexPoints[0].first )
00841         {
00842             vector<double> expansionPoint ( N );
00843             double expansionError = getReflectionPoint ( center,simplexPoints[N].second,expansionPoint,2.0 );
00844 
00845             if ( expansionError < reflectionError )
00846             {
00847                 simplexPoints[N].second = expansionPoint;
00848                 simplexPoints[N].first = expansionError;
00849                 continue;
00850             }
00851             else
00852             {
00853                 simplexPoints[N].second = reflectionPoint;
00854                 simplexPoints[N].first = reflectionError;
00855                 continue;
00856             }
00857         }
00858 
00859         // contraction (the new point is the worst so far)
00860         vector<double> contractionPoint ( N );
00861         double contractionError, refError;
00862         if ( reflectionError <= simplexPoints[N].first )
00863         {   // outside contraction
00864             refError = reflectionError;
00865             contractionError = getReflectionPoint ( center,reflectionPoint,contractionPoint,0.5 );
00866         }
00867         else
00868         {   // inside contraction
00869             refError = simplexPoints[N].first;
00870             contractionError = getReflectionPoint ( center,simplexPoints[N].second,contractionPoint,0.5 );
00871         }
00872 
00873         if ( contractionError <= refError )
00874         {
00875             simplexPoints[N].second = contractionPoint;
00876             simplexPoints[N].first = contractionError;
00877             continue;
00878         }
00879 
00880         // reduction
00881         for ( int j=1; j < N+1; j++ )
00882         {
00883             vector<double> reductionPoint ( N );
00884             double reductionError = getReflectionPoint ( center,simplexPoints[j].second, reductionPoint, 0.5 );
00885             simplexPoints[j].second = reductionPoint;
00886             simplexPoints[j].first = reductionError;
00887         }
00888     }
00889 
00890     sort ( simplexPoints.begin(),simplexPoints.end() );
00891     setCurrentParameter ( simplexPoints[0].second );
00892 }
00893 
00900 double AutomaticParameterTuner::calcError ( const vector<double> &paramVector )
00901 {
00902     setCurrentParameter ( paramVector );
00903 
00904     return calcRMSEonProbe();
00905 }
00906 
00912 void AutomaticParameterTuner::setCurrentParameter ( const vector<double> &paramVector )
00913 {
00914     for ( int i=0; i < m_doubleParam.size(); i++ )
00915     {
00916         double value = paramVector[i];
00917 
00918         if ( value <= m_doubleMin[i] )
00919             value = m_doubleMin[i];
00920         if ( value >= m_doubleMax[i] )
00921             value = m_doubleMax[i];
00922 
00923         *m_doubleParam[i] = value;
00924     }
00925 
00926     for ( int i=0; i < m_intParam.size(); i++ )
00927     {
00928         int value = ( int ) ( 0.5 + paramVector[i + m_doubleParam.size() ] );
00929 
00930         if ( value <= m_intMin[i] )
00931             value = m_intMin[i];
00932         if ( value >= m_intMax[i] )
00933             value = m_intMax[i];
00934 
00935         *m_intParam[i] = value;
00936     }
00937 }
00938 
00945 void AutomaticParameterTuner::calcCenter ( const vector<pair<double,vector<double> > > &simplexPoints, vector<double> &center )
00946 {
00947     center.resize ( simplexPoints[0].second.size() );
00948 
00949     for ( int i=0; i < center.size(); i++ )
00950         center[i] = 0.0;
00951 
00952     for ( int i=0; i < simplexPoints.size()-1; i++ )
00953     {
00954         for ( int j=0; j < center.size(); j++ )
00955             center[j] += ( simplexPoints[i].second ) [j];
00956     }
00957 
00958     for ( int i=0; i < center.size(); i++ )
00959         center[i] /= ( double ) ( simplexPoints.size()-1 );
00960 }
00961 
00971 double AutomaticParameterTuner::getReflectionPoint ( const vector<double> &center, const vector<double> &worstPoint, vector<double> &reflectionPoint, double alpha )
00972 {
00973     int N = center.size();
00974     reflectionPoint.resize ( N );
00975 
00976     for ( int i=0; i < N; i++ )
00977         reflectionPoint[i] = center[i] + alpha* ( center[i] - worstPoint[i] );
00978 
00979     return calcError ( reflectionPoint );
00980 }
00981 
00988 void AutomaticParameterTuner::plotParameters ( int epoch, const vector<pair<double,vector<double> > > &simplexPoints )
00989 {
00990     static time_t t0 = time ( 0 );
00991 
00992     if ( m_enableDebug )
00993         cout<<epoch<<". | error: ["<<simplexPoints[0].first<<"-"<<simplexPoints[simplexPoints.size()-1].first<<"] ";
00994 
00995     for ( int i=0; i < m_doubleParam.size(); i++ )
00996     {
00997         double min,max;
00998         calcMinMax ( simplexPoints,i,min,max );
00999         if ( m_enableDebug )
01000             cout<<" | "<<m_doubleName[i]<<": ["<<min<<" - "<<max<<"]";
01001     }
01002 
01003     for ( int i=0; i < m_intParam.size(); i++ )
01004     {
01005         int param = i+m_doubleParam.size();
01006         double min,max;
01007         calcMinMax ( simplexPoints,param,min,max );
01008         if ( m_enableDebug )
01009             cout<<" | "<<m_intName[i]<<": ["<<min<<" - "<<max<<"]";
01010     }
01011 
01012     time_t t1 = time ( 0 );
01013     if ( m_enableDebug )
01014         cout<<" | "<<t1-t0<<"[s]"<<endl;
01015     t0=t1;
01016 }
01017 
01026 void AutomaticParameterTuner::calcMinMax ( const vector<pair<double,vector<double> > > &simplexPoints, int paramNr, double &min, double &max )
01027 {
01028     min = DBL_MAX;
01029     max = DBL_MIN;
01030 
01031     for ( int i=0; i < simplexPoints.size(); i++ )
01032     {
01033         double value = simplexPoints[i].second.at ( paramNr );
01034 
01035         if ( value < min )
01036             min = value;
01037         if ( value > max )
01038             max = value;
01039     }
01040 }

Generated on Tue Jan 26 09:20:58 2010 for ELF by  doxygen 1.5.8