91 const Bool_t MethodPDERS_UseFindRoot = kFALSE;
95 REGISTER_METHOD(PDERS)
97 ClassImp(TMVA::MethodPDERS);
102 TMVA::MethodPDERS::MethodPDERS( const TString& jobName,
103 const TString& methodTitle,
104 DataSetInfo& theData,
105 const TString& theOption) :
106 MethodBase( jobName, Types::kPDERS, methodTitle, theData, theOption),
108 fVRangeMode(kAdaptive),
109 fKernelEstimator(kBox),
122 fInitializedVolumeEle(0),
136 TMVA::MethodPDERS::MethodPDERS( DataSetInfo& theData,
137 const TString& theWeightFile) :
138 MethodBase( Types::kPDERS, theData, theWeightFile),
140 fVRangeMode(kAdaptive),
141 fKernelEstimator(kBox),
154 fInitializedVolumeEle(0),
168 Bool_t TMVA::MethodPDERS::HasAnalysisType( Types::EAnalysisType type, UInt_t numberClasses, UInt_t )
170 if (type == Types::kClassification && numberClasses == 2)
return kTRUE;
171 if (type == Types::kRegression)
return kTRUE;
178 void TMVA::MethodPDERS::Init(
void )
186 fVRangeMode = kAdaptive;
187 fKernelEstimator = kBox;
192 fMaxVIterations = 150;
193 fInitialScale = 0.99;
197 fkNNMin = Int_t(fNEventsMin);
198 fkNNMax = Int_t(fNEventsMax);
200 fInitializedVolumeEle = kFALSE;
204 SetSignalReferenceCut( 0.0 );
210 TMVA::MethodPDERS::~MethodPDERS(
void )
212 if (fDelta)
delete fDelta;
213 if (fShift)
delete fShift;
215 if (NULL != fBinaryTree)
delete fBinaryTree;
254 void TMVA::MethodPDERS::DeclareOptions()
256 DeclareOptionRef(fVolumeRange=
"Adaptive",
"VolumeRangeMode",
"Method to determine volume size");
257 AddPreDefVal(TString(
"Unscaled"));
258 AddPreDefVal(TString(
"MinMax"));
259 AddPreDefVal(TString(
"RMS"));
260 AddPreDefVal(TString(
"Adaptive"));
261 AddPreDefVal(TString(
"kNN"));
263 DeclareOptionRef(fKernelString=
"Box",
"KernelEstimator",
"Kernel estimation function");
264 AddPreDefVal(TString(
"Box"));
265 AddPreDefVal(TString(
"Sphere"));
266 AddPreDefVal(TString(
"Teepee"));
267 AddPreDefVal(TString(
"Gauss"));
268 AddPreDefVal(TString(
"Sinc3"));
269 AddPreDefVal(TString(
"Sinc5"));
270 AddPreDefVal(TString(
"Sinc7"));
271 AddPreDefVal(TString(
"Sinc9"));
272 AddPreDefVal(TString(
"Sinc11"));
273 AddPreDefVal(TString(
"Lanczos2"));
274 AddPreDefVal(TString(
"Lanczos3"));
275 AddPreDefVal(TString(
"Lanczos5"));
276 AddPreDefVal(TString(
"Lanczos8"));
277 AddPreDefVal(TString(
"Trim"));
279 DeclareOptionRef(fDeltaFrac ,
"DeltaFrac",
"nEventsMin/Max for minmax and rms volume range");
280 DeclareOptionRef(fNEventsMin ,
"NEventsMin",
"nEventsMin for adaptive volume range");
281 DeclareOptionRef(fNEventsMax ,
"NEventsMax",
"nEventsMax for adaptive volume range");
282 DeclareOptionRef(fMaxVIterations,
"MaxVIterations",
"MaxVIterations for adaptive volume range");
283 DeclareOptionRef(fInitialScale ,
"InitialScale",
"InitialScale for adaptive volume range");
284 DeclareOptionRef(fGaussSigma ,
"GaussSigma",
"Width (wrt volume size) of Gaussian kernel estimator");
285 DeclareOptionRef(fNormTree ,
"NormTree",
"Normalize binary search tree");
291 void TMVA::MethodPDERS::ProcessOptions()
293 if (IgnoreEventsWithNegWeightsInTraining()) {
294 Log() << kFATAL <<
"Mechanism to ignore events with negative weights in training not yet available for method: "
295 << GetMethodTypeName()
296 <<
" --> please remove \"IgnoreNegWeightsInTraining\" option from booking string."
300 fGaussSigmaNorm = fGaussSigma;
302 fVRangeMode = MethodPDERS::kUnsupported;
304 if (fVolumeRange ==
"MinMax" ) fVRangeMode = kMinMax;
305 else if (fVolumeRange ==
"RMS" ) fVRangeMode = kRMS;
306 else if (fVolumeRange ==
"Adaptive" ) fVRangeMode = kAdaptive;
307 else if (fVolumeRange ==
"Unscaled" ) fVRangeMode = kUnscaled;
308 else if (fVolumeRange ==
"kNN" ) fVRangeMode = kkNN;
310 Log() << kFATAL <<
"VolumeRangeMode parameter '" << fVolumeRange <<
"' unknown" << Endl;
313 if (fKernelString ==
"Box" ) fKernelEstimator = kBox;
314 else if (fKernelString ==
"Sphere" ) fKernelEstimator = kSphere;
315 else if (fKernelString ==
"Teepee" ) fKernelEstimator = kTeepee;
316 else if (fKernelString ==
"Gauss" ) fKernelEstimator = kGauss;
317 else if (fKernelString ==
"Sinc3" ) fKernelEstimator = kSinc3;
318 else if (fKernelString ==
"Sinc5" ) fKernelEstimator = kSinc5;
319 else if (fKernelString ==
"Sinc7" ) fKernelEstimator = kSinc7;
320 else if (fKernelString ==
"Sinc9" ) fKernelEstimator = kSinc9;
321 else if (fKernelString ==
"Sinc11" ) fKernelEstimator = kSinc11;
322 else if (fKernelString ==
"Lanczos2" ) fKernelEstimator = kLanczos2;
323 else if (fKernelString ==
"Lanczos3" ) fKernelEstimator = kLanczos3;
324 else if (fKernelString ==
"Lanczos5" ) fKernelEstimator = kLanczos5;
325 else if (fKernelString ==
"Lanczos8" ) fKernelEstimator = kLanczos8;
326 else if (fKernelString ==
"Trim" ) fKernelEstimator = kTrim;
328 Log() << kFATAL <<
"KernelEstimator parameter '" << fKernelString <<
"' unknown" << Endl;
333 Log() << kVERBOSE <<
"interpreted option string: vRangeMethod: '"
334 << (
const char*)((fVRangeMode == kMinMax) ?
"MinMax" :
335 (fVRangeMode == kUnscaled) ?
"Unscaled" :
336 (fVRangeMode == kRMS ) ?
"RMS" :
"Adaptive") <<
"'" << Endl;
337 if (fVRangeMode == kMinMax || fVRangeMode == kRMS)
338 Log() << kVERBOSE <<
"deltaFrac: " << fDeltaFrac << Endl;
340 Log() << kVERBOSE <<
"nEventsMin/Max, maxVIterations, initialScale: "
341 << fNEventsMin <<
" " << fNEventsMax
342 <<
" " << fMaxVIterations <<
" " << fInitialScale << Endl;
343 Log() << kVERBOSE <<
"KernelEstimator = " << fKernelString << Endl;
352 void TMVA::MethodPDERS::Train(
void )
354 if (IsNormalised()) Log() << kFATAL <<
"\"Normalise\" option cannot be used with PDERS; "
355 <<
"please remove the option from the configuration string, or "
356 <<
"use \"!Normalise\""
359 CreateBinarySearchTree( Types::kTraining );
364 fInitializedVolumeEle = kTRUE;
372 Double_t TMVA::MethodPDERS::GetMvaValue( Double_t* err, Double_t* errUpper )
374 if (fInitializedVolumeEle == kFALSE) {
375 fInitializedVolumeEle = kTRUE;
378 assert( fBinaryTree );
385 NoErrorCalc(err, errUpper);
387 return this->CRScalc( *GetEvent() );
392 const std::vector< Float_t >& TMVA::MethodPDERS::GetRegressionValues()
394 if (fRegressionReturnVal == 0) fRegressionReturnVal =
new std::vector<Float_t>;
395 fRegressionReturnVal->clear();
398 if (fInitializedVolumeEle == kFALSE) {
399 fInitializedVolumeEle = kTRUE;
402 assert( fBinaryTree );
409 const Event* ev = GetEvent();
410 this->RRScalc( *ev, fRegressionReturnVal );
412 Event * evT =
new Event(*ev);
414 for (std::vector<Float_t>::iterator it = fRegressionReturnVal->begin(); it != fRegressionReturnVal->end(); ++it ) {
415 evT->SetTarget(ivar,(*it));
419 const Event* evT2 = GetTransformationHandler().InverseTransform( evT );
420 fRegressionReturnVal->clear();
422 for (ivar = 0; ivar<evT2->GetNTargets(); ivar++) {
423 fRegressionReturnVal->push_back(evT2->GetTarget(ivar));
429 return (*fRegressionReturnVal);
435 void TMVA::MethodPDERS::CalcAverages()
437 if (fVRangeMode == kAdaptive || fVRangeMode == kRMS || fVRangeMode == kkNN ) {
439 fBinaryTree->CalcStatistics();
441 for (UInt_t ivar=0; ivar<GetNvar(); ivar++) {
442 if (!DoRegression()){
443 Float_t rmsS = fBinaryTree->RMS(Types::kSignal, ivar);
444 Float_t rmsB = fBinaryTree->RMS(Types::kBackground, ivar);
445 fAverageRMS.push_back( (rmsS + rmsB)*0.5 );
447 Float_t rms = fBinaryTree->RMS( ivar );
448 fAverageRMS.push_back( rms );
457 void TMVA::MethodPDERS::CreateBinarySearchTree( Types::ETreeType type )
459 if (NULL != fBinaryTree)
delete fBinaryTree;
460 fBinaryTree =
new BinarySearchTree();
462 fBinaryTree->SetNormalize( kTRUE );
465 fBinaryTree->Fill( GetEventCollection(type) );
468 fBinaryTree->NormalizeTree();
471 if (!DoRegression()) {
473 fScaleS = 1.0/fBinaryTree->GetSumOfWeights( Types::kSignal );
474 fScaleB = 1.0/fBinaryTree->GetSumOfWeights( Types::kBackground );
476 Log() << kVERBOSE <<
"Signal and background scales: " << fScaleS <<
" " << fScaleB << Endl;
483 void TMVA::MethodPDERS::SetVolumeElement(
void ) {
485 Log() << kFATAL <<
"GetNvar() == 0" << Endl;
490 fkNNMin = Int_t(fNEventsMin);
491 fkNNMax = Int_t(fNEventsMax);
493 if (fDelta)
delete fDelta;
494 if (fShift)
delete fShift;
495 fDelta =
new std::vector<Float_t>( GetNvar() );
496 fShift =
new std::vector<Float_t>( GetNvar() );
498 for (UInt_t ivar=0; ivar<GetNvar(); ivar++) {
499 switch (fVRangeMode) {
505 if (fAverageRMS.size() != GetNvar())
506 Log() << kFATAL <<
"<SetVolumeElement> RMS not computed: " << fAverageRMS.size() << Endl;
507 (*fDelta)[ivar] = fAverageRMS[ivar]*fDeltaFrac;
508 Log() << kVERBOSE <<
"delta of var[" << (*fInputVars)[ivar]
509 <<
"\t]: " << fAverageRMS[ivar]
510 <<
"\t | comp with |max - min|: " << (GetXmax( ivar ) - GetXmin( ivar ))
514 (*fDelta)[ivar] = (GetXmax( ivar ) - GetXmin( ivar ))*fDeltaFrac;
517 (*fDelta)[ivar] = fDeltaFrac;
520 Log() << kFATAL <<
"<SetVolumeElement> unknown range-set mode: "
521 << fVRangeMode << Endl;
523 (*fShift)[ivar] = 0.5;
531 Double_t TMVA::MethodPDERS::IGetVolumeContentForRoot( Double_t scale )
533 return ThisPDERS()->GetVolumeContentForRoot( scale );
539 Double_t TMVA::MethodPDERS::GetVolumeContentForRoot( Double_t scale )
541 Volume v( *fHelpVolume );
542 v.ScaleInterval( scale );
544 Double_t count = GetBinaryTree()->SearchVolume( &v );
550 void TMVA::MethodPDERS::GetSample(
const Event& e,
551 std::vector<const BinarySearchTreeNode*>& events,
562 #ifdef TMVA_MethodPDERS__countByHand__Debug__
565 count = fBinaryTree->SearchVolume( volume );
567 Int_t iS = 0, iB = 0;
568 UInt_t nvar = GetNvar();
569 for (UInt_t ievt_=0; ievt_<Data()->GetNTrainingEvents(); ievt_++) {
570 const Event * ev = GetTrainingEvent(ievt_);
572 for (Int_t ivar=0; ivar<nvar; ivar++) {
573 Float_t x = ev->GetValue(ivar);
574 inV = (x > (*volume->Lower)[ivar] && x <= (*volume->Upper)[ivar]);
581 Log() << kVERBOSE <<
"debug: my test: " << in << Endl;
582 Log() << kVERBOSE <<
"debug: binTree: " << count << Endl << Endl;
588 if (fVRangeMode == kRMS || fVRangeMode == kMinMax || fVRangeMode == kUnscaled) {
590 std::vector<Double_t> *lb =
new std::vector<Double_t>( GetNvar() );
591 for (UInt_t ivar=0; ivar<GetNvar(); ivar++) (*lb)[ivar] = e.GetValue(ivar);
592 std::vector<Double_t> *ub =
new std::vector<Double_t>( *lb );
593 for (UInt_t ivar=0; ivar<GetNvar(); ivar++) {
594 (*lb)[ivar] -= (*fDelta)[ivar]*(1.0 - (*fShift)[ivar]);
595 (*ub)[ivar] += (*fDelta)[ivar]*(*fShift)[ivar];
597 Volume* svolume =
new Volume( lb, ub );
600 fBinaryTree->SearchVolume( svolume, &events );
602 else if (fVRangeMode == kAdaptive) {
608 if (MethodPDERS_UseFindRoot) {
612 fHelpVolume = volume;
615 RootFinder rootFinder(
this, 0.01, 50, 200, 10 );
616 Double_t scale = rootFinder.Root( (fNEventsMin + fNEventsMax)/2.0 );
618 volume->ScaleInterval( scale );
620 fBinaryTree->SearchVolume( volume, &events );
628 count = fBinaryTree->SearchVolume( volume );
630 Float_t nEventsO = count;
633 while (nEventsO < fNEventsMin) {
634 volume->ScaleInterval( 1.15 );
635 count = fBinaryTree->SearchVolume( volume );
639 if (i_ > 50) Log() << kWARNING <<
"warning in event: " << e
640 <<
": adaptive volume pre-adjustment reached "
641 <<
">50 iterations in while loop (" << i_ <<
")" << Endl;
643 Float_t nEventsN = nEventsO;
644 Float_t nEventsE = 0.5*(fNEventsMin + fNEventsMax);
645 Float_t scaleO = 1.0;
646 Float_t scaleN = fInitialScale;
647 Float_t scale = scaleN;
648 Float_t scaleBest = scaleN;
649 Float_t nEventsBest = nEventsN;
651 for (Int_t ic=1; ic<fMaxVIterations; ic++) {
652 if (nEventsN < fNEventsMin || nEventsN > fNEventsMax) {
655 Volume* v =
new Volume( *volume );
656 v->ScaleInterval( scale );
657 nEventsN = fBinaryTree->SearchVolume( v );
660 if (nEventsN > 1 && nEventsN - nEventsO != 0)
661 if (scaleN - scaleO != 0)
662 scale += (scaleN - scaleO)/(nEventsN - nEventsO)*(nEventsE - nEventsN);
672 if (TMath::Abs(nEventsN - nEventsE) < TMath::Abs(nEventsBest - nEventsE) &&
673 (nEventsN >= fNEventsMin || nEventsBest < nEventsN)) {
674 nEventsBest = nEventsN;
685 nEventsN = nEventsBest;
687 if (nEventsN < fNEventsMin-1 || nEventsN > fNEventsMax+1)
688 Log() << kWARNING <<
"warning in event " << e
689 <<
": adaptive volume adjustment reached "
690 <<
"max. #iterations (" << fMaxVIterations <<
")"
691 <<
"[ nEvents: " << nEventsN <<
" " << fNEventsMin <<
" " << fNEventsMax <<
"]"
694 volume->ScaleInterval( scaleBest );
695 fBinaryTree->SearchVolume( volume, &events );
700 }
else if (fVRangeMode == kkNN) {
705 Int_t kNNcount = fBinaryTree->SearchVolumeWithMaxLimit( &v, &events, fkNNMax+1 );
710 while ( !(kNNcount >= fkNNMin && kNNcount <= fkNNMax) ) {
711 if (kNNcount < fkNNMin) {
713 volume->ScaleInterval( scale );
715 else if (kNNcount > fkNNMax) {
717 volume->ScaleInterval( scale );
723 kNNcount = fBinaryTree->SearchVolumeWithMaxLimit( &v, &events, fkNNMax+1 );
727 if (t_times == fMaxVIterations) {
728 Log() << kWARNING <<
"warning in event" << e
729 <<
": kNN volume adjustment reached "
730 <<
"max. #iterations (" << fMaxVIterations <<
")"
731 <<
"[ kNN: " << fkNNMin <<
" " << fkNNMax << Endl;
737 Double_t *dim_normalization =
new Double_t[GetNvar()];
738 for (UInt_t ivar=0; ivar<GetNvar(); ivar++) {
739 dim_normalization [ivar] = 1.0 / ((*v.fUpper)[ivar] - (*v.fLower)[ivar]);
742 std::vector<const BinarySearchTreeNode*> tempVector;
744 if (kNNcount >= fkNNMin) {
745 std::vector<Double_t> *distances =
new std::vector<Double_t>( kNNcount );
748 for (Int_t j=0;j< Int_t(events.size()) ;j++)
749 (*distances)[j] = GetNormalizedDistance ( e, *events[j], dim_normalization );
752 std::vector<Double_t>::iterator wsk = distances->begin();
753 for (Int_t j=0;j<fkNNMin-1;++j) ++wsk;
754 std::nth_element( distances->begin(), wsk, distances->end() );
758 for (Int_t j=0;j<Int_t(events.size());j++) {
759 Double_t dist = GetNormalizedDistance( e, *events[j], dim_normalization );
761 if (dist <= (*distances)[fkNNMin-1])
762 tempVector.push_back( events[j] );
764 fMax_distance = (*distances)[fkNNMin-1];
767 delete[] dim_normalization;
773 Log() << kFATAL <<
"<GetSample> unknown RangeMode: " << fVRangeMode << Endl;
780 Double_t TMVA::MethodPDERS::CRScalc(
const Event& e )
782 std::vector<const BinarySearchTreeNode*> events;
787 std::vector<Double_t> *lb =
new std::vector<Double_t>( GetNvar() );
788 for (UInt_t ivar=0; ivar<GetNvar(); ivar++) (*lb)[ivar] = e.GetValue(ivar);
790 std::vector<Double_t> *ub =
new std::vector<Double_t>( *lb );
791 for (UInt_t ivar=0; ivar<GetNvar(); ivar++) {
792 (*lb)[ivar] -= (*fDelta)[ivar]*(1.0 - (*fShift)[ivar]);
793 (*ub)[ivar] += (*fDelta)[ivar]*(*fShift)[ivar];
796 Volume *volume =
new Volume( lb, ub );
798 GetSample( e, events, volume );
799 Double_t count = CKernelEstimate( e, events, *volume );
809 void TMVA::MethodPDERS::RRScalc(
const Event& e, std::vector<Float_t>* count )
811 std::vector<const BinarySearchTreeNode*> events;
816 std::vector<Double_t> *lb =
new std::vector<Double_t>( GetNvar() );
817 for (UInt_t ivar=0; ivar<GetNvar(); ivar++) (*lb)[ivar] = e.GetValue(ivar);
819 std::vector<Double_t> *ub =
new std::vector<Double_t>( *lb );
820 for (UInt_t ivar=0; ivar<GetNvar(); ivar++) {
821 (*lb)[ivar] -= (*fDelta)[ivar]*(1.0 - (*fShift)[ivar]);
822 (*ub)[ivar] += (*fDelta)[ivar]*(*fShift)[ivar];
824 Volume *volume =
new Volume( lb, ub );
826 GetSample( e, events, volume );
827 RKernelEstimate( e, events, *volume, count );
836 Double_t TMVA::MethodPDERS::CKernelEstimate(
const Event & event,
837 std::vector<const BinarySearchTreeNode*>& events, Volume& v )
839 Double_t *dim_normalization =
new Double_t[GetNvar()];
840 for (UInt_t ivar=0; ivar<GetNvar(); ivar++)
841 dim_normalization [ivar] = 2 / ((*v.fUpper)[ivar] - (*v.fLower)[ivar]);
843 Double_t pdfSumS = 0;
844 Double_t pdfSumB = 0;
847 for (std::vector<const BinarySearchTreeNode*>::iterator iev = events.begin(); iev != events.end(); ++iev) {
850 Double_t normalized_distance = GetNormalizedDistance (event, *(*iev), dim_normalization);
854 if (normalized_distance > 1 && fKernelEstimator != kBox)
continue;
856 if ( (*iev)->GetClass()==fSignalClass )
857 pdfSumS += ApplyKernelFunction (normalized_distance) * (*iev)->GetWeight();
859 pdfSumB += ApplyKernelFunction (normalized_distance) * (*iev)->GetWeight();
861 pdfSumS = KernelNormalization( pdfSumS < 0. ? 0. : pdfSumS );
862 pdfSumB = KernelNormalization( pdfSumB < 0. ? 0. : pdfSumB );
864 delete[] dim_normalization;
866 if (pdfSumS < 1e-20 && pdfSumB < 1e-20)
return 0.5;
867 if (pdfSumB < 1e-20)
return 1.0;
868 if (pdfSumS < 1e-20)
return 0.0;
870 Float_t r = pdfSumB*fScaleB/(pdfSumS*fScaleS);
871 return 1.0/(r + 1.0);
877 void TMVA::MethodPDERS::RKernelEstimate(
const Event & event,
878 std::vector<const BinarySearchTreeNode*>& events, Volume& v,
879 std::vector<Float_t>* pdfSum )
881 Double_t *dim_normalization =
new Double_t[GetNvar()];
882 for (UInt_t ivar=0; ivar<GetNvar(); ivar++)
883 dim_normalization [ivar] = 2 / ((*v.fUpper)[ivar] - (*v.fLower)[ivar]);
890 for (Int_t ivar = 0; ivar < fNRegOut ; ivar++)
891 pdfSum->push_back( 0 );
894 for (std::vector<const BinarySearchTreeNode*>::iterator iev = events.begin(); iev != events.end(); ++iev) {
897 Double_t normalized_distance = GetNormalizedDistance (event, *(*iev), dim_normalization);
901 if (normalized_distance > 1 && fKernelEstimator != kBox)
continue;
903 for (Int_t ivar = 0; ivar < fNRegOut ; ivar++) {
904 pdfSum->at(ivar) += ApplyKernelFunction (normalized_distance) * (*iev)->GetWeight() * (*iev)->GetTargets()[ivar];
905 pdfDiv += ApplyKernelFunction (normalized_distance) * (*iev)->GetWeight();
909 delete[] dim_normalization;
914 for (Int_t ivar = 0; ivar < fNRegOut ; ivar++)
915 pdfSum->at(ivar) /= pdfDiv;
924 Double_t TMVA::MethodPDERS::ApplyKernelFunction (Double_t normalized_distance)
926 switch (fKernelEstimator) {
932 return (1 - normalized_distance);
935 return TMath::Gaus( normalized_distance, 0, fGaussSigmaNorm, kFALSE);
942 Double_t side_crossings = 2 + ((int) fKernelEstimator) - ((int) kSinc3);
943 return NormSinc (side_crossings * normalized_distance);
947 return LanczosFilter (2, normalized_distance);
950 return LanczosFilter (3, normalized_distance);
953 return LanczosFilter (5, normalized_distance);
956 return LanczosFilter (8, normalized_distance);
959 Double_t x = normalized_distance / fMax_distance;
965 Log() << kFATAL <<
"Kernel estimation function unsupported. Enumerator is " << fKernelEstimator << Endl;
976 Double_t TMVA::MethodPDERS::KernelNormalization (Double_t pdf)
980 TTHREAD_TLS(Double_t) ret = 1.0;
982 if (ret != 0.0) return ret*pdf;
985 switch (fKernelEstimator) {
991 ret = (GetNvar() * (GetNvar() + 1) * TMath::Gamma (((Double_t) GetNvar()) / 2.)) /
992 ( TMath::Power (2., (Double_t) GetNvar() + 1) * TMath::Power (TMath::Pi(), ((Double_t) GetNvar()) / 2.));
996 ret = 1. / TMath::Power ( 2 * TMath::Pi() * fGaussSigmaNorm * fGaussSigmaNorm, ((Double_t) GetNvar()) / 2.);
1008 ret = 1 / TMath::Power ( 2., (Double_t) GetNvar() );
1011 Log() << kFATAL <<
"Kernel estimation function unsupported. Enumerator is " << fKernelEstimator << Endl;
1015 ret *= ( TMath::Power (2., static_cast<Int_t>(GetNvar())) * TMath::Gamma (1 + (((Double_t) GetNvar()) / 2.)) ) /
1016 TMath::Power (TMath::Pi(), ((Double_t) GetNvar()) / 2.);
1024 Double_t TMVA::MethodPDERS::GetNormalizedDistance (
const Event &base_event,
1025 const BinarySearchTreeNode &sample_event,
1026 Double_t *dim_normalization)
1029 for (UInt_t ivar=0; ivar<GetNvar(); ivar++) {
1030 Double_t dist = dim_normalization[ivar] * (sample_event.GetEventV()[ivar] - base_event.GetValue(ivar));
1035 return TMath::Sqrt (ret);
1041 Double_t TMVA::MethodPDERS::NormSinc (Double_t x)
1043 if (x < 10e-10 && x > -10e-10) {
1047 Double_t pix = TMath::Pi() * x;
1048 Double_t sinc = TMath::Sin(pix) / pix;
1052 ret = TMath::Power (sinc, static_cast<Int_t>(GetNvar()));
1054 ret = TMath::Abs (sinc) * TMath::Power (sinc, static_cast<Int_t>(GetNvar() - 1));
1062 Double_t TMVA::MethodPDERS::LanczosFilter (Int_t level, Double_t x)
1064 if (x < 10e-10 && x > -10e-10) {
1068 Double_t pix = TMath::Pi() * x;
1069 Double_t pixtimesn = pix * ((Double_t) level);
1070 Double_t lanczos = (TMath::Sin(pix) / pix) * (TMath::Sin(pixtimesn) / pixtimesn);
1073 if (GetNvar() % 2) ret = TMath::Power (lanczos, static_cast<Int_t>(GetNvar()));
1074 else ret = TMath::Abs (lanczos) * TMath::Power (lanczos, static_cast<Int_t>(GetNvar() - 1));
1082 Float_t TMVA::MethodPDERS::GetError( Float_t countS, Float_t countB,
1083 Float_t sumW2S, Float_t sumW2B )
const
1085 Float_t c = fScaleB/fScaleS;
1086 Float_t d = countS + c*countB; d *= d;
1088 if (d < 1e-10)
return 1;
1090 Float_t f = c*c/d/d;
1091 Float_t err = f*countB*countB*sumW2S + f*countS*countS*sumW2B;
1093 if (err < 1e-10)
return 1;
1101 void TMVA::MethodPDERS::AddWeightsXMLTo(
void* parent )
const
1103 void* wght = gTools().AddChild(parent,
"Weights");
1105 fBinaryTree->AddXMLTo(wght);
1107 Log() << kFATAL <<
"Signal and background binary search tree not available" << Endl;
1113 void TMVA::MethodPDERS::ReadWeightsFromXML(
void* wghtnode)
1115 if (NULL != fBinaryTree)
delete fBinaryTree;
1116 void* treenode = gTools().GetChild(wghtnode);
1117 fBinaryTree = TMVA::BinarySearchTree::CreateFromXML(treenode);
1119 Log() << kFATAL <<
"Could not create BinarySearchTree from XML" << Endl;
1121 Log() << kFATAL <<
"Could not create BinarySearchTree from XML" << Endl;
1122 fBinaryTree->SetPeriode( GetNvar() );
1123 fBinaryTree->CalcStatistics();
1124 fBinaryTree->CountNodes();
1125 if (fBinaryTree->GetSumOfWeights( Types::kSignal ) > 0)
1126 fScaleS = 1.0/fBinaryTree->GetSumOfWeights( Types::kSignal );
1128 if (fBinaryTree->GetSumOfWeights( Types::kBackground ) > 0)
1129 fScaleB = 1.0/fBinaryTree->GetSumOfWeights( Types::kBackground );
1131 Log() << kINFO <<
"signal and background scales: " << fScaleS <<
" " << fScaleB << Endl;
1134 fInitializedVolumeEle = kTRUE;
1140 void TMVA::MethodPDERS::ReadWeightsFromStream( std::istream& istr)
1142 if (NULL != fBinaryTree)
delete fBinaryTree;
1144 fBinaryTree =
new BinarySearchTree();
1146 istr >> *fBinaryTree;
1148 fBinaryTree->SetPeriode( GetNvar() );
1150 fBinaryTree->CalcStatistics();
1152 fBinaryTree->CountNodes();
1155 fScaleS = 1.0/fBinaryTree->GetSumOfWeights( Types::kSignal );
1156 fScaleB = 1.0/fBinaryTree->GetSumOfWeights( Types::kBackground );
1158 Log() << kINFO <<
"signal and background scales: " << fScaleS <<
" " << fScaleB << Endl;
1164 fInitializedVolumeEle = kTRUE;
1170 void TMVA::MethodPDERS::WriteWeightsToStream( TFile& )
const
1177 void TMVA::MethodPDERS::ReadWeightsFromStream( TFile& )
1184 TMVA::MethodPDERS* TMVA::MethodPDERS::ThisPDERS(
void )
1186 return GetMethodPDERSThreadLocal();
1191 void TMVA::MethodPDERS::UpdateThis(
void )
1193 GetMethodPDERSThreadLocal() =
this;
1199 void TMVA::MethodPDERS::MakeClassSpecific( std::ostream& fout,
const TString& className )
const
1201 fout <<
" // not implemented for class: \"" << className <<
"\"" << std::endl;
1202 fout <<
"};" << std::endl;
1211 void TMVA::MethodPDERS::GetHelpMessage()
const
1214 Log() << gTools().Color(
"bold") <<
"--- Short description:" << gTools().Color(
"reset") << Endl;
1216 Log() <<
"PDERS is a generalization of the projective likelihood classifier " << Endl;
1217 Log() <<
"to N dimensions, where N is the number of input variables used." << Endl;
1218 Log() <<
"In its adaptive form it is mostly equivalent to k-Nearest-Neighbor" << Endl;
1219 Log() <<
"(k-NN) methods. If the multidimensional PDF for signal and background" << Endl;
1220 Log() <<
"were known, this classifier would exploit the full information" << Endl;
1221 Log() <<
"contained in the input variables, and would hence be optimal. In " << Endl;
1222 Log() <<
"practice however, huge training samples are necessary to sufficiently " << Endl;
1223 Log() <<
"populate the multidimensional phase space. " << Endl;
1225 Log() <<
"The simplest implementation of PDERS counts the number of signal" << Endl;
1226 Log() <<
"and background events in the vicinity of a test event, and returns" << Endl;
1227 Log() <<
"a weight according to the majority species of the neighboring events." << Endl;
1228 Log() <<
"A more involved version of PDERS (selected by the option \"KernelEstimator\")" << Endl;
1229 Log() <<
"uses Kernel estimation methods to approximate the shape of the PDF." << Endl;
1231 Log() << gTools().Color(
"bold") <<
"--- Performance optimisation:" << gTools().Color(
"reset") << Endl;
1233 Log() <<
"PDERS can be very powerful in case of strongly non-linear problems, " << Endl;
1234 Log() <<
"e.g., distinct islands of signal and background regions. Because of " << Endl;
1235 Log() <<
"the exponential growth of the phase space, it is important to restrict" << Endl;
1236 Log() <<
"the number of input variables (dimension) to the strictly necessary." << Endl;
1238 Log() <<
"Note that PDERS is a slowly responding classifier. Moreover, the necessity" << Endl;
1239 Log() <<
"to store the entire binary tree in memory, to avoid accessing virtual " << Endl;
1240 Log() <<
"memory, limits the number of training events that can effectively be " << Endl;
1241 Log() <<
"used to model the multidimensional PDF." << Endl;
1243 Log() << gTools().Color(
"bold") <<
"--- Performance tuning via configuration options:" << gTools().Color(
"reset") << Endl;
1245 Log() <<
"If the PDERS response is found too slow when using the adaptive volume " << Endl;
1246 Log() <<
"size (option \"VolumeRangeMode=Adaptive\"), it might be found beneficial" << Endl;
1247 Log() <<
"to reduce the number of events required in the volume, and/or to enlarge" << Endl;
1248 Log() <<
"the allowed range (\"NeventsMin/Max\"). PDERS is relatively insensitive" << Endl;
1249 Log() <<
"to the width (\"GaussSigma\") of the Gaussian kernel (if used)." << Endl;