Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
MethodPDERS.cxx
Go to the documentation of this file.
1// @(#)root/tmva $Id$
2// Author: Andreas Hoecker, Yair Mahalalel, Joerg Stelzer, Helge Voss, Kai Voss
3
4/***********************************************************************************
5 * Project: TMVA - a Root-integrated toolkit for multivariate data analysis *
6 * Package: TMVA *
7 * Class : MethodPDERS *
8 * *
9 * *
10 * Description: *
11 * Implementation *
12 * *
13 * Authors (alphabetical): *
14 * Krzysztof Danielowski <danielow@cern.ch> - IFJ PAN & AGH, Poland *
15 * Andreas Hoecker <Andreas.Hocker@cern.ch> - CERN, Switzerland *
16 * Kamil Kraszewski <kalq@cern.ch> - IFJ PAN & UJ, Poland *
17 * Maciej Kruk <mkruk@cern.ch> - IFJ PAN & AGH, Poland *
18 * Yair Mahalalel <Yair.Mahalalel@cern.ch> - CERN, Switzerland *
19 * Helge Voss <Helge.Voss@cern.ch> - MPI-K Heidelberg, Germany *
20 * Kai Voss <Kai.Voss@cern.ch> - U. of Victoria, Canada *
21 * *
22 * Copyright (c) 2005: *
23 * CERN, Switzerland *
24 * U. of Victoria, Canada *
25 * MPI-K Heidelberg, Germany *
26 * *
27 * Redistribution and use in source and binary forms, with or without *
28 * modification, are permitted according to the terms listed in LICENSE *
29 * (see tmva/doc/LICENSE) *
30 ***********************************************************************************/
31
32/*! \class TMVA::MethodPDERS
33\ingroup TMVA
34
35This is a generalization of the above Likelihood methods to \f$ N_{var} \f$
36dimensions, where \f$ N_{var} \f$ is the number of input variables
37used in the MVA. If the multi-dimensional probability density functions
38(PDFs) for signal and background were known, this method contains the entire
39physical information, and is therefore optimal. Usually, kernel estimation
40methods are used to approximate the PDFs using the events from the
41training sample.
42
43A very simple probability density estimator (PDE) has been suggested
44in [hep-ex/0211019](http://arxiv.org/abs/hep-ex/0211019). The
45PDE for a given test event is obtained from counting the (normalized)
46number of signal and background (training) events that occur in the
47"vicinity" of the test event. The volume that describes "vicinity" is
48user-defined. A [search method based on binary-trees](http://arxiv.org/abs/hep-ex/0211019)
49is used to effectively reduce the
50selection time for the range search. Three different volume definitions
51are optional:
52
53 - *MinMax:* the volume is defined in each dimension with respect
54 to the full variable range found in the training sample.
55 - *RMS:* the volume is defined in each dimensions with respect
56 to the RMS estimated from the training sample.
57 - *Adaptive:* a volume element is defined in each dimensions with
58 respect to the RMS estimated from the training sample. The overall
59 scale of the volume element is then determined for each event so
60 that the total number of events confined in the volume be within
61 a user-defined range.
62
63The adaptive range search is used by default.
64*/
65
66#include "TMVA/MethodPDERS.h"
67
68#include "TMVA/BinaryTree.h"
70#include "TMVA/Configurable.h"
72#include "TMVA/Event.h"
73#include "TMVA/IMethod.h"
74#include "TMVA/MethodBase.h"
75#include "TMVA/MsgLogger.h"
76#include "TMVA/RootFinder.h"
77#include "TMVA/Tools.h"
79#include "TMVA/Types.h"
80
81#include "ThreadLocalStorage.h"
82#include "TFile.h"
83#include "TMath.h"
84
85#include <cassert>
86#include <algorithm>
87
88namespace TMVA {
90};
91
92
94
95
96////////////////////////////////////////////////////////////////////////////////
97/// standard constructor for the PDERS method
98
100 const TString& methodTitle,
103 MethodBase( jobName, Types::kPDERS, methodTitle, theData, theOption),
104 fFcnCall(0),
105 fVRangeMode(kAdaptive),
106 fKernelEstimator(kBox),
107 fDelta(0),
108 fShift(0),
109 fScaleS(0),
110 fScaleB(0),
111 fDeltaFrac(0),
112 fGaussSigma(0),
113 fGaussSigmaNorm(0),
114 fNRegOut(0),
115 fNEventsMin(0),
116 fNEventsMax(0),
117 fMaxVIterations(0),
118 fInitialScale(0),
119 fInitializedVolumeEle(0),
120 fkNNMin(0),
121 fkNNMax(0),
122 fMax_distance(0),
123 fPrinted(0),
124 fNormTree(0)
125{
126 fHelpVolume = NULL;
127 fBinaryTree = NULL;
128}
129
130////////////////////////////////////////////////////////////////////////////////
131/// construct MethodPDERS through from file
132
134 const TString& theWeightFile) :
136 fFcnCall(0),
137 fVRangeMode(kAdaptive),
138 fKernelEstimator(kBox),
139 fDelta(0),
140 fShift(0),
141 fScaleS(0),
142 fScaleB(0),
143 fDeltaFrac(0),
144 fGaussSigma(0),
145 fGaussSigmaNorm(0),
146 fNRegOut(0),
147 fNEventsMin(0),
148 fNEventsMax(0),
149 fMaxVIterations(0),
150 fInitialScale(0),
151 fInitializedVolumeEle(0),
152 fkNNMin(0),
153 fkNNMax(0),
154 fMax_distance(0),
155 fPrinted(0),
156 fNormTree(0)
157{
160}
161
162////////////////////////////////////////////////////////////////////////////////
163/// PDERS can handle classification with 2 classes and regression with one or more regression-targets
164
171
172////////////////////////////////////////////////////////////////////////////////
173/// default initialisation routine called by all constructors
174
176{
177 fBinaryTree = NULL;
178
179 UpdateThis();
180
181 // default options
182 fDeltaFrac = 3.0;
183 fVRangeMode = kAdaptive;
184 fKernelEstimator = kBox;
185
186 // special options for Adaptive mode
187 fNEventsMin = 100;
188 fNEventsMax = 200;
189 fMaxVIterations = 150;
190 fInitialScale = 0.99;
191 fGaussSigma = 0.1;
192 fNormTree = kFALSE;
193
194 fkNNMin = Int_t(fNEventsMin);
195 fkNNMax = Int_t(fNEventsMax);
196
197 fInitializedVolumeEle = kFALSE;
198 fAverageRMS.clear();
199
200 // the minimum requirement to declare an event signal-like
201 SetSignalReferenceCut( 0.0 );
202}
203
204////////////////////////////////////////////////////////////////////////////////
205/// destructor
206
208{
209 if (fDelta) delete fDelta;
210 if (fShift) delete fShift;
211
212 if (NULL != fBinaryTree) delete fBinaryTree;
213}
214
215////////////////////////////////////////////////////////////////////////////////
216/// define the options (their key words) that can be set in the option string.
217///
218/// know options:
219/// - VolumeRangeMode `<string>` Method to determine volume range
220/// available values are:
221/// - MinMax
222/// - Unscaled
223/// - RMS
224/// - kNN
225/// - Adaptive `<default>`
226///
227/// - KernelEstimator `<string>` Kernel estimation function
228/// available values are:
229/// - Box `<default>`
230/// - Sphere
231/// - Teepee
232/// - Gauss
233/// - Sinc3
234/// - Sinc5
235/// - Sinc7
236/// - Sinc9
237/// - Sinc11
238/// - Lanczos2
239/// - Lanczos3
240/// - Lanczos5
241/// - Lanczos8
242/// - Trim
243///
244/// - DeltaFrac `<float>` Ratio of #%EventsMin/#%EventsMax for MinMax and RMS volume range
245/// - NEventsMin `<int>` Minimum number of events for adaptive volume range
246/// - NEventsMax `<int>` Maximum number of events for adaptive volume range
247/// - MaxVIterations `<int>` Maximum number of iterations for adaptive volume range
248/// - InitialScale `<float>` Initial scale for adaptive volume range
249/// - GaussSigma `<float>` Width with respect to the volume size of Gaussian kernel estimator
250
252{
253 DeclareOptionRef(fVolumeRange="Adaptive", "VolumeRangeMode", "Method to determine volume size");
254 AddPreDefVal(TString("Unscaled"));
255 AddPreDefVal(TString("MinMax"));
256 AddPreDefVal(TString("RMS"));
257 AddPreDefVal(TString("Adaptive"));
258 AddPreDefVal(TString("kNN"));
259
260 DeclareOptionRef(fKernelString="Box", "KernelEstimator", "Kernel estimation function");
261 AddPreDefVal(TString("Box"));
262 AddPreDefVal(TString("Sphere"));
263 AddPreDefVal(TString("Teepee"));
264 AddPreDefVal(TString("Gauss"));
265 AddPreDefVal(TString("Sinc3"));
266 AddPreDefVal(TString("Sinc5"));
267 AddPreDefVal(TString("Sinc7"));
268 AddPreDefVal(TString("Sinc9"));
269 AddPreDefVal(TString("Sinc11"));
270 AddPreDefVal(TString("Lanczos2"));
271 AddPreDefVal(TString("Lanczos3"));
272 AddPreDefVal(TString("Lanczos5"));
273 AddPreDefVal(TString("Lanczos8"));
274 AddPreDefVal(TString("Trim"));
275
276 DeclareOptionRef(fDeltaFrac , "DeltaFrac", "nEventsMin/Max for minmax and rms volume range");
277 DeclareOptionRef(fNEventsMin , "NEventsMin", "nEventsMin for adaptive volume range");
278 DeclareOptionRef(fNEventsMax , "NEventsMax", "nEventsMax for adaptive volume range");
279 DeclareOptionRef(fMaxVIterations, "MaxVIterations", "MaxVIterations for adaptive volume range");
280 DeclareOptionRef(fInitialScale , "InitialScale", "InitialScale for adaptive volume range");
281 DeclareOptionRef(fGaussSigma , "GaussSigma", "Width (wrt volume size) of Gaussian kernel estimator");
282 DeclareOptionRef(fNormTree , "NormTree", "Normalize binary search tree");
283}
284
285////////////////////////////////////////////////////////////////////////////////
286/// process the options specified by the user
287
289{
290 if (IgnoreEventsWithNegWeightsInTraining()) {
291 Log() << kFATAL << "Mechanism to ignore events with negative weights in training not yet available for method: "
292 << GetMethodTypeName()
293 << " --> please remove \"IgnoreNegWeightsInTraining\" option from booking string."
294 << Endl;
295 }
296
297 fGaussSigmaNorm = fGaussSigma; // * TMath::Sqrt( Double_t(GetNvar()) );
298
299 fVRangeMode = MethodPDERS::kUnsupported;
300
301 if (fVolumeRange == "MinMax" ) fVRangeMode = kMinMax;
302 else if (fVolumeRange == "RMS" ) fVRangeMode = kRMS;
303 else if (fVolumeRange == "Adaptive" ) fVRangeMode = kAdaptive;
304 else if (fVolumeRange == "Unscaled" ) fVRangeMode = kUnscaled;
305 else if (fVolumeRange == "kNN" ) fVRangeMode = kkNN;
306 else {
307 Log() << kFATAL << "VolumeRangeMode parameter '" << fVolumeRange << "' unknown" << Endl;
308 }
309
310 if (fKernelString == "Box" ) fKernelEstimator = kBox;
311 else if (fKernelString == "Sphere" ) fKernelEstimator = kSphere;
312 else if (fKernelString == "Teepee" ) fKernelEstimator = kTeepee;
313 else if (fKernelString == "Gauss" ) fKernelEstimator = kGauss;
314 else if (fKernelString == "Sinc3" ) fKernelEstimator = kSinc3;
315 else if (fKernelString == "Sinc5" ) fKernelEstimator = kSinc5;
316 else if (fKernelString == "Sinc7" ) fKernelEstimator = kSinc7;
317 else if (fKernelString == "Sinc9" ) fKernelEstimator = kSinc9;
318 else if (fKernelString == "Sinc11" ) fKernelEstimator = kSinc11;
319 else if (fKernelString == "Lanczos2" ) fKernelEstimator = kLanczos2;
320 else if (fKernelString == "Lanczos3" ) fKernelEstimator = kLanczos3;
321 else if (fKernelString == "Lanczos5" ) fKernelEstimator = kLanczos5;
322 else if (fKernelString == "Lanczos8" ) fKernelEstimator = kLanczos8;
323 else if (fKernelString == "Trim" ) fKernelEstimator = kTrim;
324 else {
325 Log() << kFATAL << "KernelEstimator parameter '" << fKernelString << "' unknown" << Endl;
326 }
327
328 // TODO: Add parameter validation
329
330 Log() << kVERBOSE << "interpreted option string: vRangeMethod: '"
331 << (const char*)((fVRangeMode == kMinMax) ? "MinMax" :
332 (fVRangeMode == kUnscaled) ? "Unscaled" :
333 (fVRangeMode == kRMS ) ? "RMS" : "Adaptive") << "'" << Endl;
334 if (fVRangeMode == kMinMax || fVRangeMode == kRMS)
335 Log() << kVERBOSE << "deltaFrac: " << fDeltaFrac << Endl;
336 else
337 Log() << kVERBOSE << "nEventsMin/Max, maxVIterations, initialScale: "
338 << fNEventsMin << " " << fNEventsMax
339 << " " << fMaxVIterations << " " << fInitialScale << Endl;
340 Log() << kVERBOSE << "KernelEstimator = " << fKernelString << Endl;
341}
342
343////////////////////////////////////////////////////////////////////////////////
344/// this is a dummy training: the preparation work to do is the construction
345/// of the binary tree as a pointer chain. It is easier to directly save the
346/// trainingTree in the weight file, and to rebuild the binary tree in the
347/// test phase from scratch
348
350{
351 if (IsNormalised()) Log() << kFATAL << "\"Normalise\" option cannot be used with PDERS; "
352 << "please remove the option from the configuration string, or "
353 << "use \"!Normalise\""
354 << Endl;
355
356 CreateBinarySearchTree( Types::kTraining );
357
358 CalcAverages();
359 SetVolumeElement();
360
361 fInitializedVolumeEle = kTRUE;
362}
363
364////////////////////////////////////////////////////////////////////////////////
365/// init the size of a volume element using a defined fraction of the
366/// volume containing the entire events
367
369{
370 if (fInitializedVolumeEle == kFALSE) {
371 fInitializedVolumeEle = kTRUE;
372
373 // binary trees must exist
374 assert( fBinaryTree );
375
376 CalcAverages();
377 SetVolumeElement();
378 }
379
380 // cannot determine error
381 NoErrorCalc(err, errUpper);
382
383 return this->CRScalc( *GetEvent() );
384}
385
386////////////////////////////////////////////////////////////////////////////////
387
388const std::vector< Float_t >& TMVA::MethodPDERS::GetRegressionValues()
389{
390 if (fRegressionReturnVal == 0) fRegressionReturnVal = new std::vector<Float_t>;
391 fRegressionReturnVal->clear();
392 // init the size of a volume element using a defined fraction of the
393 // volume containing the entire events
394 if (fInitializedVolumeEle == kFALSE) {
395 fInitializedVolumeEle = kTRUE;
396
397 // binary trees must exist
398 assert( fBinaryTree );
399
400 CalcAverages();
401
402 SetVolumeElement();
403 }
404
405 const Event* ev = GetEvent();
406 this->RRScalc( *ev, fRegressionReturnVal );
407
408 Event * evT = new Event(*ev);
409 UInt_t ivar = 0;
410 for (std::vector<Float_t>::iterator it = fRegressionReturnVal->begin(); it != fRegressionReturnVal->end(); ++it ) {
411 evT->SetTarget(ivar,(*it));
412 ivar++;
413 }
414
415 const Event* evT2 = GetTransformationHandler().InverseTransform( evT );
416 fRegressionReturnVal->clear();
417
418 for (ivar = 0; ivar<evT2->GetNTargets(); ivar++) {
419 fRegressionReturnVal->push_back(evT2->GetTarget(ivar));
420 }
421
422 delete evT;
423
424
425 return (*fRegressionReturnVal);
426}
427
428////////////////////////////////////////////////////////////////////////////////
429/// compute also average RMS values required for adaptive Gaussian
430
432{
433 if (fVRangeMode == kAdaptive || fVRangeMode == kRMS || fVRangeMode == kkNN ) {
434 fAverageRMS.clear();
435 fBinaryTree->CalcStatistics();
436
437 for (UInt_t ivar=0; ivar<GetNvar(); ivar++) {
438 if (!DoRegression()){ //why there are separate rms for signal and background?
439 Float_t rmsS = fBinaryTree->RMS(Types::kSignal, ivar);
440 Float_t rmsB = fBinaryTree->RMS(Types::kBackground, ivar);
441 fAverageRMS.push_back( (rmsS + rmsB)*0.5 );
442 } else {
443 Float_t rms = fBinaryTree->RMS( ivar );
444 fAverageRMS.push_back( rms );
445 }
446 }
447 }
448}
449
450////////////////////////////////////////////////////////////////////////////////
451/// create binary search trees for signal and background
452
454{
455 if (NULL != fBinaryTree) delete fBinaryTree;
456 fBinaryTree = new BinarySearchTree();
457 if (fNormTree) {
458 fBinaryTree->SetNormalize( kTRUE );
459 }
460
461 fBinaryTree->Fill( GetEventCollection(type) );
462
463 if (fNormTree) {
464 fBinaryTree->NormalizeTree();
465 }
466
467 if (!DoRegression()) {
468 // these are the signal and background scales for the weights
469 fScaleS = 1.0/fBinaryTree->GetSumOfWeights( Types::kSignal );
470 fScaleB = 1.0/fBinaryTree->GetSumOfWeights( Types::kBackground );
471
472 Log() << kVERBOSE << "Signal and background scales: " << fScaleS << " " << fScaleB << Endl;
473 }
474}
475
476////////////////////////////////////////////////////////////////////////////////
477/// defines volume dimensions
478
480 if (GetNvar()==0) {
481 Log() << kFATAL << "GetNvar() == 0" << Endl;
482 return;
483 }
484
485 // init relative scales
486 fkNNMin = Int_t(fNEventsMin);
487 fkNNMax = Int_t(fNEventsMax);
488
489 if (fDelta) delete fDelta;
490 if (fShift) delete fShift;
491 fDelta = new std::vector<Float_t>( GetNvar() );
492 fShift = new std::vector<Float_t>( GetNvar() );
493
494 for (UInt_t ivar=0; ivar<GetNvar(); ivar++) {
495 switch (fVRangeMode) {
496
497 case kRMS:
498 case kkNN:
499 case kAdaptive:
500 // sanity check
501 if (fAverageRMS.size() != GetNvar())
502 Log() << kFATAL << "<SetVolumeElement> RMS not computed: " << fAverageRMS.size() << Endl;
503 (*fDelta)[ivar] = fAverageRMS[ivar]*fDeltaFrac;
504 Log() << kVERBOSE << "delta of var[" << (*fInputVars)[ivar]
505 << "\t]: " << fAverageRMS[ivar]
506 << "\t | comp with |max - min|: " << (GetXmax( ivar ) - GetXmin( ivar ))
507 << Endl;
508 break;
509 case kMinMax:
510 (*fDelta)[ivar] = (GetXmax( ivar ) - GetXmin( ivar ))*fDeltaFrac;
511 break;
512 case kUnscaled:
513 (*fDelta)[ivar] = fDeltaFrac;
514 break;
515 default:
516 Log() << kFATAL << "<SetVolumeElement> unknown range-set mode: "
517 << fVRangeMode << Endl;
518 }
519 (*fShift)[ivar] = 0.5; // volume is centered around test value
520 }
521
522}
523
524////////////////////////////////////////////////////////////////////////////////
525/// Interface to RootFinder
526
528{
529 return ThisPDERS()->GetVolumeContentForRoot( scale );
530}
531
532////////////////////////////////////////////////////////////////////////////////
533/// count number of events in rescaled volume
534
536{
537 Volume v( *fHelpVolume );
538 v.ScaleInterval( scale );
539
540 Double_t count = GetBinaryTree()->SearchVolume( &v );
541
542 v.Delete();
543 return count;
544}
545
547 std::vector<const BinarySearchTreeNode*>& events,
548 Volume *volume )
549{
550 Float_t count = 0;
551
552 // -------------------------------------------------------------------------
553 //
554 // ==== test of volume search =====
555 //
556 // #define TMVA::MethodPDERS__countByHand__Debug__
557
558#ifdef TMVA_MethodPDERS__countByHand__Debug__
559
560 // starting values
561 count = fBinaryTree->SearchVolume( volume );
562
563 Int_t iS = 0, iB = 0;
564 UInt_t nvar = GetNvar();
565 for (UInt_t ievt_=0; ievt_<Data()->GetNTrainingEvents(); ievt_++) {
566 const Event * ev = GetTrainingEvent(ievt_);
567 Bool_t inV;
568 for (Int_t ivar=0; ivar<nvar; ivar++) {
569 Float_t x = ev->GetValue(ivar);
570 inV = (x > (*volume->Lower)[ivar] && x <= (*volume->Upper)[ivar]);
571 if (!inV) break;
572 }
573 if (inV) {
574 in++;
575 }
576 }
577 Log() << kVERBOSE << "debug: my test: " << in << Endl;// <- ***********tree
578 Log() << kVERBOSE << "debug: binTree: " << count << Endl << Endl;// <- ***********tree
579
580#endif
581
582 // -------------------------------------------------------------------------
583
584 if (fVRangeMode == kRMS || fVRangeMode == kMinMax || fVRangeMode == kUnscaled) { // Constant volume
585
586 std::vector<Double_t> *lb = new std::vector<Double_t>( GetNvar() );
587 for (UInt_t ivar=0; ivar<GetNvar(); ivar++) (*lb)[ivar] = e.GetValue(ivar);
588 std::vector<Double_t> *ub = new std::vector<Double_t>( *lb );
589 for (UInt_t ivar=0; ivar<GetNvar(); ivar++) {
590 (*lb)[ivar] -= (*fDelta)[ivar]*(1.0 - (*fShift)[ivar]);
591 (*ub)[ivar] += (*fDelta)[ivar]*(*fShift)[ivar];
592 }
593 Volume* svolume = new Volume( lb, ub );
594 // starting values
595
596 fBinaryTree->SearchVolume( svolume, &events );
597 }
598 else if (fVRangeMode == kAdaptive) { // adaptive volume
599
600 // -----------------------------------------------------------------------
601
602 // TODO: optimize, perhaps multi stage with broadening limits,
603 // or a different root finding method entirely,
604 if (MethodPDERS_UseFindRoot) {
605
606 // that won't need to search through large volume, where the bottle neck probably is
607
608 fHelpVolume = volume;
609
610 UpdateThis(); // necessary update of static pointer
611 RootFinder rootFinder( this, 0.01, 50, 200, 10 );
612 Double_t scale = rootFinder.Root( (fNEventsMin + fNEventsMax)/2.0 );
613
614 volume->ScaleInterval( scale );
615
616 fBinaryTree->SearchVolume( volume, &events );
617
618 fHelpVolume = NULL;
619 }
620 // -----------------------------------------------------------------------
621 else {
622
623 // starting values
624 count = fBinaryTree->SearchVolume( volume );
625
626 Float_t nEventsO = count;
627 Int_t i_=0;
628
629 while (nEventsO < fNEventsMin) { // this isn't a sain start... try again
630 volume->ScaleInterval( 1.15 );
631 count = fBinaryTree->SearchVolume( volume );
632 nEventsO = count;
633 i_++;
634 }
635 if (i_ > 50) Log() << kWARNING << "warning in event: " << e
636 << ": adaptive volume pre-adjustment reached "
637 << ">50 iterations in while loop (" << i_ << ")" << Endl;
638
640 Float_t nEventsE = 0.5*(fNEventsMin + fNEventsMax);
641 Float_t scaleO = 1.0;
642 Float_t scaleN = fInitialScale;
646
647 for (Int_t ic=1; ic<fMaxVIterations; ic++) {
648 if (nEventsN < fNEventsMin || nEventsN > fNEventsMax) {
649
650 // search for events in rescaled volume
651 Volume* v = new Volume( *volume );
652 v->ScaleInterval( scale );
653 nEventsN = fBinaryTree->SearchVolume( v );
654
655 // determine next iteration (linear approximation)
656 if (nEventsN > 1 && nEventsN - nEventsO != 0)
657 if (scaleN - scaleO != 0)
659 else
660 scale += (-0.01); // should not actually occur...
661 else
662 scale += 0.5; // use much larger volume
663
664 // save old scale
665 scaleN = scale;
666
667 // take if better (don't accept it if too small number of events)
669 (nEventsN >= fNEventsMin || nEventsBest < nEventsN)) {
672 }
673
674 v->Delete();
675 delete v;
676 }
677 else break;
678 }
679
680 // last sanity check
682 // include "1" to cover float precision
684 Log() << kWARNING << "warning in event " << e
685 << ": adaptive volume adjustment reached "
686 << "max. #iterations (" << fMaxVIterations << ")"
687 << "[ nEvents: " << nEventsN << " " << fNEventsMin << " " << fNEventsMax << "]"
688 << Endl;
689
690 volume->ScaleInterval( scaleBest );
691 fBinaryTree->SearchVolume( volume, &events );
692 }
693
694 // end of adaptive method
695
696 } else if (fVRangeMode == kkNN) {
697 Volume v(*volume);
698
699 events.clear();
700 // check number of signals in beginning volume
701 Int_t kNNcount = fBinaryTree->SearchVolumeWithMaxLimit( &v, &events, fkNNMax+1 );
702 //if this number is too large return fkNNMax+1
703
704 Int_t t_times = 0; // number of iterations
705
706 while ( !(kNNcount >= fkNNMin && kNNcount <= fkNNMax) ) {
707 if (kNNcount < fkNNMin) { //if we have too less points
708 Float_t scale = 2; //better scale needed
709 volume->ScaleInterval( scale );
710 }
711 else if (kNNcount > fkNNMax) { //if we have too many points
712 Float_t scale = 0.1; //better scale needed
713 volume->ScaleInterval( scale );
714 }
715 events.clear();
716
717 v = *volume ;
718
719 kNNcount = fBinaryTree->SearchVolumeWithMaxLimit( &v, &events, fkNNMax+1 ); //new search
720
721 t_times++;
722
723 if (t_times == fMaxVIterations) {
724 Log() << kWARNING << "warning in event" << e
725 << ": kNN volume adjustment reached "
726 << "max. #iterations (" << fMaxVIterations << ")"
727 << "[ kNN: " << fkNNMin << " " << fkNNMax << Endl;
728 break;
729 }
730 }
731
732 //vector to normalize distance in each dimension
733 Double_t *dim_normalization = new Double_t[GetNvar()];
734 for (UInt_t ivar=0; ivar<GetNvar(); ivar++) {
735 dim_normalization [ivar] = 1.0 / ((*v.fUpper)[ivar] - (*v.fLower)[ivar]);
736 }
737
738 std::vector<const BinarySearchTreeNode*> tempVector; // temporary vector for events
739
740 if (kNNcount >= fkNNMin) {
741 std::vector<Double_t> *distances = new std::vector<Double_t>( kNNcount );
742
743 //counting the distance for each event
744 for (Int_t j=0;j< Int_t(events.size()) ;j++)
745 (*distances)[j] = GetNormalizedDistance ( e, *events[j], dim_normalization );
746
747 //counting the fkNNMin-th element
748 std::vector<Double_t>::iterator wsk = distances->begin();
749 for (Int_t j=0;j<fkNNMin-1;++j) ++wsk;
750 std::nth_element( distances->begin(), wsk, distances->end() );
751
752 //getting all elements that are closer than fkNNMin-th element
753 //signals
754 for (Int_t j=0;j<Int_t(events.size());j++) {
755 Double_t dist = GetNormalizedDistance( e, *events[j], dim_normalization );
756
757 if (dist <= (*distances)[fkNNMin-1])
758 tempVector.push_back( events[j] );
759 }
760 fMax_distance = (*distances)[fkNNMin-1];
761 delete distances;
762 }
763 delete[] dim_normalization;
764 events = tempVector;
765
766 } else {
767
768 // troubles ahead...
769 Log() << kFATAL << "<GetSample> unknown RangeMode: " << fVRangeMode << Endl;
770 }
771 // -----------------------------------------------------------------------
772}
773
774////////////////////////////////////////////////////////////////////////////////
775
777{
778 std::vector<const BinarySearchTreeNode*> events;
779
780 // computes event weight by counting number of signal and background
781 // events (of reference sample) that are found within given volume
782 // defined by the event
783 std::vector<Double_t> *lb = new std::vector<Double_t>( GetNvar() );
784 for (UInt_t ivar=0; ivar<GetNvar(); ivar++) (*lb)[ivar] = e.GetValue(ivar);
785
786 std::vector<Double_t> *ub = new std::vector<Double_t>( *lb );
787 for (UInt_t ivar=0; ivar<GetNvar(); ivar++) {
788 (*lb)[ivar] -= (*fDelta)[ivar]*(1.0 - (*fShift)[ivar]);
789 (*ub)[ivar] += (*fDelta)[ivar]*(*fShift)[ivar];
790 }
791
792 Volume *volume = new Volume( lb, ub );
793
794 GetSample( e, events, volume );
795 Double_t count = CKernelEstimate( e, events, *volume );
796 delete volume;
797 delete lb;
798 delete ub;
799
800 return count;
801}
802
803////////////////////////////////////////////////////////////////////////////////
804
805void TMVA::MethodPDERS::RRScalc( const Event& e, std::vector<Float_t>* count )
806{
807 std::vector<const BinarySearchTreeNode*> events;
808
809 // computes event weight by counting number of signal and background
810 // events (of reference sample) that are found within given volume
811 // defined by the event
812 std::vector<Double_t> *lb = new std::vector<Double_t>( GetNvar() );
813 for (UInt_t ivar=0; ivar<GetNvar(); ivar++) (*lb)[ivar] = e.GetValue(ivar);
814
815 std::vector<Double_t> *ub = new std::vector<Double_t>( *lb );
816 for (UInt_t ivar=0; ivar<GetNvar(); ivar++) {
817 (*lb)[ivar] -= (*fDelta)[ivar]*(1.0 - (*fShift)[ivar]);
818 (*ub)[ivar] += (*fDelta)[ivar]*(*fShift)[ivar];
819 }
820 Volume *volume = new Volume( lb, ub );
821
822 GetSample( e, events, volume );
823 RKernelEstimate( e, events, *volume, count );
824
825 delete volume;
826
827 return;
828}
829////////////////////////////////////////////////////////////////////////////////
830/// normalization factors so we can work with radius 1 hyperspheres
831
833 std::vector<const BinarySearchTreeNode*>& events, Volume& v )
834{
835 Double_t *dim_normalization = new Double_t[GetNvar()];
836 for (UInt_t ivar=0; ivar<GetNvar(); ivar++)
837 dim_normalization [ivar] = 2 / ((*v.fUpper)[ivar] - (*v.fLower)[ivar]);
838
839 Double_t pdfSumS = 0;
840 Double_t pdfSumB = 0;
841
842 // Iteration over sample points
843 for (std::vector<const BinarySearchTreeNode*>::iterator iev = events.begin(); iev != events.end(); ++iev) {
844
845 // First switch to the one dimensional distance
846 Double_t normalized_distance = GetNormalizedDistance (event, *(*iev), dim_normalization);
847
848 // always working within the hyperelipsoid, except for when we don't
849 // note that rejection ratio goes to 1 as nvar goes to infinity
850 if (normalized_distance > 1 && fKernelEstimator != kBox) continue;
851
852 if ( (*iev)->GetClass()==fSignalClass )
853 pdfSumS += ApplyKernelFunction (normalized_distance) * (*iev)->GetWeight();
854 else
855 pdfSumB += ApplyKernelFunction (normalized_distance) * (*iev)->GetWeight();
856 }
857 pdfSumS = KernelNormalization( pdfSumS < 0. ? 0. : pdfSumS );
858 pdfSumB = KernelNormalization( pdfSumB < 0. ? 0. : pdfSumB );
859
860 delete[] dim_normalization;
861
862 if (pdfSumS < 1e-20 && pdfSumB < 1e-20) return 0.5;
863 if (pdfSumB < 1e-20) return 1.0;
864 if (pdfSumS < 1e-20) return 0.0;
865
866 Float_t r = pdfSumB*fScaleB/(pdfSumS*fScaleS);
867 return 1.0/(r + 1.0); // TODO: propagate errors from here
868}
869
870////////////////////////////////////////////////////////////////////////////////
871/// normalization factors so we can work with radius 1 hyperspheres
872
874 std::vector<const BinarySearchTreeNode*>& events, Volume& v,
875 std::vector<Float_t>* pdfSum )
876{
877 Double_t *dim_normalization = new Double_t[GetNvar()];
878 for (UInt_t ivar=0; ivar<GetNvar(); ivar++)
879 dim_normalization [ivar] = 2 / ((*v.fUpper)[ivar] - (*v.fLower)[ivar]);
880
881 // std::vector<Float_t> pdfSum;
882 pdfSum->clear();
883 Float_t pdfDiv = 0;
884 fNRegOut = 1; // for now, regression is just for 1 dimension
885
886 for (Int_t ivar = 0; ivar < fNRegOut ; ivar++)
887 pdfSum->push_back( 0 );
888
889 // Iteration over sample points
890 for (std::vector<const BinarySearchTreeNode*>::iterator iev = events.begin(); iev != events.end(); ++iev) {
891
892 // First switch to the one dimensional distance
893 Double_t normalized_distance = GetNormalizedDistance (event, *(*iev), dim_normalization);
894
895 // always working within the hyperelipsoid, except for when we don't
896 // note that rejection ratio goes to 1 as nvar goes to infinity
897 if (normalized_distance > 1 && fKernelEstimator != kBox) continue;
898
899 for (Int_t ivar = 0; ivar < fNRegOut ; ivar++) {
900 pdfSum->at(ivar) += ApplyKernelFunction (normalized_distance) * (*iev)->GetWeight() * (*iev)->GetTargets()[ivar];
901 pdfDiv += ApplyKernelFunction (normalized_distance) * (*iev)->GetWeight();
902 }
903 }
904
905 delete[] dim_normalization;
906
907 if (pdfDiv == 0)
908 return;
909
910 for (Int_t ivar = 0; ivar < fNRegOut ; ivar++)
911 pdfSum->at(ivar) /= pdfDiv;
912
913 return;
914}
915
916////////////////////////////////////////////////////////////////////////////////
917/// from the normalized euclidean distance calculate the distance
918/// for a certain kernel
919
921{
922 switch (fKernelEstimator) {
923 case kBox:
924 case kSphere:
925 return 1;
926 break;
927 case kTeepee:
928 return (1 - normalized_distance);
929 break;
930 case kGauss:
931 return TMath::Gaus( normalized_distance, 0, fGaussSigmaNorm, kFALSE);
932 break;
933 case kSinc3:
934 case kSinc5:
935 case kSinc7:
936 case kSinc9:
937 case kSinc11: {
938 Double_t side_crossings = 2 + ((int) fKernelEstimator) - ((int) kSinc3);
939 return NormSinc (side_crossings * normalized_distance);
940 }
941 break;
942 case kLanczos2:
943 return LanczosFilter (2, normalized_distance);
944 break;
945 case kLanczos3:
946 return LanczosFilter (3, normalized_distance);
947 break;
948 case kLanczos5:
949 return LanczosFilter (5, normalized_distance);
950 break;
951 case kLanczos8:
952 return LanczosFilter (8, normalized_distance);
953 break;
954 case kTrim: {
955 Double_t x = normalized_distance / fMax_distance;
956 x = 1 - x*x*x;
957 return x*x*x;
958 }
959 break;
960 default:
961 Log() << kFATAL << "Kernel estimation function unsupported. Enumerator is " << fKernelEstimator << Endl;
962 break;
963 }
964
965 return 0;
966}
967
968////////////////////////////////////////////////////////////////////////////////
969/// Calculating the normalization factor only once (might need a reset at some point.
970/// Can the method be restarted with different params?)
971
973{
974 // Caching jammed to disable function.
975 // It's not really useful after all, badly implemented and untested :-)
976 TTHREAD_TLS(Double_t) ret = 1.0;
977
978 if (ret != 0.0) return ret*pdf;
979
980 // We first normalize by the volume of the hypersphere.
981 switch (fKernelEstimator) {
982 case kBox:
983 case kSphere:
984 ret = 1.;
985 break;
986 case kTeepee:
987 ret = (GetNvar() * (GetNvar() + 1) * TMath::Gamma (((Double_t) GetNvar()) / 2.)) /
988 ( TMath::Power (2., (Double_t) GetNvar() + 1) * TMath::Power (TMath::Pi(), ((Double_t) GetNvar()) / 2.));
989 break;
990 case kGauss:
991 // We use full range integral here. Reasonable because of the fast function decay.
992 ret = 1. / TMath::Power ( 2 * TMath::Pi() * fGaussSigmaNorm * fGaussSigmaNorm, ((Double_t) GetNvar()) / 2.);
993 break;
994 case kSinc3:
995 case kSinc5:
996 case kSinc7:
997 case kSinc9:
998 case kSinc11:
999 case kLanczos2:
1000 case kLanczos3:
1001 case kLanczos5:
1002 case kLanczos8:
1003 // We use the full range integral here. Reasonable because the central lobe dominates it.
1004 ret = 1 / TMath::Power ( 2., (Double_t) GetNvar() );
1005 break;
1006 default:
1007 Log() << kFATAL << "Kernel estimation function unsupported. Enumerator is " << fKernelEstimator << Endl;
1008 }
1009
1010 // Normalizing by the full volume
1011 ret *= ( TMath::Power (2., static_cast<Int_t>(GetNvar())) * TMath::Gamma (1 + (((Double_t) GetNvar()) / 2.)) ) /
1012 TMath::Power (TMath::Pi(), ((Double_t) GetNvar()) / 2.);
1013
1014 return ret*pdf;
1015}
1016
1017////////////////////////////////////////////////////////////////////////////////
1018/// We use Euclidian metric here. Might not be best or most efficient.
1019
1023{
1024 Double_t ret=0;
1025 for (UInt_t ivar=0; ivar<GetNvar(); ivar++) {
1026 Double_t dist = dim_normalization[ivar] * (sample_event.GetEventV()[ivar] - base_event.GetValue(ivar));
1027 ret += dist*dist;
1028 }
1029 // DD 26.11.2008: bugfix: division by (GetNvar()) was missing for correct normalisation
1030 ret /= GetNvar();
1031 return TMath::Sqrt (ret);
1032}
1033
1034////////////////////////////////////////////////////////////////////////////////
1035/// NormSinc
1036
1038{
1039 if (x < 10e-10 && x > -10e-10) {
1040 return 1; // Poor man's l'Hopital
1041 }
1042
1043 Double_t pix = TMath::Pi() * x;
1045 Double_t ret;
1046
1047 if (GetNvar() % 2)
1048 ret = TMath::Power (sinc, static_cast<Int_t>(GetNvar()));
1049 else
1050 ret = TMath::Abs (sinc) * TMath::Power (sinc, static_cast<Int_t>(GetNvar() - 1));
1051
1052 return ret;
1053}
1054
1055////////////////////////////////////////////////////////////////////////////////
1056/// Lanczos Filter
1057
1059{
1060 if (x < 10e-10 && x > -10e-10) {
1061 return 1; // Poor man's l'Hopital
1062 }
1063
1064 Double_t pix = TMath::Pi() * x;
1065 Double_t pixtimesn = pix * ((Double_t) level);
1067 Double_t ret;
1068
1069 if (GetNvar() % 2) ret = TMath::Power (lanczos, static_cast<Int_t>(GetNvar()));
1070 else ret = TMath::Abs (lanczos) * TMath::Power (lanczos, static_cast<Int_t>(GetNvar() - 1));
1071
1072 return ret;
1073}
1074
1075////////////////////////////////////////////////////////////////////////////////
1076/// statistical error estimate for RS estimator
1077
1079 Float_t sumW2S, Float_t sumW2B ) const
1080{
1081 Float_t c = fScaleB/fScaleS;
1082 Float_t d = countS + c*countB; d *= d;
1083
1084 if (d < 1e-10) return 1; // Error is zero because of B = S = 0
1085
1086 Float_t f = c*c/d/d;
1088
1089 if (err < 1e-10) return 1; // Error is zero because of B or S = 0
1090
1091 return sqrt(err);
1092}
1093
1094////////////////////////////////////////////////////////////////////////////////
1095/// write weights to xml file
1096
1097void TMVA::MethodPDERS::AddWeightsXMLTo( void* parent ) const
1098{
1099 void* wght = gTools().AddChild(parent, "Weights");
1100 if (fBinaryTree)
1101 fBinaryTree->AddXMLTo(wght);
1102 else
1103 Log() << kFATAL << "Signal and background binary search tree not available" << Endl;
1104 //Log() << kFATAL << "Please implement writing of weights as XML" << Endl;
1105}
1106
1107////////////////////////////////////////////////////////////////////////////////
1108
1110{
1111 if (NULL != fBinaryTree) delete fBinaryTree;
1112 void* treenode = gTools().GetChild(wghtnode);
1114 if(!fBinaryTree)
1115 Log() << kFATAL << "Could not create BinarySearchTree from XML" << Endl;
1116 if(!fBinaryTree)
1117 Log() << kFATAL << "Could not create BinarySearchTree from XML" << Endl;
1118 fBinaryTree->SetPeriode( GetNvar() );
1119 fBinaryTree->CalcStatistics();
1120 fBinaryTree->CountNodes();
1121 if (fBinaryTree->GetSumOfWeights( Types::kSignal ) > 0)
1122 fScaleS = 1.0/fBinaryTree->GetSumOfWeights( Types::kSignal );
1123 else fScaleS = 1;
1124 if (fBinaryTree->GetSumOfWeights( Types::kBackground ) > 0)
1125 fScaleB = 1.0/fBinaryTree->GetSumOfWeights( Types::kBackground );
1126 else fScaleB = 1;
1127 Log() << kINFO << "signal and background scales: " << fScaleS << " " << fScaleB << Endl;
1128 CalcAverages();
1129 SetVolumeElement();
1130 fInitializedVolumeEle = kTRUE;
1131}
1132
1133////////////////////////////////////////////////////////////////////////////////
1134/// read weight info from file
1135
1137{
1138 if (NULL != fBinaryTree) delete fBinaryTree;
1139
1140 fBinaryTree = new BinarySearchTree();
1141
1142 istr >> *fBinaryTree;
1143
1144 fBinaryTree->SetPeriode( GetNvar() );
1145
1146 fBinaryTree->CalcStatistics();
1147
1148 fBinaryTree->CountNodes();
1149
1150 // these are the signal and background scales for the weights
1151 fScaleS = 1.0/fBinaryTree->GetSumOfWeights( Types::kSignal );
1152 fScaleB = 1.0/fBinaryTree->GetSumOfWeights( Types::kBackground );
1153
1154 Log() << kINFO << "signal and background scales: " << fScaleS << " " << fScaleB << Endl;
1155
1156 CalcAverages();
1157
1158 SetVolumeElement();
1159
1160 fInitializedVolumeEle = kTRUE;
1161}
1162
1163////////////////////////////////////////////////////////////////////////////////
1164/// write training sample (TTree) to file
1165
1169
1170////////////////////////////////////////////////////////////////////////////////
1171/// read training sample from file
1172
1176
1177////////////////////////////////////////////////////////////////////////////////
1178/// static pointer to this object
1179
1181{
1182 return GetMethodPDERSThreadLocal();
1183}
1184////////////////////////////////////////////////////////////////////////////////
1185/// update static this pointer
1186
1188{
1189 GetMethodPDERSThreadLocal() = this;
1190}
1191
1192////////////////////////////////////////////////////////////////////////////////
1193/// write specific classifier response
1194
1195void TMVA::MethodPDERS::MakeClassSpecific( std::ostream& fout, const TString& className ) const
1196{
1197 fout << " // not implemented for class: \"" << className << "\"" << std::endl;
1198 fout << "};" << std::endl;
1199}
1200
1201////////////////////////////////////////////////////////////////////////////////
1202/// get help message text
1203///
1204/// typical length of text line:
1205/// "|--------------------------------------------------------------|"
1206
1208{
1209 Log() << Endl;
1210 Log() << gTools().Color("bold") << "--- Short description:" << gTools().Color("reset") << Endl;
1211 Log() << Endl;
1212 Log() << "PDERS is a generalization of the projective likelihood classifier " << Endl;
1213 Log() << "to N dimensions, where N is the number of input variables used." << Endl;
1214 Log() << "In its adaptive form it is mostly equivalent to k-Nearest-Neighbor" << Endl;
1215 Log() << "(k-NN) methods. If the multidimensional PDF for signal and background" << Endl;
1216 Log() << "were known, this classifier would exploit the full information" << Endl;
1217 Log() << "contained in the input variables, and would hence be optimal. In " << Endl;
1218 Log() << "practice however, huge training samples are necessary to sufficiently " << Endl;
1219 Log() << "populate the multidimensional phase space. " << Endl;
1220 Log() << Endl;
1221 Log() << "The simplest implementation of PDERS counts the number of signal" << Endl;
1222 Log() << "and background events in the vicinity of a test event, and returns" << Endl;
1223 Log() << "a weight according to the majority species of the neighboring events." << Endl;
1224 Log() << "A more involved version of PDERS (selected by the option \"KernelEstimator\")" << Endl;
1225 Log() << "uses Kernel estimation methods to approximate the shape of the PDF." << Endl;
1226 Log() << Endl;
1227 Log() << gTools().Color("bold") << "--- Performance optimisation:" << gTools().Color("reset") << Endl;
1228 Log() << Endl;
1229 Log() << "PDERS can be very powerful in case of strongly non-linear problems, " << Endl;
1230 Log() << "e.g., distinct islands of signal and background regions. Because of " << Endl;
1231 Log() << "the exponential growth of the phase space, it is important to restrict" << Endl;
1232 Log() << "the number of input variables (dimension) to the strictly necessary." << Endl;
1233 Log() << Endl;
1234 Log() << "Note that PDERS is a slowly responding classifier. Moreover, the necessity" << Endl;
1235 Log() << "to store the entire binary tree in memory, to avoid accessing virtual " << Endl;
1236 Log() << "memory, limits the number of training events that can effectively be " << Endl;
1237 Log() << "used to model the multidimensional PDF." << Endl;
1238 Log() << Endl;
1239 Log() << gTools().Color("bold") << "--- Performance tuning via configuration options:" << gTools().Color("reset") << Endl;
1240 Log() << Endl;
1241 Log() << "If the PDERS response is found too slow when using the adaptive volume " << Endl;
1242 Log() << "size (option \"VolumeRangeMode=Adaptive\"), it might be found beneficial" << Endl;
1243 Log() << "to reduce the number of events required in the volume, and/or to enlarge" << Endl;
1244 Log() << "the allowed range (\"NeventsMin/Max\"). PDERS is relatively insensitive" << Endl;
1245 Log() << "to the width (\"GaussSigma\") of the Gaussian kernel (if used)." << Endl;
1246}
@ kBox
Definition Buttons.h:29
#define REGISTER_METHOD(CLASS)
for example
#define d(i)
Definition RSha256.hxx:102
#define f(i)
Definition RSha256.hxx:104
#define c(i)
Definition RSha256.hxx:101
#define e(i)
Definition RSha256.hxx:103
bool Bool_t
Boolean (0=false, 1=true) (bool)
Definition RtypesCore.h:78
int Int_t
Signed integer 4 bytes (int)
Definition RtypesCore.h:60
float Float_t
Float 4 bytes (float)
Definition RtypesCore.h:72
constexpr Bool_t kFALSE
Definition RtypesCore.h:109
double Double_t
Double 8 bytes.
Definition RtypesCore.h:74
constexpr Bool_t kTRUE
Definition RtypesCore.h:108
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 pix
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 r
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 Atom_t Time_t type
const_iterator begin() const
const_iterator end() const
A file, usually with extension .root, that stores data and code in the form of serialized objects in ...
Definition TFile.h:130
Node for the BinarySearch or Decision Trees.
A simple Binary search tree including a volume search method.
static BinarySearchTree * CreateFromXML(void *node, UInt_t tmva_Version_Code=262657)
re-create a new tree (decision tree or search tree) from XML
Class that contains all the data information.
Definition DataSetInfo.h:62
Virtual base Class for all MVA method.
Definition MethodBase.h:82
This is a generalization of the above Likelihood methods to dimensions, where is the number of inpu...
Definition MethodPDERS.h:61
void ReadWeightsFromXML(void *wghtnode) override
void DeclareOptions() override
define the options (their key words) that can be set in the option string.
void GetHelpMessage() const override
get help message text
void WriteWeightsToStream(TFile &rf) const
write training sample (TTree) to file
void CreateBinarySearchTree(Types::ETreeType type)
create binary search trees for signal and background
BinarySearchTree * fBinaryTree
binary tree
void MakeClassSpecific(std::ostream &, const TString &) const override
write specific classifier response
virtual ~MethodPDERS(void)
destructor
MethodPDERS(const TString &jobName, const TString &methodTitle, DataSetInfo &theData, const TString &theOption)
standard constructor for the PDERS method
void GetSample(const Event &e, std::vector< const BinarySearchTreeNode * > &events, Volume *volume)
void ReadWeightsFromStream(std::istream &istr) override
read weight info from file
void ProcessOptions() override
process the options specified by the user
void AddWeightsXMLTo(void *parent) const override
write weights to xml file
Float_t GetError(Float_t countS, Float_t countB, Float_t sumW2S, Float_t sumW2B) const
statistical error estimate for RS estimator
static MethodPDERS * ThisPDERS(void)
static pointer to this object
Double_t GetMvaValue(Double_t *err=nullptr, Double_t *errUpper=nullptr) override
init the size of a volume element using a defined fraction of the volume containing the entire events
void Train(void) override
this is a dummy training: the preparation work to do is the construction of the binary tree as a poin...
Double_t KernelNormalization(Double_t pdf)
Calculating the normalization factor only once (might need a reset at some point.
void RRScalc(const Event &, std::vector< Float_t > *count)
void UpdateThis()
update static this pointer
Double_t CRScalc(const Event &)
void Init(void) override
default initialisation routine called by all constructors
void CalcAverages()
compute also average RMS values required for adaptive Gaussian
void RKernelEstimate(const Event &, std::vector< const BinarySearchTreeNode * > &, Volume &, std::vector< Float_t > *pdfSum)
normalization factors so we can work with radius 1 hyperspheres
Double_t NormSinc(Double_t x)
NormSinc.
void SetVolumeElement(void)
defines volume dimensions
const std::vector< Float_t > & GetRegressionValues() override
Double_t LanczosFilter(Int_t level, Double_t x)
Lanczos Filter.
Bool_t HasAnalysisType(Types::EAnalysisType type, UInt_t numberClasses, UInt_t numberTargets) override
PDERS can handle classification with 2 classes and regression with one or more regression-targets.
Double_t CKernelEstimate(const Event &, std::vector< const BinarySearchTreeNode * > &, Volume &)
normalization factors so we can work with radius 1 hyperspheres
Double_t ApplyKernelFunction(Double_t normalized_distance)
from the normalized euclidean distance calculate the distance for a certain kernel
Double_t GetNormalizedDistance(const TMVA::Event &base_event, const BinarySearchTreeNode &sample_event, Double_t *dim_normalization)
We use Euclidian metric here. Might not be best or most efficient.
static Double_t IGetVolumeContentForRoot(Double_t)
Interface to RootFinder.
Double_t GetVolumeContentForRoot(Double_t)
count number of events in rescaled volume
Root finding using Brents algorithm (translated from CERNLIB function RZERO)
Definition RootFinder.h:48
const TString & Color(const TString &)
human readable color strings
Definition Tools.cxx:803
void * GetChild(void *parent, const char *childname=nullptr)
get child node
Definition Tools.cxx:1125
void * AddChild(void *parent, const char *childname, const char *content=nullptr, bool isRootNode=false)
add child node
Definition Tools.cxx:1099
Singleton class for Global types used by TMVA.
Definition Types.h:71
@ kSignal
Never change this number - it is elsewhere assumed to be zero !
Definition Types.h:135
@ kBackground
Definition Types.h:136
@ kClassification
Definition Types.h:127
@ kRegression
Definition Types.h:128
@ kTraining
Definition Types.h:143
Volume for BinarySearchTree.
Definition Volume.h:47
void ScaleInterval(Double_t f)
"scale" the volume by symmetrically blowing up the interval in each dimension
Definition Volume.cxx:180
const Bool_t MethodPDERS_UseFindRoot
Basic string class.
Definition TString.h:138
Double_t x[n]
Definition legend1.C:17
create variable transformations
Tools & gTools()
MsgLogger & Endl(MsgLogger &ml)
Definition MsgLogger.h:148
Double_t Gaus(Double_t x, Double_t mean=0, Double_t sigma=1, Bool_t norm=kFALSE)
Calculates a gaussian function with mean and sigma.
Definition TMath.cxx:471
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 Gamma(Double_t z)
Computation of gamma(z) for all z.
Definition TMath.cxx:353
constexpr Double_t Pi()
Definition TMath.h:40
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:122