Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
SimulatedAnnealing.cxx
Go to the documentation of this file.
1// @(#)root/tmva $Id$
2// Author: Andreas Hoecker, Joerg Stelzer, Helge Voss, Krzysztof Danielowski, Kamil Kraszewski, Maciej Kruk
3
4/**********************************************************************************
5 * Project: TMVA - a Root-integrated toolkit for multivariate data analysis *
6 * Package: TMVA *
7 * Class : SimulatedAnnealing *
8 * *
9 * *
10 * Description: *
11 * Implementation (see header for description) *
12 * *
13 * Authors (alphabetical): *
14 * Krzysztof Danielowski <danielow@cern.ch> - IFJ & AGH, Poland *
15 * Kamil Kraszewski <kalq@cern.ch> - IFJ & UJ, Poland *
16 * Maciej Kruk <mkruk@cern.ch> - IFJ & AGH, Poland *
17 * *
18 * Copyright (c) 2008: *
19 * IFJ-Krakow, Poland *
20 * CERN, Switzerland *
21 * MPI-K Heidelberg, Germany *
22 * *
23 * Redistribution and use in source and binary forms, with or without *
24 * modification, are permitted according to the terms listed in LICENSE *
25 * (see tmva/doc/LICENSE) *
26 **********************************************************************************/
27
28/*! \class TMVA::SimulatedAnnealing
29\ingroup TMVA
30Base implementation of simulated annealing fitting procedure.
31*/
32
34
35#include "TMVA/IFitterTarget.h"
36#include "TMVA/Interval.h"
37#include "TMVA/GeneticRange.h"
38#include "TMVA/MsgLogger.h"
39#include "TMVA/Timer.h"
40#include "TMVA/Types.h"
41
42#include "TRandom3.h"
43#include "TMath.h"
44
45
46////////////////////////////////////////////////////////////////////////////////
47/// constructor
48
49TMVA::SimulatedAnnealing::SimulatedAnnealing( IFitterTarget& target, const std::vector<Interval*>& ranges )
50: fKernelTemperature (kIncreasingAdaptive),
51 fFitterTarget ( target ),
52 fRandom ( new TRandom3(100) ),
53 fRanges ( ranges ),
54 fMaxCalls ( 500000 ),
55 fInitialTemperature ( 1000 ),
56 fMinTemperature ( 0 ),
57 fEps ( 1e-10 ),
58 fTemperatureScale ( 0.06 ),
59 fAdaptiveSpeed ( 1.0 ),
60 fTemperatureAdaptiveStep( 0.0 ),
61 fUseDefaultScale ( kFALSE ),
62 fUseDefaultTemperature ( kFALSE ),
63 fLogger( new MsgLogger("SimulatedAnnealing") ),
64 fProgress(0.0)
65{
67}
68
69////////////////////////////////////////////////////////////////////////////////
70/// option setter
71
75 Double_t eps,
82{
83 fMaxCalls = maxCalls;
84 fInitialTemperature = initialTemperature;
85 fMinTemperature = minTemperature;
86 fEps = eps;
87
88 if (kernelTemperatureS == "IncreasingAdaptive") {
89 fKernelTemperature = kIncreasingAdaptive;
90 Log() << kINFO << "Using increasing adaptive algorithm" << Endl;
91 }
92 else if (kernelTemperatureS == "DecreasingAdaptive") {
93 fKernelTemperature = kDecreasingAdaptive;
94 Log() << kINFO << "Using decreasing adaptive algorithm" << Endl;
95 }
96 else if (kernelTemperatureS == "Sqrt") {
97 fKernelTemperature = kSqrt;
98 Log() << kINFO << "Using \"Sqrt\" algorithm" << Endl;
99 }
100 else if (kernelTemperatureS == "Homo") {
101 fKernelTemperature = kHomo;
102 Log() << kINFO << "Using \"Homo\" algorithm" << Endl;
103 }
104 else if (kernelTemperatureS == "Log") {
105 fKernelTemperature = kLog;
106 Log() << kINFO << "Using \"Log\" algorithm" << Endl;
107 }
108 else if (kernelTemperatureS == "Sin") {
109 fKernelTemperature = kSin;
110 Log() << kINFO << "Using \"Sin\" algorithm" << Endl;
111 }
112
113 fTemperatureScale = temperatureScale;
114 fAdaptiveSpeed = adaptiveSpeed;
115 fTemperatureAdaptiveStep = temperatureAdaptiveStep;
116
117 fUseDefaultScale = useDefaultScale;
118 fUseDefaultTemperature = useDefaultTemperature;
119}
120
121////////////////////////////////////////////////////////////////////////////////
122/// destructor
123
127
128////////////////////////////////////////////////////////////////////////////////
129/// random starting parameters
130
131void TMVA::SimulatedAnnealing::FillWithRandomValues( std::vector<Double_t>& parameters )
132{
133 for (UInt_t rIter = 0; rIter < parameters.size(); rIter++) {
134 parameters[rIter] = fRandom->Uniform(0.0,1.0)*(fRanges[rIter]->GetMax() - fRanges[rIter]->GetMin()) + fRanges[rIter]->GetMin();
135 }
136}
137
138////////////////////////////////////////////////////////////////////////////////
139/// copy parameters
140
141void TMVA::SimulatedAnnealing::ReWriteParameters( std::vector<Double_t>& from, std::vector<Double_t>& to)
142{
143 for (UInt_t rIter = 0; rIter < from.size(); rIter++) to[rIter] = from[rIter];
144}
145
146////////////////////////////////////////////////////////////////////////////////
147/// generate adjacent parameters
148
149void TMVA::SimulatedAnnealing::GenerateNeighbour( std::vector<Double_t>& parameters, std::vector<Double_t>& oldParameters,
151{
152 ReWriteParameters( parameters, oldParameters );
153
154 for (UInt_t rIter=0;rIter<parameters.size();rIter++) {
156 do {
157 uni = fRandom->Uniform(0.0,1.0);
158 sign = (uni - 0.5 >= 0.0) ? (1.0) : (-1.0);
160 parameters[rIter] = oldParameters[rIter] + (fRanges[rIter]->GetMax()-fRanges[rIter]->GetMin())*0.1*distribution;
161 }
162 while (parameters[rIter] < fRanges[rIter]->GetMin() || parameters[rIter] > fRanges[rIter]->GetMax() );
163 }
164}
165////////////////////////////////////////////////////////////////////////////////
166/// generate adjacent parameters
167
168std::vector<Double_t> TMVA::SimulatedAnnealing::GenerateNeighbour( std::vector<Double_t>& parameters, Double_t currentTemperature )
169{
170 std::vector<Double_t> newParameters( fRanges.size() );
171
172 for (UInt_t rIter=0; rIter<parameters.size(); rIter++) {
174 do {
175 uni = fRandom->Uniform(0.0,1.0);
176 sign = (uni - 0.5 >= 0.0) ? (1.0) : (-1.0);
178 newParameters[rIter] = parameters[rIter] + (fRanges[rIter]->GetMax()-fRanges[rIter]->GetMin())*0.1*distribution;
179 }
180 while (newParameters[rIter] < fRanges[rIter]->GetMin() || newParameters[rIter] > fRanges[rIter]->GetMax() );
181 }
182
183 return newParameters;
184}
185
186////////////////////////////////////////////////////////////////////////////////
187/// generate new temperature
188
190{
191 if (fKernelTemperature == kSqrt) {
192 currentTemperature = fInitialTemperature/(Double_t)TMath::Sqrt(Iter+2) * fTemperatureScale;
193 }
194 else if (fKernelTemperature == kLog) {
195 currentTemperature = fInitialTemperature/(Double_t)TMath::Log(Iter+2) * fTemperatureScale;
196 }
197 else if (fKernelTemperature == kHomo) {
198 currentTemperature = fInitialTemperature/(Double_t)(Iter+2) * fTemperatureScale;
199 }
200 else if (fKernelTemperature == kSin) {
201 currentTemperature = (TMath::Sin( (Double_t)Iter / fTemperatureScale ) + 1.0 )/ (Double_t)(Iter+1.0) * fInitialTemperature + fEps;
202 }
203 else if (fKernelTemperature == kGeo) {
204 currentTemperature = currentTemperature*fTemperatureScale;
205 }
206 else if (fKernelTemperature == kIncreasingAdaptive) {
207 currentTemperature = fMinTemperature + fTemperatureScale*TMath::Log(1.0+fProgress*fAdaptiveSpeed);
208 }
209 else if (fKernelTemperature == kDecreasingAdaptive) {
210 currentTemperature = currentTemperature*fTemperatureScale;
211 }
212 else Log() << kFATAL << "No such kernel!" << Endl;
213}
214
215////////////////////////////////////////////////////////////////////////////////
216/// result checker
217
225
226////////////////////////////////////////////////////////////////////////////////
227/// setting of default scale
228
230{
231 if (fKernelTemperature == kSqrt) fTemperatureScale = 1.0;
232 else if (fKernelTemperature == kLog) fTemperatureScale = 1.0;
233 else if (fKernelTemperature == kHomo) fTemperatureScale = 1.0;
234 else if (fKernelTemperature == kSin) fTemperatureScale = 20.0;
235 else if (fKernelTemperature == kGeo) fTemperatureScale = 0.99997;
236 else if (fKernelTemperature == kDecreasingAdaptive) {
237 fTemperatureScale = 1.0;
238 while (TMath::Abs(TMath::Power(fTemperatureScale,fMaxCalls) * fInitialTemperature - fMinTemperature) >
239 TMath::Abs(TMath::Power(fTemperatureScale-0.000001,fMaxCalls) * fInitialTemperature - fMinTemperature)) {
240 fTemperatureScale -= 0.000001;
241 }
242 }
243 else if (fKernelTemperature == kIncreasingAdaptive) fTemperatureScale = 0.15*( 1.0 / (Double_t)(fRanges.size() ) );
244 else Log() << kFATAL << "No such kernel!" << Endl;
245}
246
247////////////////////////////////////////////////////////////////////////////////
248/// maximum temperature
249
251{
253 Bool_t stopper = 0;
254 Double_t t, dT, cold, delta, deltaY, y, yNew, yBest, yOld;
255 std::vector<Double_t> x( fRanges.size() ), xNew( fRanges.size() ), xBest( fRanges.size() ), xOld( fRanges.size() );
256 t = fMinTemperature;
257 deltaY = cold = 0.0;
258 dT = fTemperatureAdaptiveStep;
259 for (UInt_t rIter = 0; rIter < x.size(); rIter++)
260 x[rIter] = ( fRanges[rIter]->GetMax() + fRanges[rIter]->GetMin() ) / 2.0;
261 y = yBest = 1E10;
262 for (Int_t i=0; i<fMaxCalls/50; i++) {
263 if ((i>0) && (deltaY>0.0)) {
264 cold = deltaY;
265 stopper = 1;
266 }
267 t += dT*i;
268 x = xOld = GenerateNeighbour(x,t);
269 y = yOld = fFitterTarget.EstimatorFunction( xOld );
270 equilibrium = 0;
271 for ( Int_t k=0; (k<30) && (equilibrium<=12); k++ ) {
272 xNew = GenerateNeighbour(x,t);
273 //"energy"
274 yNew = fFitterTarget.EstimatorFunction( xNew );
275 deltaY = yNew - y;
276 if (deltaY < 0.0) { // keep xnew if energy is reduced
277 std::swap(x,xNew);
278 std::swap(y,yNew);
279 if (y < yBest) {
280 xBest = x;
281 yBest = y;
282 }
283 delta = TMath::Abs( deltaY );
284 if (y != 0.0) delta /= y;
285 else if (yNew != 0.0) delta /= y;
286
287 // equilibrium is defined as a 10% or smaller change in 10 iterations
288 if (delta < 0.1) equilibrium++;
289 else equilibrium = 0;
290 }
291 else equilibrium++;
292 }
293
294 // "energy"
295 yNew = fFitterTarget.EstimatorFunction( xNew );
296 deltaY = yNew - yOld;
297 if ( (deltaY < 0.0 )&&( yNew < yBest)) {
298 xBest=x;
299 yBest = yNew;
300 }
301 y = yNew;
302 if ((stopper) && (deltaY >= (100.0 * cold))) break; // phase transition with another parameter to change
303 }
304 parameters = xBest;
305 return t;
306}
307
308////////////////////////////////////////////////////////////////////////////////
309/// minimisation algorithm
310
311Double_t TMVA::SimulatedAnnealing::Minimize( std::vector<Double_t>& parameters )
312{
313 std::vector<Double_t> bestParameters(fRanges.size());
314 std::vector<Double_t> oldParameters (fRanges.size());
315
318
319 equals = 0;
320
321 if (fUseDefaultTemperature) {
322 if (fKernelTemperature == kIncreasingAdaptive) {
323 fMinTemperature = currentTemperature = 1e-06;
324 FillWithRandomValues( parameters );
325 }
326 else fInitialTemperature = currentTemperature = GenerateMaxTemperature( parameters );
327 }
328 else {
329 if (fKernelTemperature == kIncreasingAdaptive)
330 currentTemperature = fMinTemperature;
331 else
332 currentTemperature = fInitialTemperature;
333 FillWithRandomValues( parameters );
334 }
335
336 if (fUseDefaultScale) SetDefaultScale();
337
338 Log() << kINFO
339 << "Temperatur scale = " << fTemperatureScale
340 << ", current temperature = " << currentTemperature << Endl;
341
342 bestParameters = parameters;
343 bestFit = currentFit = fFitterTarget.EstimatorFunction( bestParameters );
344
345 optimizeCalls = fMaxCalls/100; //use 1% calls to optimize best founded minimum
346 generalCalls = fMaxCalls - optimizeCalls; //and 99% calls to found that one
347 fProgress = 0.0;
348
349 Timer timer( fMaxCalls, fLogger->GetSource().c_str() );
350
351 for (Int_t sample = 0; sample < generalCalls; sample++) {
352 if (fIPyCurrentIter) *fIPyCurrentIter = sample;
353 if (fExitFromTraining && *fExitFromTraining) break;
354 GenerateNeighbour( parameters, oldParameters, currentTemperature );
355 Double_t localFit = fFitterTarget.EstimatorFunction( parameters );
356
357 if (localFit < currentFit || TMath::Abs(currentFit-localFit) < fEps) { // if not worse than last one
358 if (TMath::Abs(currentFit-localFit) < fEps) { // if the same as last one
359 equals++;
360 if (equals >= 3) //if we still at the same level, we should increase temperature
361 fProgress+=1.0;
362 }
363 else {
364 fProgress = 0.0;
365 equals = 0;
366 }
367
369
370 if (currentFit < bestFit) {
371 ReWriteParameters( parameters, bestParameters );
373 }
374 }
375 else {
376 if (!ShouldGoIn(localFit, currentFit, currentTemperature))
377 ReWriteParameters( oldParameters, parameters );
378 else
380
381 fProgress+=1.0;
382 equals = 0;
383 }
384
385 GenerateNewTemperature( currentTemperature, sample );
386
387 if ((fMaxCalls<100) || sample%Int_t(fMaxCalls/100.0) == 0) timer.DrawProgressBar( sample );
388 }
389
390 // get elapsed time
391 Log() << kINFO << "Elapsed time: " << timer.GetElapsedTime()
392 << " " << Endl;
393
394 // suppose this minimum is the best one, now just try to improve it
395
396 Double_t startingTemperature = fMinTemperature*(fRanges.size())*2.0;
398
400 GenerateNeighbour( parameters, oldParameters, currentTemperature );
401 Double_t localFit = fFitterTarget.EstimatorFunction( parameters );
402
403 if (localFit < currentFit) { //if better than last one
405
406 if (currentFit < bestFit) {
407 ReWriteParameters( parameters, bestParameters );
409 }
410 }
411 else ReWriteParameters( oldParameters, parameters ); //we never try worse parameters
412
414 }
415
416 ReWriteParameters( bestParameters, parameters );
417
418 return bestFit;
419}
#define e(i)
Definition RSha256.hxx:103
int Int_t
Signed integer 4 bytes (int)
Definition RtypesCore.h:59
constexpr Bool_t kFALSE
Definition RtypesCore.h:108
double Double_t
Double 8 bytes.
Definition RtypesCore.h:73
constexpr Bool_t kTRUE
Definition RtypesCore.h:107
ROOT::Detail::TRangeCast< T, true > TRangeDynCast
TRangeDynCast is an adapter class that allows the typed iteration through a TCollection.
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t winding char text const char depth char const char Int_t count const char ColorStruct_t color const char Pixmap_t Pixmap_t PictureAttributes_t attr const char char ret_data h unsigned char height h Atom_t Int_t ULong_t ULong_t unsigned char prop_list Atom_t Atom_t target
Interface for a fitter 'target'.
ostringstream derivative to redirect and format output
Definition MsgLogger.h:57
void GenerateNeighbour(std::vector< Double_t > &parameters, std::vector< Double_t > &oldParameters, Double_t currentTemperature)
generate adjacent parameters
Double_t Minimize(std::vector< Double_t > &parameters)
minimisation algorithm
virtual ~SimulatedAnnealing()
destructor
Double_t GenerateMaxTemperature(std::vector< Double_t > &parameters)
maximum temperature
void SetOptions(Int_t maxCalls, Double_t initialTemperature, Double_t minTemperature, Double_t eps, TString kernelTemperatureS, Double_t temperatureScale, Double_t adaptiveSpeed, Double_t temperatureAdaptiveStep, Bool_t useDefaultScale, Bool_t useDefaultTemperature)
option setter
void SetDefaultScale()
setting of default scale
void GenerateNewTemperature(Double_t &currentTemperature, Int_t Iter)
generate new temperature
void FillWithRandomValues(std::vector< Double_t > &parameters)
random starting parameters
void ReWriteParameters(std::vector< Double_t > &from, std::vector< Double_t > &to)
copy parameters
enum TMVA::SimulatedAnnealing::EKernelTemperature fKernelTemperature
SimulatedAnnealing(IFitterTarget &target, const std::vector< TMVA::Interval * > &ranges)
constructor
Bool_t ShouldGoIn(Double_t currentFit, Double_t localFit, Double_t currentTemperature)
result checker
Timing information for training and evaluation of MVA methods.
Definition Timer.h:58
Random number generator class based on M.
Definition TRandom3.h:27
Basic string class.
Definition TString.h:138
Double_t y[n]
Definition legend1.C:17
Double_t x[n]
Definition legend1.C:17
MsgLogger & Endl(MsgLogger &ml)
Definition MsgLogger.h:148
Double_t Exp(Double_t x)
Returns the base-e exponential function of x, which is e raised to the power x.
Definition TMath.h:720
Double_t Log(Double_t x)
Returns the natural logarithm of x.
Definition TMath.h:767
Double_t Sqrt(Double_t x)
Returns the square root of x.
Definition TMath.h:673
LongDouble_t Power(LongDouble_t x, LongDouble_t y)
Returns x raised to the power y.
Definition TMath.h:732
Double_t Sin(Double_t)
Returns the sine of an angle of x radians.
Definition TMath.h:599
Short_t Abs(Short_t d)
Returns the absolute value of parameter Short_t d.
Definition TMathBase.h:124