00001 #include "AutomaticParameterTuner.h"
00002
00003 extern StreamOutput cout;
00004
00008 AutomaticParameterTuner::AutomaticParameterTuner()
00009 {
00010
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
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
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
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
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
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
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
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
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
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
00439 if ( m_epochParamPos < m_epochParam.size() )
00440 {
00441
00442 *m_epochParam[m_epochParamPos] = *m_epochParam[m_epochParamPos] + 1;
00443 }
00444
00445
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
00454 *m_doubleParam[pos] = best * ( dir? ( 1.0/exp ) : exp );
00455
00456
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
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
00472 *m_intParam[pos] = ( int ) ( round ( ( double ) ( best ) * ( dir? ( 1.0/exp ) : exp ) ) );
00473
00474
00475 if ( best == *m_intParam[pos] )
00476 *m_intParam[pos] = dir? best+1 : best-1;
00477
00478
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
00496 if ( m_expSearchEpoch > m_expSearchMaxEpochs )
00497 {
00498 m_expSearchEpoch = 0;
00499
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
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
00545 if ( error<m_expSearchErrorBest )
00546 {
00547 m_expSearchErrorBest = error;
00548
00549
00550 m_epochParamBreak = 0;
00551
00552 if ( m_enableDebug )
00553 cout<<" !min! ";
00554 saveBestPrediction();
00555
00556
00557 if ( m_epochParamPos < m_epochParam.size() )
00558 {
00559 m_epochParamBest[m_epochParamPos] = *m_epochParam[m_epochParamPos];
00560 }
00561
00562
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
00570 m_expSearchDoubleParamBest[pos] = *m_doubleParam[pos];
00571
00572
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
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
00590 m_expSearchIntParamBest[pos] = *m_intParam[pos];
00591
00592
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
00604 {
00605
00606 if ( m_epochParamPos < m_epochParam.size() )
00607 {
00608
00609 m_epochParamBreak = true;
00610 }
00611
00612
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
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
00635 if ( m_epochParamPos < m_epochParam.size() )
00636 {
00637 m_epochParamPos++;
00638
00639
00640 if ( m_doubleParam.size() == 0 && m_intParam.size() == 0 && m_epochParamPos == m_epochParam.size() )
00641 m_epochParamPos = 0;
00642 }
00643
00644
00645 if ( m_expSearchDoubleParamPos < m_doubleParam.size() && m_epochParamPos == m_epochParam.size() )
00646 {
00647
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];
00654 m_expSearchDoubleParamPos++;
00655 }
00656
00657
00658 if ( m_intParam.size() == 0 && m_expSearchDoubleParamPos == m_doubleParam.size() )
00659 m_expSearchDoubleParamPos = 0;
00660 }
00661
00662
00663 if ( m_expSearchIntParamPos < m_intParam.size() && m_expSearchDoubleParamPos == m_doubleParam.size() )
00664 {
00665
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];
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
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
00730 if ( m_optimizeBlendRMSE )
00731 {
00732
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
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
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
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
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
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
00860 vector<double> contractionPoint ( N );
00861 double contractionError, refError;
00862 if ( reflectionError <= simplexPoints[N].first )
00863 {
00864 refError = reflectionError;
00865 contractionError = getReflectionPoint ( center,reflectionPoint,contractionPoint,0.5 );
00866 }
00867 else
00868 {
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
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> ¶mVector )
00901 {
00902 setCurrentParameter ( paramVector );
00903
00904 return calcRMSEonProbe();
00905 }
00906
00912 void AutomaticParameterTuner::setCurrentParameter ( const vector<double> ¶mVector )
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> ¢er )
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> ¢er, 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 }