Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
Factory.cxx
Go to the documentation of this file.
1// @(#)Root/tmva $Id$
2// Author: Andreas Hoecker, Peter Speckmayer, Joerg Stelzer, Helge Voss, Kai Voss, Eckhard von Toerne, Jan Therhaag
3// Updated by: Omar Zapata, Kim Albertsson
4/**********************************************************************************
5 * Project: TMVA - a Root-integrated toolkit for multivariate data analysis *
6 * Package: TMVA *
7 * Class : Factory *
8 * *
9 * *
10 * Description: *
11 * Implementation (see header for description) *
12 * *
13 * Authors : *
14 * Andreas Hoecker <Andreas.Hocker@cern.ch> - CERN, Switzerland *
15 * Joerg Stelzer <stelzer@cern.ch> - DESY, Germany *
16 * Peter Speckmayer <peter.speckmayer@cern.ch> - CERN, Switzerland *
17 * Jan Therhaag <Jan.Therhaag@cern.ch> - U of Bonn, Germany *
18 * Eckhard v. Toerne <evt@uni-bonn.de> - U of Bonn, Germany *
19 * Helge Voss <Helge.Voss@cern.ch> - MPI-K Heidelberg, Germany *
20 * Kai Voss <Kai.Voss@cern.ch> - U. of Victoria, Canada *
21 * Omar Zapata <Omar.Zapata@cern.ch> - UdeA/ITM Colombia *
22 * Lorenzo Moneta <Lorenzo.Moneta@cern.ch> - CERN, Switzerland *
23 * Sergei Gleyzer <Sergei.Gleyzer@cern.ch> - U of Florida & CERN *
24 * Kim Albertsson <kim.albertsson@cern.ch> - LTU & CERN *
25 * *
26 * Copyright (c) 2005-2015: *
27 * CERN, Switzerland *
28 * U. of Victoria, Canada *
29 * MPI-K Heidelberg, Germany *
30 * U. of Bonn, Germany *
31 * UdeA/ITM, Colombia *
32 * U. of Florida, USA *
33 * *
34 * Redistribution and use in source and binary forms, with or without *
35 * modification, are permitted according to the terms listed in LICENSE *
36 * (see tmva/doc/LICENSE) *
37 **********************************************************************************/
38
39/*! \class TMVA::Factory
40\ingroup TMVA
41
42This is the main MVA steering class.
43It creates all MVA methods, and guides them through the training, testing and
44evaluation phases.
45*/
46
47#include "TMVA/Factory.h"
48
50#include "TMVA/Config.h"
51#include "TMVA/Configurable.h"
52#include "TMVA/Tools.h"
53#include "TMVA/Ranking.h"
54#include "TMVA/DataSet.h"
55#include "TMVA/IMethod.h"
56#include "TMVA/MethodBase.h"
58#include "TMVA/DataSetManager.h"
59#include "TMVA/DataSetInfo.h"
60#include "TMVA/DataLoader.h"
61#include "TMVA/MethodBoost.h"
62#include "TMVA/MethodCategory.h"
63#include "TMVA/ROCCalc.h"
64#include "TMVA/ROCCurve.h"
65#include "TMVA/MsgLogger.h"
66
67#include "TMVA/VariableInfo.h"
69
70#include "TMVA/Results.h"
74
75#include "TMVA/Types.h"
76
77#include "TROOT.h"
78#include "TFile.h"
79#include "TH2.h"
80#include "TGraph.h"
81#include "TStyle.h"
82#include "TPrincipal.h"
83#include "TMath.h"
84#include "TSystem.h"
85#include "TCanvas.h"
86#include "TMultiGraph.h"
87
88#include <bitset>
89#include <list>
90#include <set>
91
93// const Int_t MinNoTestEvents = 1;
94
95
96#define READXML kTRUE
97
98// number of bits for bitset
99#define VIBITS 32
100
101////////////////////////////////////////////////////////////////////////////////
102/// Standard constructor.
103///
104/// - jobname : this name will appear in all weight file names produced by the MVAs
105/// - theTargetFile : output ROOT file; the test tree and all evaluation plots
106/// will be stored here
107/// - theOption : option string; currently: "V" for verbose
108
110 : Configurable(theOption), fTransformations("I"), fVerbose(kFALSE), fVerboseLevel(kINFO), fCorrelations(kFALSE),
111 fROC(kTRUE), fSilentFile(theTargetFile == nullptr), fJobName(jobName), fAnalysisType(Types::kClassification),
112 fModelPersistence(kTRUE)
113{
114 fName = "Factory";
117
118 // render silent
119 if (gTools().CheckForSilentOption(GetOptions()))
120 Log().InhibitOutput(); // make sure is silent if wanted to
121
122 // init configurable
123 SetConfigDescription("Configuration options for Factory running");
125
126 // histograms are not automatically associated with the current
127 // directory and hence don't go out of scope when closing the file
128 // TH1::AddDirectory(kFALSE);
130#ifdef WIN32
131 // under Windows, switch progress bar and color off by default, as the typical windows shell doesn't handle these
132 // (would need different sequences..)
133 Bool_t color = kFALSE;
135#else
136 Bool_t color = !gROOT->IsBatch();
138#endif
139 DeclareOptionRef(fVerbose, "V", "Verbose flag");
140 DeclareOptionRef(fVerboseLevel = TString("Info"), "VerboseLevel", "VerboseLevel (Debug/Verbose/Info)");
141 AddPreDefVal(TString("Debug"));
142 AddPreDefVal(TString("Verbose"));
143 AddPreDefVal(TString("Info"));
144 DeclareOptionRef(color, "Color", "Flag for coloured screen output (default: True, if in batch mode: False)");
146 fTransformations, "Transformations",
147 "List of transformations to test; formatting example: \"Transformations=I;D;P;U;G,D\", for identity, "
148 "decorrelation, PCA, Uniform and Gaussianisation followed by decorrelation transformations");
149 DeclareOptionRef(fCorrelations, "Correlations", "boolean to show correlation in output");
150 DeclareOptionRef(fROC, "ROC", "boolean to show ROC in output");
151 DeclareOptionRef(silent, "Silent",
152 "Batch mode: boolean silent flag inhibiting any output from TMVA after the creation of the factory "
153 "class object (default: False)");
154 DeclareOptionRef(drawProgressBar, "DrawProgressBar",
155 "Draw progress bar to display training, testing and evaluation schedule (default: True)");
156 DeclareOptionRef(fModelPersistence, "ModelPersistence",
157 "Option to save the trained model in xml file or using serialization");
158
159 TString analysisType("Auto");
160 DeclareOptionRef(analysisType, "AnalysisType",
161 "Set the analysis type (Classification, Regression, Multiclass, Auto) (default: Auto)");
162 AddPreDefVal(TString("Classification"));
163 AddPreDefVal(TString("Regression"));
164 AddPreDefVal(TString("Multiclass"));
165 AddPreDefVal(TString("Auto"));
166
167 ParseOptions();
169
170 if (Verbose())
171 fLogger->SetMinType(kVERBOSE);
172 if (fVerboseLevel.CompareTo("Debug") == 0)
173 fLogger->SetMinType(kDEBUG);
174 if (fVerboseLevel.CompareTo("Verbose") == 0)
175 fLogger->SetMinType(kVERBOSE);
176 if (fVerboseLevel.CompareTo("Info") == 0)
177 fLogger->SetMinType(kINFO);
178
179 // global settings
180 gConfig().SetUseColor(color);
183
184 analysisType.ToLower();
185 if (analysisType == "classification")
187 else if (analysisType == "regression")
189 else if (analysisType == "multiclass")
191 else if (analysisType == "auto")
193
194 // Greetings();
195}
196
197////////////////////////////////////////////////////////////////////////////////
198/// Constructor.
199
201 : Configurable(theOption), fTransformations("I"), fVerbose(kFALSE), fCorrelations(kFALSE), fROC(kTRUE),
202 fSilentFile(kTRUE), fJobName(jobName), fAnalysisType(Types::kClassification), fModelPersistence(kTRUE)
203{
204 fName = "Factory";
205 fgTargetFile = nullptr;
207
208 // render silent
209 if (gTools().CheckForSilentOption(GetOptions()))
210 Log().InhibitOutput(); // make sure is silent if wanted to
211
212 // init configurable
213 SetConfigDescription("Configuration options for Factory running");
215
216 // histograms are not automatically associated with the current
217 // directory and hence don't go out of scope when closing the file
220#ifdef WIN32
221 // under Windows, switch progress bar and color off by default, as the typical windows shell doesn't handle these
222 // (would need different sequences..)
223 Bool_t color = kFALSE;
225#else
226 Bool_t color = !gROOT->IsBatch();
228#endif
229 DeclareOptionRef(fVerbose, "V", "Verbose flag");
230 DeclareOptionRef(fVerboseLevel = TString("Info"), "VerboseLevel", "VerboseLevel (Debug/Verbose/Info)");
231 AddPreDefVal(TString("Debug"));
232 AddPreDefVal(TString("Verbose"));
233 AddPreDefVal(TString("Info"));
234 DeclareOptionRef(color, "Color", "Flag for coloured screen output (default: True, if in batch mode: False)");
236 fTransformations, "Transformations",
237 "List of transformations to test; formatting example: \"Transformations=I;D;P;U;G,D\", for identity, "
238 "decorrelation, PCA, Uniform and Gaussianisation followed by decorrelation transformations");
239 DeclareOptionRef(fCorrelations, "Correlations", "boolean to show correlation in output");
240 DeclareOptionRef(fROC, "ROC", "boolean to show ROC in output");
241 DeclareOptionRef(silent, "Silent",
242 "Batch mode: boolean silent flag inhibiting any output from TMVA after the creation of the factory "
243 "class object (default: False)");
244 DeclareOptionRef(drawProgressBar, "DrawProgressBar",
245 "Draw progress bar to display training, testing and evaluation schedule (default: True)");
246 DeclareOptionRef(fModelPersistence, "ModelPersistence",
247 "Option to save the trained model in xml file or using serialization");
248
249 TString analysisType("Auto");
250 DeclareOptionRef(analysisType, "AnalysisType",
251 "Set the analysis type (Classification, Regression, Multiclass, Auto) (default: Auto)");
252 AddPreDefVal(TString("Classification"));
253 AddPreDefVal(TString("Regression"));
254 AddPreDefVal(TString("Multiclass"));
255 AddPreDefVal(TString("Auto"));
256
257 ParseOptions();
259
260 if (Verbose())
261 fLogger->SetMinType(kVERBOSE);
262 if (fVerboseLevel.CompareTo("Debug") == 0)
263 fLogger->SetMinType(kDEBUG);
264 if (fVerboseLevel.CompareTo("Verbose") == 0)
265 fLogger->SetMinType(kVERBOSE);
266 if (fVerboseLevel.CompareTo("Info") == 0)
267 fLogger->SetMinType(kINFO);
268
269 // global settings
270 gConfig().SetUseColor(color);
273
274 analysisType.ToLower();
275 if (analysisType == "classification")
277 else if (analysisType == "regression")
279 else if (analysisType == "multiclass")
281 else if (analysisType == "auto")
283
284 Greetings();
285}
286
287////////////////////////////////////////////////////////////////////////////////
288/// Print welcome message.
289/// Options are: kLogoWelcomeMsg, kIsometricWelcomeMsg, kLeanWelcomeMsg
290
292{
293 gTools().ROOTVersionMessage(Log());
294 gTools().TMVAWelcomeMessage(Log(), gTools().kLogoWelcomeMsg);
295 gTools().TMVAVersionMessage(Log());
296 Log() << Endl;
297}
298
299////////////////////////////////////////////////////////////////////////////////
300/// Destructor.
301
303{
304 std::vector<TMVA::VariableTransformBase *>::iterator trfIt = fDefaultTrfs.begin();
305 for (; trfIt != fDefaultTrfs.end(); ++trfIt)
306 delete (*trfIt);
307
308 this->DeleteAllMethods();
309
310 // problem with call of REGISTER_METHOD macro ...
311 // ClassifierFactory::DestroyInstance();
312 // Types::DestroyInstance();
313 // Tools::DestroyInstance();
314 // Config::DestroyInstance();
315}
316
317////////////////////////////////////////////////////////////////////////////////
318/// Delete methods.
319
321{
322 std::map<TString, MVector *>::iterator itrMap;
323
324 for (itrMap = fMethodsMap.begin(); itrMap != fMethodsMap.end(); ++itrMap) {
325 MVector *methods = itrMap->second;
326 // delete methods
327 MVector::iterator itrMethod = methods->begin();
328 for (; itrMethod != methods->end(); ++itrMethod) {
329 Log() << kDEBUG << "Delete method: " << (*itrMethod)->GetName() << Endl;
330 delete (*itrMethod);
331 }
332 methods->clear();
333 delete methods;
334 }
335}
336
337////////////////////////////////////////////////////////////////////////////////
338
340{
341 fVerbose = v;
342}
343
344////////////////////////////////////////////////////////////////////////////////
345/// Books an MVA classifier or regression method. The option configuration
346/// string is custom for each MVA. The TString field `theNameAppendix` serves to
347/// define (and distinguish) several instances of a given MVA, e.g., when one
348/// wants to compare the performance of various configurations
349///
350/// The method is identified by `theMethodName`, which can be provided either as:
351/// - a string containing the method's name, or
352/// - a `TMVA::Types::EMVA` enum value (automatically converted to the corresponding method name).
353
355 TString methodTitle, TString theOption)
356{
357 if (fModelPersistence)
358 gSystem->MakeDirectory(loader->GetName()); // creating directory for DataLoader output
359
360 TString datasetname = loader->GetName();
361
362 if (fAnalysisType == Types::kNoAnalysisType) {
363 if (loader->GetDataSetInfo().GetNClasses() == 2 && loader->GetDataSetInfo().GetClassInfo("Signal") != NULL &&
364 loader->GetDataSetInfo().GetClassInfo("Background") != NULL) {
365 fAnalysisType = Types::kClassification; // default is classification
366 } else if (loader->GetDataSetInfo().GetNClasses() >= 2) {
367 fAnalysisType = Types::kMulticlass; // if two classes, but not named "Signal" and "Background"
368 } else
369 Log() << kFATAL << "No analysis type for " << loader->GetDataSetInfo().GetNClasses() << " classes and "
370 << loader->GetDataSetInfo().GetNTargets() << " regression targets." << Endl;
371 }
372
373 // booking via name; the names are translated into enums and the
374 // corresponding overloaded BookMethod is called
375
376 if (fMethodsMap.find(datasetname) != fMethodsMap.end()) {
377 if (GetMethod(datasetname, methodTitle) != 0) {
378 Log() << kFATAL << "Booking failed since method with title <" << methodTitle << "> already exists "
379 << "in with DataSet Name <" << loader->GetName() << "> " << Endl;
380 }
381 }
382
383 Log() << kHEADER << "Booking method: " << gTools().Color("bold")
384 << methodTitle
385 // << gTools().Color("reset")<<" DataSet Name: "<<gTools().Color("bold")<<loader->GetName()
386 << gTools().Color("reset") << Endl << Endl;
387
388 // interpret option string with respect to a request for boosting (i.e., BostNum > 0)
389 Int_t boostNum = 0;
391 conf->DeclareOptionRef(boostNum = 0, "Boost_num", "Number of times the classifier will be boosted");
392 conf->ParseOptions();
393 delete conf;
394 // this is name of weight file directory
396 if (fModelPersistence) {
397 // find prefix in fWeightFileDir;
399 fileDir = prefix;
400 if (!prefix.IsNull())
401 if (fileDir[fileDir.Length() - 1] != '/')
402 fileDir += "/";
403 fileDir += loader->GetName();
405 }
406 // initialize methods
407 IMethod *im;
408 if (!boostNum) {
409 im = ClassifierFactory::Instance().Create(theMethodName.tString().Data(), fJobName, methodTitle, loader->GetDataSetInfo(),
410 theOption);
411 } else {
412 // boosted classifier, requires a specific definition, making it transparent for the user
413 Log() << kDEBUG << "Boost Number is " << boostNum << " > 0: train boosted classifier" << Endl;
414 im = ClassifierFactory::Instance().Create("Boost", fJobName, methodTitle, loader->GetDataSetInfo(), theOption);
415 MethodBoost *methBoost = dynamic_cast<MethodBoost *>(im); // DSMTEST divided into two lines
416 if (!methBoost) { // DSMTEST
417 Log() << kFATAL << "Method with type kBoost cannot be casted to MethodCategory. /Factory" << Endl; // DSMTEST
418 return nullptr;
419 }
420 if (fModelPersistence)
421 methBoost->SetWeightFileDir(fileDir);
422 methBoost->SetModelPersistence(fModelPersistence);
423 methBoost->SetBoostedMethodName(theMethodName.tString()); // DSMTEST divided into two lines
424 methBoost->fDataSetManager = loader->GetDataSetInfo().GetDataSetManager(); // DSMTEST
425 methBoost->SetFile(fgTargetFile);
426 methBoost->SetSilentFile(IsSilentFile());
427 }
428
429 MethodBase *method = dynamic_cast<MethodBase *>(im);
430 if (method == 0)
431 return 0; // could not create method
432
433 // set fDataSetManager if MethodCategory (to enable Category to create datasetinfo objects) // DSMTEST
434 if (method->GetMethodType() == Types::kCategory) { // DSMTEST
435 MethodCategory *methCat = (dynamic_cast<MethodCategory *>(im)); // DSMTEST
436 if (!methCat) { // DSMTEST
437 Log() << kFATAL << "Method with type kCategory cannot be casted to MethodCategory. /Factory"
438 << Endl; // DSMTEST
439 return nullptr;
440 }
441 if (fModelPersistence)
442 methCat->SetWeightFileDir(fileDir);
443 methCat->SetModelPersistence(fModelPersistence);
444 methCat->fDataSetManager = loader->GetDataSetInfo().GetDataSetManager(); // DSMTEST
445 methCat->SetFile(fgTargetFile);
446 methCat->SetSilentFile(IsSilentFile());
447 } // DSMTEST
448
449 if (!method->HasAnalysisType(fAnalysisType, loader->GetDataSetInfo().GetNClasses(),
450 loader->GetDataSetInfo().GetNTargets())) {
451 Log() << kWARNING << "Method " << method->GetMethodTypeName() << " is not capable of handling ";
452 if (fAnalysisType == Types::kRegression) {
453 Log() << "regression with " << loader->GetDataSetInfo().GetNTargets() << " targets." << Endl;
454 } else if (fAnalysisType == Types::kMulticlass) {
455 Log() << "multiclass classification with " << loader->GetDataSetInfo().GetNClasses() << " classes." << Endl;
456 } else {
457 Log() << "classification with " << loader->GetDataSetInfo().GetNClasses() << " classes." << Endl;
458 }
459 return 0;
460 }
461
462 if (fModelPersistence)
463 method->SetWeightFileDir(fileDir);
464 method->SetModelPersistence(fModelPersistence);
465 method->SetAnalysisType(fAnalysisType);
466 method->SetupMethod();
467 method->ParseOptions();
468 method->ProcessSetup();
469 method->SetFile(fgTargetFile);
470 method->SetSilentFile(IsSilentFile());
471
472 // check-for-unused-options is performed; may be overridden by derived classes
473 method->CheckSetup();
474
475 if (fMethodsMap.find(datasetname) == fMethodsMap.end()) {
476 MVector *mvector = new MVector;
477 fMethodsMap[datasetname] = mvector;
478 }
479 fMethodsMap[datasetname]->push_back(method);
480 return method;
481}
482
483////////////////////////////////////////////////////////////////////////////////
484/// Adds an already constructed method to be managed by this factory.
485///
486/// \note Private.
487/// \note Know what you are doing when using this method. The method that you
488/// are loading could be trained already.
489///
490
493{
494 TString datasetname = loader->GetName();
495 std::string methodTypeName = std::string(Types::Instance().GetMethodName(methodType).Data());
496 DataSetInfo &dsi = loader->GetDataSetInfo();
497
499 MethodBase *method = (dynamic_cast<MethodBase *>(im));
500
501 if (method == nullptr)
502 return nullptr;
503
504 if (method->GetMethodType() == Types::kCategory) {
505 Log() << kERROR << "Cannot handle category methods for now." << Endl;
506 }
507
509 if (fModelPersistence) {
510 // find prefix in fWeightFileDir;
512 fileDir = prefix;
513 if (!prefix.IsNull())
514 if (fileDir[fileDir.Length() - 1] != '/')
515 fileDir += "/";
516 fileDir = loader->GetName();
518 }
519
520 if (fModelPersistence)
521 method->SetWeightFileDir(fileDir);
522 method->SetModelPersistence(fModelPersistence);
523 method->SetAnalysisType(fAnalysisType);
524 method->SetupMethod();
525 method->SetFile(fgTargetFile);
526 method->SetSilentFile(IsSilentFile());
527
528 method->DeclareCompatibilityOptions();
529
530 // read weight file
531 method->ReadStateFromFile();
532
533 // method->CheckSetup();
534
535 TString methodTitle = method->GetName();
536 if (HasMethod(datasetname, methodTitle) != 0) {
537 Log() << kFATAL << "Booking failed since method with title <" << methodTitle << "> already exists "
538 << "in with DataSet Name <" << loader->GetName() << "> " << Endl;
539 }
540
541 Log() << kINFO << "Booked classifier \"" << method->GetMethodName() << "\" of type: \""
542 << method->GetMethodTypeName() << "\"" << Endl;
543
544 if (fMethodsMap.count(datasetname) == 0) {
545 MVector *mvector = new MVector;
546 fMethodsMap[datasetname] = mvector;
547 }
548
549 fMethodsMap[datasetname]->push_back(method);
550
551 return method;
552}
553
554////////////////////////////////////////////////////////////////////////////////
555/// Returns pointer to MVA that corresponds to given method title.
556
558{
559 if (fMethodsMap.find(datasetname) == fMethodsMap.end())
560 return 0;
561
562 MVector *methods = fMethodsMap.find(datasetname)->second;
563
564 MVector::const_iterator itrMethod;
565 //
566 for (itrMethod = methods->begin(); itrMethod != methods->end(); ++itrMethod) {
567 MethodBase *mva = dynamic_cast<MethodBase *>(*itrMethod);
568 if ((mva->GetMethodName()) == methodTitle)
569 return mva;
570 }
571 return 0;
572}
573
574////////////////////////////////////////////////////////////////////////////////
575/// Checks whether a given method name is defined for a given dataset.
576
578{
579 if (fMethodsMap.find(datasetname) == fMethodsMap.end())
580 return 0;
581
582 std::string methodName = methodTitle.Data();
583 auto isEqualToMethodName = [&methodName](TMVA::IMethod *m) { return (0 == methodName.compare(m->GetName())); };
584
585 TMVA::Factory::MVector *methods = this->fMethodsMap.at(datasetname);
587
589}
590
591////////////////////////////////////////////////////////////////////////////////
592
594{
595 RootBaseDir()->cd();
596
597 if (!RootBaseDir()->GetDirectory(fDataSetInfo.GetName()))
598 RootBaseDir()->mkdir(fDataSetInfo.GetName());
599 else
600 return; // loader is now in the output file, we dont need to save again
601
602 RootBaseDir()->cd(fDataSetInfo.GetName());
603 fDataSetInfo.GetDataSet(); // builds dataset (including calculation of correlation matrix)
604
605 // correlation matrix of the default DS
606 const TMatrixD *m(0);
607 const TH2 *h(0);
608
609 if (fAnalysisType == Types::kMulticlass) {
610 for (UInt_t cls = 0; cls < fDataSetInfo.GetNClasses(); cls++) {
611 m = fDataSetInfo.CorrelationMatrix(fDataSetInfo.GetClassInfo(cls)->GetName());
612 h = fDataSetInfo.CreateCorrelationMatrixHist(
613 m, TString("CorrelationMatrix") + fDataSetInfo.GetClassInfo(cls)->GetName(),
614 TString("Correlation Matrix (") + fDataSetInfo.GetClassInfo(cls)->GetName() + TString(")"));
615 if (h != 0) {
616 h->Write();
617 delete h;
618 }
619 }
620 } else {
621 m = fDataSetInfo.CorrelationMatrix("Signal");
622 h = fDataSetInfo.CreateCorrelationMatrixHist(m, "CorrelationMatrixS", "Correlation Matrix (signal)");
623 if (h != 0) {
624 h->Write();
625 delete h;
626 }
627
628 m = fDataSetInfo.CorrelationMatrix("Background");
629 h = fDataSetInfo.CreateCorrelationMatrixHist(m, "CorrelationMatrixB", "Correlation Matrix (background)");
630 if (h != 0) {
631 h->Write();
632 delete h;
633 }
634
635 m = fDataSetInfo.CorrelationMatrix("Regression");
636 h = fDataSetInfo.CreateCorrelationMatrixHist(m, "CorrelationMatrix", "Correlation Matrix");
637 if (h != 0) {
638 h->Write();
639 delete h;
640 }
641 }
642
643 // some default transformations to evaluate
644 // NOTE: all transformations are destroyed after this test
645 TString processTrfs = "I"; //"I;N;D;P;U;G,D;"
646
647 // plus some user defined transformations
648 processTrfs = fTransformations;
649
650 // remove any trace of identity transform - if given (avoid to apply it twice)
651 std::vector<TMVA::TransformationHandler *> trfs;
653
654 std::vector<TString> trfsDef = gTools().SplitString(processTrfs, ';');
655 std::vector<TString>::iterator trfsDefIt = trfsDef.begin();
656 for (; trfsDefIt != trfsDef.end(); ++trfsDefIt) {
657 trfs.push_back(new TMVA::TransformationHandler(fDataSetInfo, "Factory"));
658 TString trfS = (*trfsDefIt);
659
660 // Log() << kINFO << Endl;
661 Log() << kDEBUG << "current transformation string: '" << trfS.Data() << "'" << Endl;
662 TMVA::CreateVariableTransforms(trfS, fDataSetInfo, *(trfs.back()), Log());
663
664 if (trfS.BeginsWith('I'))
665 identityTrHandler = trfs.back();
666 }
667
668 const std::vector<Event *> &inputEvents = fDataSetInfo.GetDataSet()->GetEventCollection();
669
670 // apply all transformations
671 std::vector<TMVA::TransformationHandler *>::iterator trfIt = trfs.begin();
672
673 for (; trfIt != trfs.end(); ++trfIt) {
674 // setting a Root dir causes the variables distributions to be saved to the root file
675 (*trfIt)->SetRootDir(RootBaseDir()->GetDirectory(fDataSetInfo.GetName())); // every dataloader have its own dir
676 (*trfIt)->CalcTransformations(inputEvents);
677 }
679 identityTrHandler->PrintVariableRanking();
680
681 // clean up
682 for (trfIt = trfs.begin(); trfIt != trfs.end(); ++trfIt)
683 delete *trfIt;
684}
685
686////////////////////////////////////////////////////////////////////////////////
687/// Iterates through all booked methods and sees if they use parameter tuning and if so
688/// does just that, i.e.\ calls "Method::Train()" for different parameter settings and
689/// keeps in mind the "optimal one"...\ and that's the one that will later on be used
690/// in the main training loop.
691
693{
694
695 std::map<TString, MVector *>::iterator itrMap;
696 std::map<TString, Double_t> TunedParameters;
697 for (itrMap = fMethodsMap.begin(); itrMap != fMethodsMap.end(); ++itrMap) {
698 MVector *methods = itrMap->second;
699
700 MVector::iterator itrMethod;
701
702 // iterate over methods and optimize
703 for (itrMethod = methods->begin(); itrMethod != methods->end(); ++itrMethod) {
705 MethodBase *mva = dynamic_cast<MethodBase *>(*itrMethod);
706 if (!mva) {
707 Log() << kFATAL << "Dynamic cast to MethodBase failed" << Endl;
708 return TunedParameters;
709 }
710
711 if (mva->Data()->GetNTrainingEvents() < MinNoTrainingEvents) {
712 Log() << kWARNING << "Method " << mva->GetMethodName() << " not trained (training tree has less entries ["
713 << mva->Data()->GetNTrainingEvents() << "] than required [" << MinNoTrainingEvents << "]" << Endl;
714 continue;
715 }
716
717 Log() << kINFO << "Optimize method: " << mva->GetMethodName() << " for "
718 << (fAnalysisType == Types::kRegression
719 ? "Regression"
720 : (fAnalysisType == Types::kMulticlass ? "Multiclass classification" : "Classification"))
721 << Endl;
722
723 TunedParameters = mva->OptimizeTuningParameters(fomType, fitType);
724 Log() << kINFO << "Optimization of tuning parameters finished for Method:" << mva->GetName() << Endl;
725 }
726 }
727
728 return TunedParameters;
729}
730
731////////////////////////////////////////////////////////////////////////////////
732/// Private method to generate a ROCCurve instance for a given method.
733/// Handles the conversion from TMVA ResultSet to a format the ROCCurve class
734/// understands.
735///
736/// \note You own the retured pointer.
737///
738
744
745////////////////////////////////////////////////////////////////////////////////
746/// Private method to generate a ROCCurve instance for a given method.
747/// Handles the conversion from TMVA ResultSet to a format the ROCCurve class
748/// understands.
749///
750/// \note You own the retured pointer.
751///
752
754{
755 if (fMethodsMap.find(datasetname) == fMethodsMap.end()) {
756 Log() << kERROR << Form("DataSet = %s not found in methods map.", datasetname.Data()) << Endl;
757 return nullptr;
758 }
759
760 if (!this->HasMethod(datasetname, theMethodName)) {
761 Log() << kERROR << Form("Method = %s not found with Dataset = %s ", theMethodName.Data(), datasetname.Data())
762 << Endl;
763 return nullptr;
764 }
765
766 std::set<Types::EAnalysisType> allowedAnalysisTypes = {Types::kClassification, Types::kMulticlass};
767 if (allowedAnalysisTypes.count(this->fAnalysisType) == 0) {
768 Log() << kERROR << Form("Can only generate ROC curves for analysis type kClassification and kMulticlass.")
769 << Endl;
770 return nullptr;
771 }
772
773 TMVA::MethodBase *method = dynamic_cast<TMVA::MethodBase *>(this->GetMethod(datasetname, theMethodName));
774 TMVA::DataSet *dataset = method->Data();
775 dataset->SetCurrentType(type);
776 TMVA::Results *results = dataset->GetResults(theMethodName, type, this->fAnalysisType);
777
778 UInt_t nClasses = method->DataInfo().GetNClasses();
779 if (this->fAnalysisType == Types::kMulticlass && iClass >= nClasses) {
780 Log() << kERROR
781 << Form("Given class number (iClass = %i) does not exist. There are %i classes in dataset.", iClass,
782 nClasses)
783 << Endl;
784 return nullptr;
785 }
786
787 TMVA::ROCCurve *rocCurve = nullptr;
788 if (this->fAnalysisType == Types::kClassification) {
789
790 std::vector<Float_t> *mvaRes = dynamic_cast<ResultsClassification *>(results)->GetValueVector();
791 std::vector<Bool_t> *mvaResTypes = dynamic_cast<ResultsClassification *>(results)->GetValueVectorTypes();
792 std::vector<Float_t> mvaResWeights;
793
794 auto eventCollection = dataset->GetEventCollection(type);
795 mvaResWeights.reserve(eventCollection.size());
796 for (auto ev : eventCollection) {
797 mvaResWeights.push_back(ev->GetWeight());
798 }
799
801
802 } else if (this->fAnalysisType == Types::kMulticlass) {
803 std::vector<Float_t> mvaRes;
804 std::vector<Bool_t> mvaResTypes;
805 std::vector<Float_t> mvaResWeights;
806
807 std::vector<std::vector<Float_t>> *rawMvaRes = dynamic_cast<ResultsMulticlass *>(results)->GetValueVector();
808
809 // Vector transpose due to values being stored as
810 // [ [0, 1, 2], [0, 1, 2], ... ]
811 // in ResultsMulticlass::GetValueVector.
812 mvaRes.reserve(rawMvaRes->size());
813 for (auto item : *rawMvaRes) {
814 mvaRes.push_back(item[iClass]);
815 }
816
817 auto eventCollection = dataset->GetEventCollection(type);
818 mvaResTypes.reserve(eventCollection.size());
819 mvaResWeights.reserve(eventCollection.size());
820 for (auto ev : eventCollection) {
821 mvaResTypes.push_back(ev->GetClass() == iClass);
822 mvaResWeights.push_back(ev->GetWeight());
823 }
824
826 }
827
828 return rocCurve;
829}
830
831////////////////////////////////////////////////////////////////////////////////
832/// Calculate the integral of the ROC curve, also known as the area under curve
833/// (AUC), for a given method.
834///
835/// Argument iClass specifies the class to generate the ROC curve in a
836/// multiclass setting. It is ignored for binary classification.
837///
838
844
845////////////////////////////////////////////////////////////////////////////////
846/// Calculate the integral of the ROC curve, also known as the area under curve
847/// (AUC), for a given method.
848///
849/// Argument iClass specifies the class to generate the ROC curve in a
850/// multiclass setting. It is ignored for binary classification.
851///
852
854{
855 if (fMethodsMap.find(datasetname) == fMethodsMap.end()) {
856 Log() << kERROR << Form("DataSet = %s not found in methods map.", datasetname.Data()) << Endl;
857 return 0;
858 }
859
860 if (!this->HasMethod(datasetname, theMethodName)) {
861 Log() << kERROR << Form("Method = %s not found with Dataset = %s ", theMethodName.Data(), datasetname.Data())
862 << Endl;
863 return 0;
864 }
865
866 std::set<Types::EAnalysisType> allowedAnalysisTypes = {Types::kClassification, Types::kMulticlass};
867 if (allowedAnalysisTypes.count(this->fAnalysisType) == 0) {
868 Log() << kERROR << Form("Can only generate ROC integral for analysis type kClassification. and kMulticlass.")
869 << Endl;
870 return 0;
871 }
872
874 if (!rocCurve) {
875 Log() << kFATAL
876 << Form("ROCCurve object was not created in Method = %s not found with Dataset = %s ", theMethodName.Data(),
877 datasetname.Data())
878 << Endl;
879 return 0;
880 }
881
882 Int_t npoints = TMVA::gConfig().fVariablePlotting.fNbinsXOfROCCurve + 1;
883 Double_t rocIntegral = rocCurve->GetROCIntegral(npoints);
884 delete rocCurve;
885
886 return rocIntegral;
887}
888
889////////////////////////////////////////////////////////////////////////////////
890/// Argument iClass specifies the class to generate the ROC curve in a
891/// multiclass setting. It is ignored for binary classification.
892///
893/// Returns a ROC graph for a given method, or nullptr on error.
894///
895/// Note: Evaluation of the given method must have been run prior to ROC
896/// generation through Factory::EvaluateAllMetods.
897///
898/// NOTE: The ROC curve is 1 vs. all where the given class is considered signal
899/// and the others considered background. This is ok in binary classification
900/// but in in multi class classification, the ROC surface is an N dimensional
901/// shape, where N is number of classes - 1.
902
908
909////////////////////////////////////////////////////////////////////////////////
910/// Argument iClass specifies the class to generate the ROC curve in a
911/// multiclass setting. It is ignored for binary classification.
912///
913/// Returns a ROC graph for a given method, or nullptr on error.
914///
915/// Note: Evaluation of the given method must have been run prior to ROC
916/// generation through Factory::EvaluateAllMetods.
917///
918/// NOTE: The ROC curve is 1 vs. all where the given class is considered signal
919/// and the others considered background. This is ok in binary classification
920/// but in in multi class classification, the ROC surface is an N dimensional
921/// shape, where N is number of classes - 1.
922
925{
926 if (fMethodsMap.find(datasetname) == fMethodsMap.end()) {
927 Log() << kERROR << Form("DataSet = %s not found in methods map.", datasetname.Data()) << Endl;
928 return nullptr;
929 }
930
931 if (!this->HasMethod(datasetname, theMethodName)) {
932 Log() << kERROR << Form("Method = %s not found with Dataset = %s ", theMethodName.Data(), datasetname.Data())
933 << Endl;
934 return nullptr;
935 }
936
937 std::set<Types::EAnalysisType> allowedAnalysisTypes = {Types::kClassification, Types::kMulticlass};
938 if (allowedAnalysisTypes.count(this->fAnalysisType) == 0) {
939 Log() << kERROR << Form("Can only generate ROC curves for analysis type kClassification and kMulticlass.")
940 << Endl;
941 return nullptr;
942 }
943
945 TGraph *graph = nullptr;
946
947 if (!rocCurve) {
948 Log() << kFATAL
949 << Form("ROCCurve object was not created in Method = %s not found with Dataset = %s ", theMethodName.Data(),
950 datasetname.Data())
951 << Endl;
952 return nullptr;
953 }
954
955 graph = (TGraph *)rocCurve->GetROCCurve()->Clone();
956 delete rocCurve;
957
958 if (setTitles) {
959 graph->GetYaxis()->SetTitle("Background rejection (Specificity)");
960 graph->GetXaxis()->SetTitle("Signal efficiency (Sensitivity)");
961 graph->SetTitle(TString::Format("Signal efficiency vs. Background rejection (%s)", theMethodName.Data()).Data());
962 }
963
964 return graph;
965}
966
967////////////////////////////////////////////////////////////////////////////////
968/// Generate a collection of graphs, for all methods for a given class. Suitable
969/// for comparing method performance.
970///
971/// Argument iClass specifies the class to generate the ROC curve in a
972/// multiclass setting. It is ignored for binary classification.
973///
974/// NOTE: The ROC curve is 1 vs. all where the given class is considered signal
975/// and the others considered background. This is ok in binary classification
976/// but in in multi class classification, the ROC surface is an N dimensional
977/// shape, where N is number of classes - 1.
978
983
984////////////////////////////////////////////////////////////////////////////////
985/// Generate a collection of graphs, for all methods for a given class. Suitable
986/// for comparing method performance.
987///
988/// Argument iClass specifies the class to generate the ROC curve in a
989/// multiclass setting. It is ignored for binary classification.
990///
991/// NOTE: The ROC curve is 1 vs. all where the given class is considered signal
992/// and the others considered background. This is ok in binary classification
993/// but in in multi class classification, the ROC surface is an N dimensional
994/// shape, where N is number of classes - 1.
995
997{
998 UInt_t line_color = 1;
999
1001
1002 MVector *methods = fMethodsMap[datasetname.Data()];
1003 for (auto *method_raw : *methods) {
1005 if (method == nullptr) {
1006 continue;
1007 }
1008
1009 TString methodName = method->GetMethodName();
1010 UInt_t nClasses = method->DataInfo().GetNClasses();
1011
1012 if (this->fAnalysisType == Types::kMulticlass && iClass >= nClasses) {
1013 Log() << kERROR
1014 << Form("Given class number (iClass = %i) does not exist. There are %i classes in dataset.", iClass,
1015 nClasses)
1016 << Endl;
1017 continue;
1018 }
1019
1020 TString className = method->DataInfo().GetClassInfo(iClass)->GetName();
1021
1022 TGraph *graph = this->GetROCCurve(datasetname, methodName, false, iClass, type);
1023 graph->SetTitle(methodName);
1024
1025 graph->SetLineWidth(2);
1026 graph->SetLineColor(line_color++);
1027 graph->SetFillColor(10);
1028
1029 multigraph->Add(graph);
1030 }
1031
1032 if (multigraph->GetListOfGraphs() == nullptr) {
1033 Log() << kERROR << Form("No metohds have class %i defined.", iClass) << Endl;
1034 return nullptr;
1035 }
1036
1037 return multigraph;
1038}
1039
1040////////////////////////////////////////////////////////////////////////////////
1041/// Draws ROC curves for all methods booked with the factory for a given class
1042/// onto a canvas.
1043///
1044/// Argument iClass specifies the class to generate the ROC curve in a
1045/// multiclass setting. It is ignored for binary classification.
1046///
1047/// NOTE: The ROC curve is 1 vs. all where the given class is considered signal
1048/// and the others considered background. This is ok in binary classification
1049/// but in in multi class classification, the ROC surface is an N dimensional
1050/// shape, where N is number of classes - 1.
1051
1056
1057////////////////////////////////////////////////////////////////////////////////
1058/// Draws ROC curves for all methods booked with the factory for a given class.
1059///
1060/// Argument iClass specifies the class to generate the ROC curve in a
1061/// multiclass setting. It is ignored for binary classification.
1062///
1063/// NOTE: The ROC curve is 1 vs. all where the given class is considered signal
1064/// and the others considered background. This is ok in binary classification
1065/// but in in multi class classification, the ROC surface is an N dimensional
1066/// shape, where N is number of classes - 1.
1067
1069{
1070 if (fMethodsMap.find(datasetname) == fMethodsMap.end()) {
1071 Log() << kERROR << Form("DataSet = %s not found in methods map.", datasetname.Data()) << Endl;
1072 return 0;
1073 }
1074
1075 TString name = TString::Format("ROCCurve %s class %i", datasetname.Data(), iClass);
1076 TCanvas *canvas = new TCanvas(name.Data(), "ROC Curve", 200, 10, 700, 500);
1077 canvas->SetGrid();
1078
1079 TMultiGraph *multigraph = this->GetROCCurveAsMultiGraph(datasetname, iClass, type);
1080
1081 if (multigraph) {
1082 multigraph->Draw("AL");
1083
1084 multigraph->GetYaxis()->SetTitle("Background rejection (Specificity)");
1085 multigraph->GetXaxis()->SetTitle("Signal efficiency (Sensitivity)");
1086
1087 TString titleString = TString::Format("Signal efficiency vs. Background rejection");
1088 if (this->fAnalysisType == Types::kMulticlass) {
1089 titleString = TString::Format("%s (Class=%i)", titleString.Data(), iClass);
1090 }
1091
1092 // Workaround for TMultigraph not drawing title correctly.
1093 multigraph->GetHistogram()->SetTitle(titleString.Data());
1094 multigraph->SetTitle(titleString.Data());
1095
1096 canvas->BuildLegend(0.15, 0.15, 0.35, 0.3, "MVA Method");
1097 }
1098
1099 return canvas;
1100}
1101
1102////////////////////////////////////////////////////////////////////////////////
1103/// Iterates through all booked methods and calls training
1104
1106{
1107 Log() << kHEADER << gTools().Color("bold") << "Train all methods" << gTools().Color("reset") << Endl;
1108 // iterates over all MVAs that have been booked, and calls their training methods
1109
1110 // don't do anything if no method booked
1111 if (fMethodsMap.empty()) {
1112 Log() << kINFO << "...nothing found to train" << Endl;
1113 return;
1114 }
1115
1116 // here the training starts
1117 // Log() << kINFO << " " << Endl;
1118 Log() << kDEBUG << "Train all methods for "
1119 << (fAnalysisType == Types::kRegression
1120 ? "Regression"
1121 : (fAnalysisType == Types::kMulticlass ? "Multiclass" : "Classification"))
1122 << " ..." << Endl;
1123
1124 std::map<TString, MVector *>::iterator itrMap;
1125
1126 for (itrMap = fMethodsMap.begin(); itrMap != fMethodsMap.end(); ++itrMap) {
1127 MVector *methods = itrMap->second;
1128 MVector::iterator itrMethod;
1129
1130 // iterate over methods and train
1131 for (itrMethod = methods->begin(); itrMethod != methods->end(); ++itrMethod) {
1133 MethodBase *mva = dynamic_cast<MethodBase *>(*itrMethod);
1134
1135 if (mva == 0)
1136 continue;
1137
1138 if (mva->DataInfo().GetDataSetManager()->DataInput().GetEntries() <=
1139 1) { // 0 entries --> 0 events, 1 entry --> dynamical dataset (or one entry)
1140 Log() << kFATAL << "No input data for the training provided!" << Endl;
1141 }
1142
1143 if (fAnalysisType == Types::kRegression && mva->DataInfo().GetNTargets() < 1)
1144 Log() << kFATAL << "You want to do regression training without specifying a target." << Endl;
1145 else if ((fAnalysisType == Types::kMulticlass || fAnalysisType == Types::kClassification) &&
1146 mva->DataInfo().GetNClasses() < 2)
1147 Log() << kFATAL << "You want to do classification training, but specified less than two classes." << Endl;
1148
1149 // first print some information about the default dataset
1150 if (!IsSilentFile())
1151 WriteDataInformation(mva->fDataSetInfo);
1152
1153 if (mva->Data()->GetNTrainingEvents() < MinNoTrainingEvents) {
1154 Log() << kWARNING << "Method " << mva->GetMethodName() << " not trained (training tree has less entries ["
1155 << mva->Data()->GetNTrainingEvents() << "] than required [" << MinNoTrainingEvents << "]" << Endl;
1156 continue;
1157 }
1158
1159 Log() << kHEADER << "Train method: " << mva->GetMethodName() << " for "
1160 << (fAnalysisType == Types::kRegression
1161 ? "Regression"
1162 : (fAnalysisType == Types::kMulticlass ? "Multiclass classification" : "Classification"))
1163 << Endl << Endl;
1164 mva->TrainMethod();
1165 Log() << kHEADER << "Training finished" << Endl << Endl;
1166 }
1167
1168 if (fAnalysisType != Types::kRegression) {
1169
1170 // variable ranking
1171 // Log() << Endl;
1172 Log() << kINFO << "Ranking input variables (method specific)..." << Endl;
1173 for (itrMethod = methods->begin(); itrMethod != methods->end(); ++itrMethod) {
1174 MethodBase *mva = dynamic_cast<MethodBase *>(*itrMethod);
1175 if (mva && mva->Data()->GetNTrainingEvents() >= MinNoTrainingEvents) {
1176
1177 // create and print ranking
1178 const Ranking *ranking = (*itrMethod)->CreateRanking();
1179 if (ranking != 0)
1180 ranking->Print();
1181 else
1182 Log() << kINFO << "No variable ranking supplied by classifier: "
1183 << dynamic_cast<MethodBase *>(*itrMethod)->GetMethodName() << Endl;
1184 }
1185 }
1186 }
1187
1188 // save training history in case we are not in the silent mode
1189 if (!IsSilentFile()) {
1190 for (UInt_t i = 0; i < methods->size(); i++) {
1191 MethodBase *m = dynamic_cast<MethodBase *>((*methods)[i]);
1192 if (m == 0)
1193 continue;
1194 m->BaseDir()->cd();
1195 m->fTrainHistory.SaveHistory(m->GetMethodName());
1196 }
1197 }
1198
1199 // delete all methods and recreate them from weight file - this ensures that the application
1200 // of the methods (in TMVAClassificationApplication) is consistent with the results obtained
1201 // in the testing
1202 // Log() << Endl;
1203 if (fModelPersistence) {
1204
1205 Log() << kHEADER << "=== Destroy and recreate all methods via weight files for testing ===" << Endl << Endl;
1206
1207 if (!IsSilentFile())
1208 RootBaseDir()->cd();
1209
1210 // iterate through all booked methods
1211 for (UInt_t i = 0; i < methods->size(); i++) {
1212
1213 MethodBase *m = dynamic_cast<MethodBase *>((*methods)[i]);
1214 if (m == nullptr)
1215 continue;
1216
1217 TMVA::Types::EMVA methodType = m->GetMethodType();
1218 TString weightfile = m->GetWeightFileName();
1219
1220 // decide if .txt or .xml file should be read:
1221 if (READXML)
1222 weightfile.ReplaceAll(".txt", ".xml");
1223
1224 DataSetInfo &dataSetInfo = m->DataInfo();
1225 TString testvarName = m->GetTestvarName();
1226 delete m; // itrMethod[i];
1227
1228 // recreate
1229 m = dynamic_cast<MethodBase *>(ClassifierFactory::Instance().Create(
1230 Types::Instance().GetMethodName(methodType).Data(), dataSetInfo, weightfile));
1231 if (m->GetMethodType() == Types::kCategory) {
1232 MethodCategory *methCat = (dynamic_cast<MethodCategory *>(m));
1233 if (!methCat)
1234 Log() << kFATAL << "Method with type kCategory cannot be casted to MethodCategory. /Factory" << Endl;
1235 else
1236 methCat->fDataSetManager = m->DataInfo().GetDataSetManager();
1237 }
1238 // ToDo, Do we need to fill the DataSetManager of MethodBoost here too?
1239
1240 TString wfileDir = m->DataInfo().GetName();
1242 m->SetWeightFileDir(wfileDir);
1243 m->SetModelPersistence(fModelPersistence);
1244 m->SetSilentFile(IsSilentFile());
1245 m->SetAnalysisType(fAnalysisType);
1246 m->SetupMethod();
1247 m->ReadStateFromFile();
1248 m->SetTestvarName(testvarName);
1249
1250 // replace trained method by newly created one (from weight file) in methods vector
1251 (*methods)[i] = m;
1252 }
1253 }
1254 }
1255}
1256
1257////////////////////////////////////////////////////////////////////////////////
1258/// Evaluates all booked methods on the testing data and adds the output to the
1259/// Results in the corresponiding DataSet.
1260///
1261
1263{
1264 Log() << kHEADER << gTools().Color("bold") << "Test all methods" << gTools().Color("reset") << Endl;
1265
1266 // don't do anything if no method booked
1267 if (fMethodsMap.empty()) {
1268 Log() << kINFO << "...nothing found to test" << Endl;
1269 return;
1270 }
1271 std::map<TString, MVector *>::iterator itrMap;
1272
1273 for (itrMap = fMethodsMap.begin(); itrMap != fMethodsMap.end(); ++itrMap) {
1274 MVector *methods = itrMap->second;
1275 MVector::iterator itrMethod;
1276
1277 // iterate over methods and test
1278 for (itrMethod = methods->begin(); itrMethod != methods->end(); ++itrMethod) {
1280 MethodBase *mva = dynamic_cast<MethodBase *>(*itrMethod);
1281 if (mva == 0)
1282 continue;
1283 Types::EAnalysisType analysisType = mva->GetAnalysisType();
1284 Log() << kHEADER << "Test method: " << mva->GetMethodName() << " for "
1285 << (analysisType == Types::kRegression
1286 ? "Regression"
1287 : (analysisType == Types::kMulticlass ? "Multiclass classification" : "Classification"))
1288 << " performance" << Endl << Endl;
1289 mva->AddOutput(Types::kTesting, analysisType);
1290 }
1291 }
1292}
1293
1294////////////////////////////////////////////////////////////////////////////////
1295
1296void TMVA::Factory::MakeClass(const TString &datasetname, const TString &methodTitle) const
1297{
1298 if (methodTitle != "") {
1299 IMethod *method = GetMethod(datasetname, methodTitle);
1300 if (method)
1301 method->MakeClass();
1302 else {
1303 Log() << kWARNING << "<MakeClass> Could not find classifier \"" << methodTitle << "\" in list" << Endl;
1304 }
1305 } else {
1306
1307 // no classifier specified, print all help messages
1308 MVector *methods = fMethodsMap.find(datasetname)->second;
1309 MVector::const_iterator itrMethod;
1310 for (itrMethod = methods->begin(); itrMethod != methods->end(); ++itrMethod) {
1311 MethodBase *method = dynamic_cast<MethodBase *>(*itrMethod);
1312 if (method == 0)
1313 continue;
1314 Log() << kINFO << "Make response class for classifier: " << method->GetMethodName() << Endl;
1315 method->MakeClass();
1316 }
1317 }
1318}
1319
1320////////////////////////////////////////////////////////////////////////////////
1321/// Print predefined help message of classifier.
1322/// Iterate over methods and test.
1323
1324void TMVA::Factory::PrintHelpMessage(const TString &datasetname, const TString &methodTitle) const
1325{
1326 if (methodTitle != "") {
1327 IMethod *method = GetMethod(datasetname, methodTitle);
1328 if (method)
1329 method->PrintHelpMessage();
1330 else {
1331 Log() << kWARNING << "<PrintHelpMessage> Could not find classifier \"" << methodTitle << "\" in list" << Endl;
1332 }
1333 } else {
1334
1335 // no classifier specified, print all help messages
1336 MVector *methods = fMethodsMap.find(datasetname)->second;
1337 MVector::const_iterator itrMethod;
1338 for (itrMethod = methods->begin(); itrMethod != methods->end(); ++itrMethod) {
1339 MethodBase *method = dynamic_cast<MethodBase *>(*itrMethod);
1340 if (method == 0)
1341 continue;
1342 Log() << kINFO << "Print help message for classifier: " << method->GetMethodName() << Endl;
1343 method->PrintHelpMessage();
1344 }
1345 }
1346}
1347
1348////////////////////////////////////////////////////////////////////////////////
1349/// Iterates over all MVA input variables and evaluates them.
1350
1352{
1353 Log() << kINFO << "Evaluating all variables..." << Endl;
1355
1356 for (UInt_t i = 0; i < loader->GetDataSetInfo().GetNVariables(); i++) {
1357 TString s = loader->GetDataSetInfo().GetVariableInfo(i).GetLabel();
1358 if (options.Contains("V"))
1359 s += ":V";
1360 this->BookMethod(loader, "Variable", s);
1361 }
1362}
1363
1364////////////////////////////////////////////////////////////////////////////////
1365/// Iterates over all MVAs that have been booked, and calls their evaluation methods.
1366
1368{
1369 Log() << kHEADER << gTools().Color("bold") << "Evaluate all methods" << gTools().Color("reset") << Endl;
1370
1371 // don't do anything if no method booked
1372 if (fMethodsMap.empty()) {
1373 Log() << kINFO << "...nothing found to evaluate" << Endl;
1374 return;
1375 }
1376 std::map<TString, MVector *>::iterator itrMap;
1377
1378 for (itrMap = fMethodsMap.begin(); itrMap != fMethodsMap.end(); ++itrMap) {
1379 MVector *methods = itrMap->second;
1380
1381 // -----------------------------------------------------------------------
1382 // First part of evaluation process
1383 // --> compute efficiencies, and other separation estimators
1384 // -----------------------------------------------------------------------
1385
1386 // although equal, we now want to separate the output for the variables
1387 // and the real methods
1388 Int_t isel; // will be 0 for a Method; 1 for a Variable
1389 Int_t nmeth_used[2] = {0, 0}; // 0 Method; 1 Variable
1390
1391 std::vector<std::vector<TString>> mname(2);
1392 std::vector<std::vector<Double_t>> sig(2), sep(2), roc(2);
1393 std::vector<std::vector<Double_t>> eff01(2), eff10(2), eff30(2), effArea(2);
1394 std::vector<std::vector<Double_t>> eff01err(2), eff10err(2), eff30err(2);
1395 std::vector<std::vector<Double_t>> trainEff01(2), trainEff10(2), trainEff30(2);
1396
1397 std::vector<std::vector<Float_t>> multiclass_testEff;
1398 std::vector<std::vector<Float_t>> multiclass_trainEff;
1399 std::vector<std::vector<Float_t>> multiclass_testPur;
1400 std::vector<std::vector<Float_t>> multiclass_trainPur;
1401
1402 std::vector<std::vector<Float_t>> train_history;
1403
1404 // Multiclass confusion matrices.
1405 std::vector<TMatrixD> multiclass_trainConfusionEffB01;
1406 std::vector<TMatrixD> multiclass_trainConfusionEffB10;
1407 std::vector<TMatrixD> multiclass_trainConfusionEffB30;
1408 std::vector<TMatrixD> multiclass_testConfusionEffB01;
1409 std::vector<TMatrixD> multiclass_testConfusionEffB10;
1410 std::vector<TMatrixD> multiclass_testConfusionEffB30;
1411
1412 std::vector<std::vector<Double_t>> biastrain(1); // "bias" of the regression on the training data
1413 std::vector<std::vector<Double_t>> biastest(1); // "bias" of the regression on test data
1414 std::vector<std::vector<Double_t>> devtrain(1); // "dev" of the regression on the training data
1415 std::vector<std::vector<Double_t>> devtest(1); // "dev" of the regression on test data
1416 std::vector<std::vector<Double_t>> rmstrain(1); // "rms" of the regression on the training data
1417 std::vector<std::vector<Double_t>> rmstest(1); // "rms" of the regression on test data
1418 std::vector<std::vector<Double_t>> minftrain(1); // "minf" of the regression on the training data
1419 std::vector<std::vector<Double_t>> minftest(1); // "minf" of the regression on test data
1420 std::vector<std::vector<Double_t>> rhotrain(1); // correlation of the regression on the training data
1421 std::vector<std::vector<Double_t>> rhotest(1); // correlation of the regression on test data
1422
1423 // same as above but for 'truncated' quantities (computed for events within 2sigma of RMS)
1424 std::vector<std::vector<Double_t>> biastrainT(1);
1425 std::vector<std::vector<Double_t>> biastestT(1);
1426 std::vector<std::vector<Double_t>> devtrainT(1);
1427 std::vector<std::vector<Double_t>> devtestT(1);
1428 std::vector<std::vector<Double_t>> rmstrainT(1);
1429 std::vector<std::vector<Double_t>> rmstestT(1);
1430 std::vector<std::vector<Double_t>> minftrainT(1);
1431 std::vector<std::vector<Double_t>> minftestT(1);
1432
1433 // following vector contains all methods - with the exception of Cuts, which are special
1435
1438
1439 // iterate over methods and evaluate
1440 for (MVector::iterator itrMethod = methods->begin(); itrMethod != methods->end(); ++itrMethod) {
1442 MethodBase *theMethod = dynamic_cast<MethodBase *>(*itrMethod);
1443 if (theMethod == 0)
1444 continue;
1445 theMethod->SetFile(fgTargetFile);
1446 theMethod->SetSilentFile(IsSilentFile());
1447 if (theMethod->GetMethodType() != Types::kCuts)
1448 methodsNoCuts.push_back(*itrMethod);
1449
1450 if (theMethod->DoRegression()) {
1452
1453 Log() << kINFO << "Evaluate regression method: " << theMethod->GetMethodName() << Endl;
1456 Double_t rho;
1457
1458 Log() << kINFO << "TestRegression (testing)" << Endl;
1459 theMethod->TestRegression(bias, biasT, dev, devT, rms, rmsT, mInf, mInfT, rho, TMVA::Types::kTesting);
1460 biastest[0].push_back(bias);
1461 devtest[0].push_back(dev);
1462 rmstest[0].push_back(rms);
1463 minftest[0].push_back(mInf);
1464 rhotest[0].push_back(rho);
1465 biastestT[0].push_back(biasT);
1466 devtestT[0].push_back(devT);
1467 rmstestT[0].push_back(rmsT);
1468 minftestT[0].push_back(mInfT);
1469
1470 Log() << kINFO << "TestRegression (training)" << Endl;
1471 theMethod->TestRegression(bias, biasT, dev, devT, rms, rmsT, mInf, mInfT, rho, TMVA::Types::kTraining);
1472 biastrain[0].push_back(bias);
1473 devtrain[0].push_back(dev);
1474 rmstrain[0].push_back(rms);
1475 minftrain[0].push_back(mInf);
1476 rhotrain[0].push_back(rho);
1477 biastrainT[0].push_back(biasT);
1478 devtrainT[0].push_back(devT);
1479 rmstrainT[0].push_back(rmsT);
1480 minftrainT[0].push_back(mInfT);
1481
1482 mname[0].push_back(theMethod->GetMethodName());
1483 nmeth_used[0]++;
1484 if (!IsSilentFile()) {
1485 Log() << kDEBUG << "\tWrite evaluation histograms to file" << Endl;
1486 theMethod->WriteEvaluationHistosToFile(Types::kTesting);
1487 theMethod->WriteEvaluationHistosToFile(Types::kTraining);
1488 }
1489 } else if (theMethod->DoMulticlass()) {
1490 // ====================================================================
1491 // === Multiclass evaluation
1492 // ====================================================================
1494 Log() << kINFO << "Evaluate multiclass classification method: " << theMethod->GetMethodName() << Endl;
1495
1496 // This part uses a genetic alg. to evaluate the optimal sig eff * sig pur.
1497 // This is why it is disabled for now.
1498 // Find approximate optimal working point w.r.t. signalEfficiency * signalPurity.
1499 // theMethod->TestMulticlass(); // This is where the actual GA calc is done
1500 // multiclass_testEff.push_back(theMethod->GetMulticlassEfficiency(multiclass_testPur));
1501
1502 theMethod->TestMulticlass();
1503
1504 // Confusion matrix at three background efficiency levels
1505 multiclass_trainConfusionEffB01.push_back(theMethod->GetMulticlassConfusionMatrix(0.01, Types::kTraining));
1506 multiclass_trainConfusionEffB10.push_back(theMethod->GetMulticlassConfusionMatrix(0.10, Types::kTraining));
1507 multiclass_trainConfusionEffB30.push_back(theMethod->GetMulticlassConfusionMatrix(0.30, Types::kTraining));
1508
1509 multiclass_testConfusionEffB01.push_back(theMethod->GetMulticlassConfusionMatrix(0.01, Types::kTesting));
1510 multiclass_testConfusionEffB10.push_back(theMethod->GetMulticlassConfusionMatrix(0.10, Types::kTesting));
1511 multiclass_testConfusionEffB30.push_back(theMethod->GetMulticlassConfusionMatrix(0.30, Types::kTesting));
1512
1513 if (!IsSilentFile()) {
1514 Log() << kDEBUG << "\tWrite evaluation histograms to file" << Endl;
1515 theMethod->WriteEvaluationHistosToFile(Types::kTesting);
1516 theMethod->WriteEvaluationHistosToFile(Types::kTraining);
1517 }
1518
1519 nmeth_used[0]++;
1520 mname[0].push_back(theMethod->GetMethodName());
1521 } else {
1522
1523 Log() << kHEADER << "Evaluate classifier: " << theMethod->GetMethodName() << Endl << Endl;
1524 isel = (theMethod->GetMethodTypeName().Contains("Variable")) ? 1 : 0;
1525
1526 // perform the evaluation
1527 theMethod->TestClassification();
1528
1529 // evaluate the classifier
1530 mname[isel].push_back(theMethod->GetMethodName());
1531 sig[isel].push_back(theMethod->GetSignificance());
1532 sep[isel].push_back(theMethod->GetSeparation());
1533 roc[isel].push_back(theMethod->GetROCIntegral());
1534
1535 Double_t err;
1536 eff01[isel].push_back(theMethod->GetEfficiency("Efficiency:0.01", Types::kTesting, err));
1537 eff01err[isel].push_back(err);
1538 eff10[isel].push_back(theMethod->GetEfficiency("Efficiency:0.10", Types::kTesting, err));
1539 eff10err[isel].push_back(err);
1540 eff30[isel].push_back(theMethod->GetEfficiency("Efficiency:0.30", Types::kTesting, err));
1541 eff30err[isel].push_back(err);
1542 effArea[isel].push_back(theMethod->GetEfficiency("", Types::kTesting, err)); // computes the area (average)
1543
1544 trainEff01[isel].push_back(
1545 theMethod->GetTrainingEfficiency("Efficiency:0.01")); // the first pass takes longer
1546 trainEff10[isel].push_back(theMethod->GetTrainingEfficiency("Efficiency:0.10"));
1547 trainEff30[isel].push_back(theMethod->GetTrainingEfficiency("Efficiency:0.30"));
1548
1549 nmeth_used[isel]++;
1550
1551 if (!IsSilentFile()) {
1552 Log() << kDEBUG << "\tWrite evaluation histograms to file" << Endl;
1553 theMethod->WriteEvaluationHistosToFile(Types::kTesting);
1554 theMethod->WriteEvaluationHistosToFile(Types::kTraining);
1555 }
1556 }
1557 }
1558 if (doRegression) {
1559
1560 std::vector<TString> vtemps = mname[0];
1561 std::vector<std::vector<Double_t>> vtmp;
1562 vtmp.push_back(devtest[0]); // this is the vector that is ranked
1563 vtmp.push_back(devtrain[0]);
1564 vtmp.push_back(biastest[0]);
1565 vtmp.push_back(biastrain[0]);
1566 vtmp.push_back(rmstest[0]);
1567 vtmp.push_back(rmstrain[0]);
1568 vtmp.push_back(minftest[0]);
1569 vtmp.push_back(minftrain[0]);
1570 vtmp.push_back(rhotest[0]);
1571 vtmp.push_back(rhotrain[0]);
1572 vtmp.push_back(devtestT[0]); // this is the vector that is ranked
1573 vtmp.push_back(devtrainT[0]);
1574 vtmp.push_back(biastestT[0]);
1575 vtmp.push_back(biastrainT[0]);
1576 vtmp.push_back(rmstestT[0]);
1577 vtmp.push_back(rmstrainT[0]);
1578 vtmp.push_back(minftestT[0]);
1579 vtmp.push_back(minftrainT[0]);
1581 mname[0] = vtemps;
1582 devtest[0] = vtmp[0];
1583 devtrain[0] = vtmp[1];
1584 biastest[0] = vtmp[2];
1585 biastrain[0] = vtmp[3];
1586 rmstest[0] = vtmp[4];
1587 rmstrain[0] = vtmp[5];
1588 minftest[0] = vtmp[6];
1589 minftrain[0] = vtmp[7];
1590 rhotest[0] = vtmp[8];
1591 rhotrain[0] = vtmp[9];
1592 devtestT[0] = vtmp[10];
1593 devtrainT[0] = vtmp[11];
1594 biastestT[0] = vtmp[12];
1595 biastrainT[0] = vtmp[13];
1596 rmstestT[0] = vtmp[14];
1597 rmstrainT[0] = vtmp[15];
1598 minftestT[0] = vtmp[16];
1599 minftrainT[0] = vtmp[17];
1600 } else if (doMulticlass) {
1601 // TODO: fill in something meaningful
1602 // If there is some ranking of methods to be done it should be done here.
1603 // However, this is not so easy to define for multiclass so it is left out for now.
1604
1605 } else {
1606 // now sort the variables according to the best 'eff at Beff=0.10'
1607 for (Int_t k = 0; k < 2; k++) {
1608 std::vector<std::vector<Double_t>> vtemp;
1609 vtemp.push_back(effArea[k]); // this is the vector that is ranked
1610 vtemp.push_back(eff10[k]);
1611 vtemp.push_back(eff01[k]);
1612 vtemp.push_back(eff30[k]);
1613 vtemp.push_back(eff10err[k]);
1614 vtemp.push_back(eff01err[k]);
1615 vtemp.push_back(eff30err[k]);
1616 vtemp.push_back(trainEff10[k]);
1617 vtemp.push_back(trainEff01[k]);
1618 vtemp.push_back(trainEff30[k]);
1619 vtemp.push_back(sig[k]);
1620 vtemp.push_back(sep[k]);
1621 vtemp.push_back(roc[k]);
1622 std::vector<TString> vtemps = mname[k];
1624 effArea[k] = vtemp[0];
1625 eff10[k] = vtemp[1];
1626 eff01[k] = vtemp[2];
1627 eff30[k] = vtemp[3];
1628 eff10err[k] = vtemp[4];
1629 eff01err[k] = vtemp[5];
1630 eff30err[k] = vtemp[6];
1631 trainEff10[k] = vtemp[7];
1632 trainEff01[k] = vtemp[8];
1633 trainEff30[k] = vtemp[9];
1634 sig[k] = vtemp[10];
1635 sep[k] = vtemp[11];
1636 roc[k] = vtemp[12];
1637 mname[k] = vtemps;
1638 }
1639 }
1640
1641 // -----------------------------------------------------------------------
1642 // Second part of evaluation process
1643 // --> compute correlations among MVAs
1644 // --> compute correlations between input variables and MVA (determines importance)
1645 // --> count overlaps
1646 // -----------------------------------------------------------------------
1647 if (fCorrelations) {
1648 const Int_t nmeth = methodsNoCuts.size();
1649 MethodBase *method = dynamic_cast<MethodBase *>(methods[0][0]);
1650 const Int_t nvar = method->fDataSetInfo.GetNVariables();
1651 if (!doRegression && !doMulticlass) {
1652
1653 if (nmeth > 0) {
1654
1655 // needed for correlations
1656 Double_t *dvec = new Double_t[nmeth + nvar];
1657 std::vector<Double_t> rvec;
1658
1659 // for correlations
1660 TPrincipal *tpSig = new TPrincipal(nmeth + nvar, "");
1661 TPrincipal *tpBkg = new TPrincipal(nmeth + nvar, "");
1662
1663 // set required tree branch references
1664 std::vector<TString> *theVars = new std::vector<TString>;
1665 std::vector<ResultsClassification *> mvaRes;
1666 for (MVector::iterator itrMethod = methodsNoCuts.begin(); itrMethod != methodsNoCuts.end();
1667 ++itrMethod) {
1668 MethodBase *m = dynamic_cast<MethodBase *>(*itrMethod);
1669 if (m == 0)
1670 continue;
1671 theVars->push_back(m->GetTestvarName());
1672 rvec.push_back(m->GetSignalReferenceCut());
1673 theVars->back().ReplaceAll("MVA_", "");
1674 mvaRes.push_back(dynamic_cast<ResultsClassification *>(
1675 m->Data()->GetResults(m->GetMethodName(), Types::kTesting, Types::kMaxAnalysisType)));
1676 }
1677
1678 // for overlap study
1681 (*overlapS) *= 0; // init...
1682 (*overlapB) *= 0; // init...
1683
1684 // loop over test tree
1685 DataSet *defDs = method->fDataSetInfo.GetDataSet();
1686 defDs->SetCurrentType(Types::kTesting);
1687 for (Int_t ievt = 0; ievt < defDs->GetNEvents(); ievt++) {
1688 const Event *ev = defDs->GetEvent(ievt);
1689
1690 // for correlations
1691 TMatrixD *theMat = 0;
1692 for (Int_t im = 0; im < nmeth; im++) {
1693 // check for NaN value
1694 Double_t retval = (Double_t)(*mvaRes[im])[ievt][0];
1695 if (TMath::IsNaN(retval)) {
1696 Log() << kWARNING << "Found NaN return value in event: " << ievt << " for method \""
1697 << methodsNoCuts[im]->GetName() << "\"" << Endl;
1698 dvec[im] = 0;
1699 } else
1700 dvec[im] = retval;
1701 }
1702 for (Int_t iv = 0; iv < nvar; iv++)
1703 dvec[iv + nmeth] = (Double_t)ev->GetValue(iv);
1704 if (method->fDataSetInfo.IsSignal(ev)) {
1705 tpSig->AddRow(dvec);
1706 theMat = overlapS;
1707 } else {
1708 tpBkg->AddRow(dvec);
1709 theMat = overlapB;
1710 }
1711
1712 // count overlaps
1713 for (Int_t im = 0; im < nmeth; im++) {
1714 for (Int_t jm = im; jm < nmeth; jm++) {
1715 if ((dvec[im] - rvec[im]) * (dvec[jm] - rvec[jm]) > 0) {
1716 (*theMat)(im, jm)++;
1717 if (im != jm)
1718 (*theMat)(jm, im)++;
1719 }
1720 }
1721 }
1722 }
1723
1724 // renormalise overlap matrix
1725 (*overlapS) *= (1.0 / defDs->GetNEvtSigTest()); // init...
1726 (*overlapB) *= (1.0 / defDs->GetNEvtBkgdTest()); // init...
1727
1728 tpSig->MakePrincipals();
1729 tpBkg->MakePrincipals();
1730
1731 const TMatrixD *covMatS = tpSig->GetCovarianceMatrix();
1732 const TMatrixD *covMatB = tpBkg->GetCovarianceMatrix();
1733
1736
1737 // print correlation matrices
1738 if (corrMatS != 0 && corrMatB != 0) {
1739
1740 // extract MVA matrix
1743 for (Int_t im = 0; im < nmeth; im++) {
1744 for (Int_t jm = 0; jm < nmeth; jm++) {
1745 mvaMatS(im, jm) = (*corrMatS)(im, jm);
1746 mvaMatB(im, jm) = (*corrMatB)(im, jm);
1747 }
1748 }
1749
1750 // extract variables - to MVA matrix
1751 std::vector<TString> theInputVars;
1752 TMatrixD varmvaMatS(nvar, nmeth);
1753 TMatrixD varmvaMatB(nvar, nmeth);
1754 for (Int_t iv = 0; iv < nvar; iv++) {
1755 theInputVars.push_back(method->fDataSetInfo.GetVariableInfo(iv).GetLabel());
1756 for (Int_t jm = 0; jm < nmeth; jm++) {
1757 varmvaMatS(iv, jm) = (*corrMatS)(nmeth + iv, jm);
1758 varmvaMatB(iv, jm) = (*corrMatB)(nmeth + iv, jm);
1759 }
1760 }
1761
1762 if (nmeth > 1) {
1763 Log() << kINFO << Endl;
1764 Log() << kINFO << Form("Dataset[%s] : ", method->fDataSetInfo.GetName())
1765 << "Inter-MVA correlation matrix (signal):" << Endl;
1767 Log() << kINFO << Endl;
1768
1769 Log() << kINFO << Form("Dataset[%s] : ", method->fDataSetInfo.GetName())
1770 << "Inter-MVA correlation matrix (background):" << Endl;
1772 Log() << kINFO << Endl;
1773 }
1774
1775 Log() << kINFO << Form("Dataset[%s] : ", method->fDataSetInfo.GetName())
1776 << "Correlations between input variables and MVA response (signal):" << Endl;
1778 Log() << kINFO << Endl;
1779
1780 Log() << kINFO << Form("Dataset[%s] : ", method->fDataSetInfo.GetName())
1781 << "Correlations between input variables and MVA response (background):" << Endl;
1783 Log() << kINFO << Endl;
1784 } else
1785 Log() << kWARNING << Form("Dataset[%s] : ", method->fDataSetInfo.GetName())
1786 << "<TestAllMethods> cannot compute correlation matrices" << Endl;
1787
1788 // print overlap matrices
1789 Log() << kINFO << Form("Dataset[%s] : ", method->fDataSetInfo.GetName())
1790 << "The following \"overlap\" matrices contain the fraction of events for which " << Endl;
1791 Log() << kINFO << Form("Dataset[%s] : ", method->fDataSetInfo.GetName())
1792 << "the MVAs 'i' and 'j' have returned conform answers about \"signal-likeness\"" << Endl;
1793 Log() << kINFO << Form("Dataset[%s] : ", method->fDataSetInfo.GetName())
1794 << "An event is signal-like, if its MVA output exceeds the following value:" << Endl;
1795 gTools().FormattedOutput(rvec, *theVars, "Method", "Cut value", Log());
1796 Log() << kINFO << Form("Dataset[%s] : ", method->fDataSetInfo.GetName())
1797 << "which correspond to the working point: eff(signal) = 1 - eff(background)" << Endl;
1798
1799 // give notice that cut method has been excluded from this test
1800 if (nmeth != (Int_t)methods->size())
1801 Log() << kINFO << Form("Dataset[%s] : ", method->fDataSetInfo.GetName())
1802 << "Note: no correlations and overlap with cut method are provided at present" << Endl;
1803
1804 if (nmeth > 1) {
1805 Log() << kINFO << Endl;
1806 Log() << kINFO << Form("Dataset[%s] : ", method->fDataSetInfo.GetName())
1807 << "Inter-MVA overlap matrix (signal):" << Endl;
1809 Log() << kINFO << Endl;
1810
1811 Log() << kINFO << Form("Dataset[%s] : ", method->fDataSetInfo.GetName())
1812 << "Inter-MVA overlap matrix (background):" << Endl;
1814 }
1815
1816 // cleanup
1817 delete tpSig;
1818 delete tpBkg;
1819 delete corrMatS;
1820 delete corrMatB;
1821 delete theVars;
1822 delete overlapS;
1823 delete overlapB;
1824 delete[] dvec;
1825 }
1826 }
1827 }
1828 // -----------------------------------------------------------------------
1829 // Third part of evaluation process
1830 // --> output
1831 // -----------------------------------------------------------------------
1832
1833 if (doRegression) {
1834
1835 Log() << kINFO << Endl;
1836 TString hLine =
1837 "--------------------------------------------------------------------------------------------------";
1838 Log() << kINFO << "Evaluation results ranked by smallest RMS on test sample:" << Endl;
1839 Log() << kINFO << "(\"Bias\" quotes the mean deviation of the regression from true target." << Endl;
1840 Log() << kINFO << " \"MutInf\" is the \"Mutual Information\" between regression and target." << Endl;
1841 Log() << kINFO << " Indicated by \"_T\" are the corresponding \"truncated\" quantities ob-" << Endl;
1842 Log() << kINFO << " tained when removing events deviating more than 2sigma from average.)" << Endl;
1843 Log() << kINFO << hLine << Endl;
1844 // Log() << kINFO << "DataSet Name: MVA Method: <Bias> <Bias_T> RMS RMS_T | MutInf
1845 // MutInf_T" << Endl;
1846 Log() << kINFO << hLine << Endl;
1847
1848 for (Int_t i = 0; i < nmeth_used[0]; i++) {
1849 MethodBase *theMethod = dynamic_cast<MethodBase *>((*methods)[i]);
1850 if (theMethod == 0)
1851 continue;
1852
1853 Log() << kINFO
1854 << Form("%-20s %-15s:%#9.3g%#9.3g%#9.3g%#9.3g | %#5.3f %#5.3f", theMethod->fDataSetInfo.GetName(),
1855 (const char *)mname[0][i], biastest[0][i], biastestT[0][i], rmstest[0][i], rmstestT[0][i],
1856 minftest[0][i], minftestT[0][i])
1857 << Endl;
1858 }
1859 Log() << kINFO << hLine << Endl;
1860 Log() << kINFO << Endl;
1861 Log() << kINFO << "Evaluation results ranked by smallest RMS on training sample:" << Endl;
1862 Log() << kINFO << "(overtraining check)" << Endl;
1863 Log() << kINFO << hLine << Endl;
1864 Log() << kINFO
1865 << "DataSet Name: MVA Method: <Bias> <Bias_T> RMS RMS_T | MutInf MutInf_T"
1866 << Endl;
1867 Log() << kINFO << hLine << Endl;
1868
1869 for (Int_t i = 0; i < nmeth_used[0]; i++) {
1870 MethodBase *theMethod = dynamic_cast<MethodBase *>((*methods)[i]);
1871 if (theMethod == 0)
1872 continue;
1873 Log() << kINFO
1874 << Form("%-20s %-15s:%#9.3g%#9.3g%#9.3g%#9.3g | %#5.3f %#5.3f", theMethod->fDataSetInfo.GetName(),
1875 (const char *)mname[0][i], biastrain[0][i], biastrainT[0][i], rmstrain[0][i], rmstrainT[0][i],
1876 minftrain[0][i], minftrainT[0][i])
1877 << Endl;
1878 }
1879 Log() << kINFO << hLine << Endl;
1880 Log() << kINFO << Endl;
1881 } else if (doMulticlass) {
1882 // ====================================================================
1883 // === Multiclass Output
1884 // ====================================================================
1885
1886 TString hLine =
1887 "-------------------------------------------------------------------------------------------------------";
1888
1889 // This part uses a genetic alg. to evaluate the optimal sig eff * sig pur.
1890 // This is why it is disabled for now.
1891 //
1892 // // --- Acheivable signal efficiency * signal purity
1893 // // --------------------------------------------------------------------
1894 // Log() << kINFO << Endl;
1895 // Log() << kINFO << "Evaluation results ranked by best signal efficiency times signal purity " << Endl;
1896 // Log() << kINFO << hLine << Endl;
1897
1898 // // iterate over methods and evaluate
1899 // for (MVector::iterator itrMethod = methods->begin(); itrMethod != methods->end(); itrMethod++) {
1900 // MethodBase *theMethod = dynamic_cast<MethodBase *>(*itrMethod);
1901 // if (theMethod == 0) {
1902 // continue;
1903 // }
1904
1905 // TString header = "DataSet Name MVA Method ";
1906 // for (UInt_t icls = 0; icls < theMethod->fDataSetInfo.GetNClasses(); ++icls) {
1907 // header += TString::Format("%-12s ", theMethod->fDataSetInfo.GetClassInfo(icls)->GetName());
1908 // }
1909
1910 // Log() << kINFO << header << Endl;
1911 // Log() << kINFO << hLine << Endl;
1912 // for (Int_t i = 0; i < nmeth_used[0]; i++) {
1913 // TString res = TString::Format("[%-14s] %-15s", theMethod->fDataSetInfo.GetName(), mname[0][i].Data());
1914 // for (UInt_t icls = 0; icls < theMethod->fDataSetInfo.GetNClasses(); ++icls) {
1915 // res += TString::Format("%#1.3f ", (multiclass_testEff[i][icls]) * (multiclass_testPur[i][icls]));
1916 // }
1917 // Log() << kINFO << res << Endl;
1918 // }
1919
1920 // Log() << kINFO << hLine << Endl;
1921 // Log() << kINFO << Endl;
1922 // }
1923
1924 // --- 1 vs Rest ROC AUC, signal efficiency @ given background efficiency
1925 // --------------------------------------------------------------------
1926 TString header1 = TString::Format("%-15s%-15s%-15s%-15s%-15s%-15s", "Dataset", "MVA Method", "ROC AUC", "Sig eff@B=0.01",
1927 "Sig eff@B=0.10", "Sig eff@B=0.30");
1928 TString header2 = TString::Format("%-15s%-15s%-15s%-15s%-15s%-15s", "Name:", "/ Class:", "test (train)", "test (train)",
1929 "test (train)", "test (train)");
1930 Log() << kINFO << Endl;
1931 Log() << kINFO << "1-vs-rest performance metrics per class" << Endl;
1932 Log() << kINFO << hLine << Endl;
1933 Log() << kINFO << Endl;
1934 Log() << kINFO << "Considers the listed class as signal and the other classes" << Endl;
1935 Log() << kINFO << "as background, reporting the resulting binary performance." << Endl;
1936 Log() << kINFO << "A score of 0.820 (0.850) means 0.820 was acheived on the" << Endl;
1937 Log() << kINFO << "test set and 0.850 on the training set." << Endl;
1938
1939 Log() << kINFO << Endl;
1940 Log() << kINFO << header1 << Endl;
1941 Log() << kINFO << header2 << Endl;
1942 for (Int_t k = 0; k < 2; k++) {
1943 for (Int_t i = 0; i < nmeth_used[k]; i++) {
1944 if (k == 1) {
1945 mname[k][i].ReplaceAll("Variable_", "");
1946 }
1947
1948 const TString datasetName = itrMap->first;
1949 const TString mvaName = mname[k][i];
1950
1951 MethodBase *theMethod = dynamic_cast<MethodBase *>(GetMethod(datasetName, mvaName));
1952 if (theMethod == 0) {
1953 continue;
1954 }
1955
1956 Log() << kINFO << Endl;
1957 TString row = TString::Format("%-15s%-15s", datasetName.Data(), mvaName.Data());
1958 Log() << kINFO << row << Endl;
1959 Log() << kINFO << "------------------------------" << Endl;
1960
1961 UInt_t numClasses = theMethod->fDataSetInfo.GetNClasses();
1962 for (UInt_t iClass = 0; iClass < numClasses; ++iClass) {
1963
1966
1967 const TString className = theMethod->DataInfo().GetClassInfo(iClass)->GetName();
1968 const Double_t rocaucTrain = rocCurveTrain->GetROCIntegral();
1969 const Double_t effB01Train = rocCurveTrain->GetEffSForEffB(0.01);
1970 const Double_t effB10Train = rocCurveTrain->GetEffSForEffB(0.10);
1971 const Double_t effB30Train = rocCurveTrain->GetEffSForEffB(0.30);
1972 const Double_t rocaucTest = rocCurveTest->GetROCIntegral();
1973 const Double_t effB01Test = rocCurveTest->GetEffSForEffB(0.01);
1974 const Double_t effB10Test = rocCurveTest->GetEffSForEffB(0.10);
1975 const Double_t effB30Test = rocCurveTest->GetEffSForEffB(0.30);
1976 const TString rocaucCmp = TString::Format("%5.3f (%5.3f)", rocaucTest, rocaucTrain);
1977 const TString effB01Cmp = TString::Format("%5.3f (%5.3f)", effB01Test, effB01Train);
1978 const TString effB10Cmp = TString::Format("%5.3f (%5.3f)", effB10Test, effB10Train);
1979 const TString effB30Cmp = TString::Format("%5.3f (%5.3f)", effB30Test, effB30Train);
1980 row = TString::Format("%-15s%-15s%-15s%-15s%-15s%-15s", "", className.Data(), rocaucCmp.Data(), effB01Cmp.Data(),
1981 effB10Cmp.Data(), effB30Cmp.Data());
1982 Log() << kINFO << row << Endl;
1983
1984 delete rocCurveTrain;
1985 delete rocCurveTest;
1986 }
1987 }
1988 }
1989 Log() << kINFO << Endl;
1990 Log() << kINFO << hLine << Endl;
1991 Log() << kINFO << Endl;
1992
1993 // --- Confusion matrices
1994 // --------------------------------------------------------------------
1995 auto printMatrix = [](TMatrixD const &matTraining, TMatrixD const &matTesting, std::vector<TString> classnames,
1996 UInt_t numClasses, MsgLogger &stream) {
1997 // assert (classLabledWidth >= valueLabelWidth + 2)
1998 // if (...) {Log() << kWARN << "..." << Endl; }
1999
2000 // TODO: Ensure matrices are same size.
2001
2002 TString header = TString::Format(" %-14s", " ");
2003 TString headerInfo = TString::Format(" %-14s", " ");
2004
2005 for (UInt_t iCol = 0; iCol < numClasses; ++iCol) {
2006 header += TString::Format(" %-14s", classnames[iCol].Data());
2007 headerInfo += TString::Format(" %-14s", " test (train)");
2008 }
2009 stream << kINFO << header << Endl;
2010 stream << kINFO << headerInfo << Endl;
2011
2012 for (UInt_t iRow = 0; iRow < numClasses; ++iRow) {
2013 stream << kINFO << TString::Format(" %-14s", classnames[iRow].Data());
2014
2015 for (UInt_t iCol = 0; iCol < numClasses; ++iCol) {
2016 if (iCol == iRow) {
2017 stream << kINFO << TString::Format(" %-14s", "-");
2018 } else {
2021 TString entry = TString::Format("%-5.3f (%-5.3f)", testValue, trainValue);
2022 stream << kINFO << TString::Format(" %-14s", entry.Data());
2023 }
2024 }
2025 stream << kINFO << Endl;
2026 }
2027 };
2028
2029 Log() << kINFO << Endl;
2030 Log() << kINFO << "Confusion matrices for all methods" << Endl;
2031 Log() << kINFO << hLine << Endl;
2032 Log() << kINFO << Endl;
2033 Log() << kINFO << "Does a binary comparison between the two classes given by a " << Endl;
2034 Log() << kINFO << "particular row-column combination. In each case, the class " << Endl;
2035 Log() << kINFO << "given by the row is considered signal while the class given " << Endl;
2036 Log() << kINFO << "by the column index is considered background." << Endl;
2037 Log() << kINFO << Endl;
2038 for (UInt_t iMethod = 0; iMethod < methods->size(); ++iMethod) {
2039 MethodBase *theMethod = dynamic_cast<MethodBase *>(methods->at(iMethod));
2040 if (theMethod == nullptr) {
2041 continue;
2042 }
2043 UInt_t numClasses = theMethod->fDataSetInfo.GetNClasses();
2044
2045 std::vector<TString> classnames;
2046 for (UInt_t iCls = 0; iCls < numClasses; ++iCls) {
2047 classnames.push_back(theMethod->fDataSetInfo.GetClassInfo(iCls)->GetName());
2048 }
2049 Log() << kINFO
2050 << "=== Showing confusion matrix for method : " << Form("%-15s", (const char *)mname[0][iMethod])
2051 << Endl;
2052 Log() << kINFO << "(Signal Efficiency for Background Efficiency 0.01%)" << Endl;
2053 Log() << kINFO << "---------------------------------------------------" << Endl;
2055 numClasses, Log());
2056 Log() << kINFO << Endl;
2057
2058 Log() << kINFO << "(Signal Efficiency for Background Efficiency 0.10%)" << Endl;
2059 Log() << kINFO << "---------------------------------------------------" << Endl;
2061 numClasses, Log());
2062 Log() << kINFO << Endl;
2063
2064 Log() << kINFO << "(Signal Efficiency for Background Efficiency 0.30%)" << Endl;
2065 Log() << kINFO << "---------------------------------------------------" << Endl;
2067 numClasses, Log());
2068 Log() << kINFO << Endl;
2069 }
2070 Log() << kINFO << hLine << Endl;
2071 Log() << kINFO << Endl;
2072
2073 } else {
2074 // Binary classification
2075 if (fROC) {
2076 Log().EnableOutput();
2078 Log() << Endl;
2079 TString hLine = "------------------------------------------------------------------------------------------"
2080 "-------------------------";
2081 Log() << kINFO << "Evaluation results ranked by best signal efficiency and purity (area)" << Endl;
2082 Log() << kINFO << hLine << Endl;
2083 Log() << kINFO << "DataSet MVA " << Endl;
2084 Log() << kINFO << "Name: Method: ROC-integ" << Endl;
2085
2086 // Log() << kDEBUG << "DataSet MVA Signal efficiency at bkg eff.(error):
2087 // | Sepa- Signifi- " << Endl; Log() << kDEBUG << "Name: Method: @B=0.01
2088 // @B=0.10 @B=0.30 ROC-integ ROCCurve| ration: cance: " << Endl;
2089 Log() << kDEBUG << hLine << Endl;
2090 for (Int_t k = 0; k < 2; k++) {
2091 if (k == 1 && nmeth_used[k] > 0) {
2092 Log() << kINFO << hLine << Endl;
2093 Log() << kINFO << "Input Variables: " << Endl << hLine << Endl;
2094 }
2095 for (Int_t i = 0; i < nmeth_used[k]; i++) {
2096 TString datasetName = itrMap->first;
2097 TString methodName = mname[k][i];
2098
2099 if (k == 1) {
2100 methodName.ReplaceAll("Variable_", "");
2101 }
2102
2103 MethodBase *theMethod = dynamic_cast<MethodBase *>(GetMethod(datasetName, methodName));
2104 if (theMethod == 0) {
2105 continue;
2106 }
2107
2108 TMVA::DataSet *dataset = theMethod->Data();
2109 TMVA::Results *results = dataset->GetResults(methodName, Types::kTesting, this->fAnalysisType);
2110 std::vector<Bool_t> *mvaResType =
2111 dynamic_cast<ResultsClassification *>(results)->GetValueVectorTypes();
2112
2113 Double_t rocIntegral = 0.0;
2114 if (mvaResType->size() != 0) {
2115 rocIntegral = GetROCIntegral(datasetName, methodName);
2116 }
2117
2118 if (sep[k][i] < 0 || sig[k][i] < 0) {
2119 // cannot compute separation/significance -> no MVA (usually for Cuts)
2120 Log() << kINFO << Form("%-13s %-15s: %#1.3f", datasetName.Data(), methodName.Data(), effArea[k][i])
2121 << Endl;
2122
2123 // Log() << kDEBUG << Form("%-20s %-15s: %#1.3f(%02i) %#1.3f(%02i) %#1.3f(%02i)
2124 // %#1.3f %#1.3f | -- --",
2125 // datasetName.Data(),
2126 // methodName.Data(),
2127 // eff01[k][i], Int_t(1000*eff01err[k][i]),
2128 // eff10[k][i], Int_t(1000*eff10err[k][i]),
2129 // eff30[k][i], Int_t(1000*eff30err[k][i]),
2130 // effArea[k][i],rocIntegral) << Endl;
2131 } else {
2132 Log() << kINFO << Form("%-13s %-15s: %#1.3f", datasetName.Data(), methodName.Data(), rocIntegral)
2133 << Endl;
2134 // Log() << kDEBUG << Form("%-20s %-15s: %#1.3f(%02i) %#1.3f(%02i) %#1.3f(%02i)
2135 // %#1.3f %#1.3f | %#1.3f %#1.3f",
2136 // datasetName.Data(),
2137 // methodName.Data(),
2138 // eff01[k][i], Int_t(1000*eff01err[k][i]),
2139 // eff10[k][i], Int_t(1000*eff10err[k][i]),
2140 // eff30[k][i], Int_t(1000*eff30err[k][i]),
2141 // effArea[k][i],rocIntegral,
2142 // sep[k][i], sig[k][i]) << Endl;
2143 }
2144 }
2145 }
2146 Log() << kINFO << hLine << Endl;
2147 Log() << kINFO << Endl;
2148 Log() << kINFO << "Testing efficiency compared to training efficiency (overtraining check)" << Endl;
2149 Log() << kINFO << hLine << Endl;
2150 Log() << kINFO
2151 << "DataSet MVA Signal efficiency: from test sample (from training sample) "
2152 << Endl;
2153 Log() << kINFO << "Name: Method: @B=0.01 @B=0.10 @B=0.30 "
2154 << Endl;
2155 Log() << kINFO << hLine << Endl;
2156 for (Int_t k = 0; k < 2; k++) {
2157 if (k == 1 && nmeth_used[k] > 0) {
2158 Log() << kINFO << hLine << Endl;
2159 Log() << kINFO << "Input Variables: " << Endl << hLine << Endl;
2160 }
2161 for (Int_t i = 0; i < nmeth_used[k]; i++) {
2162 if (k == 1)
2163 mname[k][i].ReplaceAll("Variable_", "");
2164 MethodBase *theMethod = dynamic_cast<MethodBase *>((*methods)[i]);
2165 if (theMethod == 0)
2166 continue;
2167
2168 Log() << kINFO
2169 << Form("%-20s %-15s: %#1.3f (%#1.3f) %#1.3f (%#1.3f) %#1.3f (%#1.3f)",
2170 theMethod->fDataSetInfo.GetName(), (const char *)mname[k][i], eff01[k][i],
2171 trainEff01[k][i], eff10[k][i], trainEff10[k][i], eff30[k][i], trainEff30[k][i])
2172 << Endl;
2173 }
2174 }
2175 Log() << kINFO << hLine << Endl;
2176 Log() << kINFO << Endl;
2177
2178 if (gTools().CheckForSilentOption(GetOptions()))
2179 Log().InhibitOutput();
2180 } // end fROC
2181 }
2182 if (!IsSilentFile()) {
2183 std::list<TString> datasets;
2184 for (Int_t k = 0; k < 2; k++) {
2185 for (Int_t i = 0; i < nmeth_used[k]; i++) {
2186 MethodBase *theMethod = dynamic_cast<MethodBase *>((*methods)[i]);
2187 if (theMethod == 0)
2188 continue;
2189 // write test/training trees
2190 RootBaseDir()->cd(theMethod->fDataSetInfo.GetName());
2191 if (std::find(datasets.begin(), datasets.end(), theMethod->fDataSetInfo.GetName()) == datasets.end()) {
2192 theMethod->fDataSetInfo.GetDataSet()->GetTree(Types::kTesting)->Write("", TObject::kOverwrite);
2193 theMethod->fDataSetInfo.GetDataSet()->GetTree(Types::kTraining)->Write("", TObject::kOverwrite);
2194 datasets.push_back(theMethod->fDataSetInfo.GetName());
2195 }
2196 }
2197 }
2198 }
2199 } // end for MethodsMap
2200 // references for citation
2202}
2203
2204////////////////////////////////////////////////////////////////////////////////
2205/// Evaluate Variable Importance
2206
2208 const char *theOption)
2209{
2210 fModelPersistence = kFALSE;
2211 fSilentFile = kTRUE; // we need silent file here because we need fast classification results
2212
2213 // getting number of variables and variable names from loader
2214 const int nbits = loader->GetDataSetInfo().GetNVariables();
2215 if (vitype == VIType::kShort)
2216 return EvaluateImportanceShort(loader, theMethod, methodTitle, theOption);
2217 else if (vitype == VIType::kAll)
2218 return EvaluateImportanceAll(loader, theMethod, methodTitle, theOption);
2219 else if (vitype == VIType::kRandom) {
2220 if ( nbits > 10 && nbits < 30) {
2221 // limit nbits to less than 30 to avoid error converting from double to uint and also cannot deal with too many combinations
2222 return EvaluateImportanceRandom(loader, static_cast<UInt_t>( pow(2, nbits) ), theMethod, methodTitle, theOption);
2223 } else if (nbits < 10) {
2224 Log() << kERROR << "Error in Variable Importance: Random mode require more that 10 variables in the dataset."
2225 << Endl;
2226 } else if (nbits > 30) {
2227 Log() << kERROR << "Error in Variable Importance: Number of variables is too large for Random mode"
2228 << Endl;
2229 }
2230 }
2231 return nullptr;
2232}
2233
2234////////////////////////////////////////////////////////////////////////////////
2235
2237 const char *theOption)
2238{
2239
2240 uint64_t x = 0;
2241 uint64_t y = 0;
2242
2243 // getting number of variables and variable names from loader
2244 const int nbits = loader->GetDataSetInfo().GetNVariables();
2245 std::vector<TString> varNames = loader->GetDataSetInfo().GetListOfVariables();
2246
2247 if (nbits > 60) {
2248 Log() << kERROR << "Number of combinations is too large , is 2^" << nbits << Endl;
2249 return nullptr;
2250 }
2251 if (nbits > 20) {
2252 Log() << kWARNING << "Number of combinations is very large , is 2^" << nbits << Endl;
2253 }
2254 uint64_t range = static_cast<uint64_t>(pow(2, nbits));
2255
2256
2257 // vector to save importances
2258 std::vector<Double_t> importances(nbits);
2259 // vector to save ROC
2260 std::vector<Double_t> ROC(range);
2261 ROC[0] = 0.5;
2262 for (int i = 0; i < nbits; i++)
2263 importances[i] = 0;
2264
2265 Double_t SROC, SSROC; // computed ROC value
2266 for (x = 1; x < range; x++) {
2267
2268 std::bitset<VIBITS> xbitset(x);
2269 if (x == 0)
2270 continue; // data loader need at least one variable
2271
2272 // creating loader for seed
2274
2275 // adding variables from seed
2276 for (int index = 0; index < nbits; index++) {
2277 if (xbitset[index])
2278 seedloader->AddVariable(varNames[index], 'F');
2279 }
2280
2282 seedloader->PrepareTrainingAndTestTree(loader->GetDataSetInfo().GetCut("Signal"),
2283 loader->GetDataSetInfo().GetCut("Background"),
2284 loader->GetDataSetInfo().GetSplitOptions());
2285
2286 // Booking Seed
2287 BookMethod(seedloader, theMethod, methodTitle, theOption);
2288
2289 // Train/Test/Evaluation
2290 TrainAllMethods();
2291 TestAllMethods();
2292 EvaluateAllMethods();
2293
2294 // getting ROC
2295 ROC[x] = GetROCIntegral(xbitset.to_string(), methodTitle);
2296
2297 // cleaning information to process sub-seeds
2298 TMVA::MethodBase *smethod = dynamic_cast<TMVA::MethodBase *>(fMethodsMap[xbitset.to_string().c_str()][0][0]);
2301 delete sresults;
2302 delete seedloader;
2303 this->DeleteAllMethods();
2304
2305 fMethodsMap.clear();
2306 // removing global result because it is requiring a lot of RAM for all seeds
2307 }
2308
2309 for (x = 0; x < range; x++) {
2310 SROC = ROC[x];
2311 for (uint32_t i = 0; i < VIBITS; ++i) {
2312 if (x & (uint64_t(1) << i)) {
2313 y = x & ~(uint64_t(1) << i);
2314 std::bitset<VIBITS> ybitset(y);
2315 // need at least one variable
2316 // NOTE: if sub-seed is zero then is the special case
2317 // that count in xbitset is 1
2318 uint32_t ny = static_cast<uint32_t>( log(x - y) / 0.693147 ) ;
2319 if (y == 0) {
2320 importances[ny] = SROC - 0.5;
2321 continue;
2322 }
2323
2324 // getting ROC
2325 SSROC = ROC[y];
2326 importances[ny] += SROC - SSROC;
2327 // cleaning information
2328 }
2329 }
2330 }
2331 std::cout << "--- Variable Importance Results (All)" << std::endl;
2332 return GetImportance(nbits, importances, varNames);
2333}
2334
2335static uint64_t sum(uint64_t i)
2336{
2337 // add a limit for overflows
2338 if (i > 62) return 0;
2339 return static_cast<uint64_t>( std::pow(2, i + 1)) - 1;
2340 // uint64_t _sum = 0;
2341 // for (uint64_t n = 0; n < i; n++)
2342 // _sum += pow(2, n);
2343 // return _sum;
2344}
2345
2346////////////////////////////////////////////////////////////////////////////////
2347
2349 const char *theOption)
2350{
2351 uint64_t x = 0;
2352 uint64_t y = 0;
2353
2354 // getting number of variables and variable names from loader
2355 const int nbits = loader->GetDataSetInfo().GetNVariables();
2356 std::vector<TString> varNames = loader->GetDataSetInfo().GetListOfVariables();
2357
2358 if (nbits > 60) {
2359 Log() << kERROR << "Number of combinations is too large , is 2^" << nbits << Endl;
2360 return nullptr;
2361 }
2362 long int range = sum(nbits);
2363 // std::cout<<range<<std::endl;
2364 // vector to save importances
2365 std::vector<Double_t> importances(nbits);
2366 for (int i = 0; i < nbits; i++)
2367 importances[i] = 0;
2368
2369 Double_t SROC, SSROC; // computed ROC value
2370
2371 x = range;
2372
2373 std::bitset<VIBITS> xbitset(x);
2374 if (x == 0)
2375 Log() << kFATAL << "Error: need at least one variable."; // data loader need at least one variable
2376
2377 // creating loader for seed
2379
2380 // adding variables from seed
2381 for (int index = 0; index < nbits; index++) {
2382 if (xbitset[index])
2383 seedloader->AddVariable(varNames[index], 'F');
2384 }
2385
2386 // Loading Dataset
2388
2389 // Booking Seed
2390 BookMethod(seedloader, theMethod, methodTitle, theOption);
2391
2392 // Train/Test/Evaluation
2393 TrainAllMethods();
2394 TestAllMethods();
2395 EvaluateAllMethods();
2396
2397 // getting ROC
2398 SROC = GetROCIntegral(xbitset.to_string(), methodTitle);
2399
2400 // cleaning information to process sub-seeds
2401 TMVA::MethodBase *smethod = dynamic_cast<TMVA::MethodBase *>(fMethodsMap[xbitset.to_string().c_str()][0][0]);
2404 delete sresults;
2405 delete seedloader;
2406 this->DeleteAllMethods();
2407 fMethodsMap.clear();
2408
2409 // removing global result because it is requiring a lot of RAM for all seeds
2410
2411 for (uint32_t i = 0; i < VIBITS; ++i) {
2412 if (x & (uint64_t(1) << i)) {
2413 y = x & ~(uint64_t(1) << i);
2414 std::bitset<VIBITS> ybitset(y);
2415 // need at least one variable
2416 // NOTE: if sub-seed is zero then is the special case
2417 // that count in xbitset is 1
2418 uint32_t ny = static_cast<uint32_t>(log(x - y) / 0.693147);
2419 if (y == 0) {
2420 importances[ny] = SROC - 0.5;
2421 continue;
2422 }
2423
2424 // creating loader for sub-seed
2426 // adding variables from sub-seed
2427 for (int index = 0; index < nbits; index++) {
2428 if (ybitset[index])
2429 subseedloader->AddVariable(varNames[index], 'F');
2430 }
2431
2432 // Loading Dataset
2434
2435 // Booking SubSeed
2436 BookMethod(subseedloader, theMethod, methodTitle, theOption);
2437
2438 // Train/Test/Evaluation
2439 TrainAllMethods();
2440 TestAllMethods();
2441 EvaluateAllMethods();
2442
2443 // getting ROC
2444 SSROC = GetROCIntegral(ybitset.to_string(), methodTitle);
2445 importances[ny] += SROC - SSROC;
2446
2447 // cleaning information
2448 TMVA::MethodBase *ssmethod = dynamic_cast<TMVA::MethodBase *>(fMethodsMap[ybitset.to_string().c_str()][0][0]);
2451 delete ssresults;
2452 delete subseedloader;
2453 this->DeleteAllMethods();
2454 fMethodsMap.clear();
2455 }
2456 }
2457 std::cout << "--- Variable Importance Results (Short)" << std::endl;
2458 return GetImportance(nbits, importances, varNames);
2459}
2460
2461////////////////////////////////////////////////////////////////////////////////
2462
2464 TString methodTitle, const char *theOption)
2465{
2466 TRandom3 *rangen = new TRandom3(0); // Random Gen.
2467
2468 uint64_t x = 0;
2469 uint64_t y = 0;
2470
2471 // getting number of variables and variable names from loader
2472 const int nbits = loader->GetDataSetInfo().GetNVariables();
2473 std::vector<TString> varNames = loader->GetDataSetInfo().GetListOfVariables();
2474
2475 long int range = pow(2, nbits);
2476
2477 // vector to save importances
2478 std::vector<Double_t> importances(nbits);
2479 for (int i = 0; i < nbits; i++)
2480 importances[i] = 0;
2481
2482 Double_t SROC, SSROC; // computed ROC value
2483 for (UInt_t n = 0; n < nseeds; n++) {
2484 x = rangen->Integer(range);
2485
2486 std::bitset<32> xbitset(x);
2487 if (x == 0)
2488 continue; // data loader need at least one variable
2489
2490 // creating loader for seed
2492
2493 // adding variables from seed
2494 for (int index = 0; index < nbits; index++) {
2495 if (xbitset[index])
2496 seedloader->AddVariable(varNames[index], 'F');
2497 }
2498
2499 // Loading Dataset
2501
2502 // Booking Seed
2503 BookMethod(seedloader, theMethod, methodTitle, theOption);
2504
2505 // Train/Test/Evaluation
2506 TrainAllMethods();
2507 TestAllMethods();
2508 EvaluateAllMethods();
2509
2510 // getting ROC
2511 SROC = GetROCIntegral(xbitset.to_string(), methodTitle);
2512 // std::cout << "Seed: n " << n << " x " << x << " xbitset:" << xbitset << " ROC " << SROC << std::endl;
2513
2514 // cleaning information to process sub-seeds
2515 TMVA::MethodBase *smethod = dynamic_cast<TMVA::MethodBase *>(fMethodsMap[xbitset.to_string().c_str()][0][0]);
2518 delete sresults;
2519 delete seedloader;
2520 this->DeleteAllMethods();
2521 fMethodsMap.clear();
2522
2523 // removing global result because it is requiring a lot of RAM for all seeds
2524
2525 for (uint32_t i = 0; i < 32; ++i) {
2526 if (x & (uint64_t(1) << i)) {
2527 y = x & ~(uint64_t(1) << i);
2528 std::bitset<32> ybitset(y);
2529 // need at least one variable
2530 // NOTE: if sub-seed is zero then is the special case
2531 // that count in xbitset is 1
2532 Double_t ny = log(x - y) / 0.693147;
2533 if (y == 0) {
2534 importances[ny] = SROC - 0.5;
2535 // std::cout << "SubSeed: " << y << " y:" << ybitset << "ROC " << 0.5 << std::endl;
2536 continue;
2537 }
2538
2539 // creating loader for sub-seed
2541 // adding variables from sub-seed
2542 for (int index = 0; index < nbits; index++) {
2543 if (ybitset[index])
2544 subseedloader->AddVariable(varNames[index], 'F');
2545 }
2546
2547 // Loading Dataset
2549
2550 // Booking SubSeed
2551 BookMethod(subseedloader, theMethod, methodTitle, theOption);
2552
2553 // Train/Test/Evaluation
2554 TrainAllMethods();
2555 TestAllMethods();
2556 EvaluateAllMethods();
2557
2558 // getting ROC
2559 SSROC = GetROCIntegral(ybitset.to_string(), methodTitle);
2560 importances[ny] += SROC - SSROC;
2561 // std::cout << "SubSeed: " << y << " y:" << ybitset << " x-y " << x - y << " " << std::bitset<32>(x - y) <<
2562 // " ny " << ny << " SROC " << SROC << " SSROC " << SSROC << " Importance = " << importances[ny] <<
2563 // std::endl; cleaning information
2565 dynamic_cast<TMVA::MethodBase *>(fMethodsMap[ybitset.to_string().c_str()][0][0]);
2568 delete ssresults;
2569 delete subseedloader;
2570 this->DeleteAllMethods();
2571 fMethodsMap.clear();
2572 }
2573 }
2574 }
2575 std::cout << "--- Variable Importance Results (Random)" << std::endl;
2576 return GetImportance(nbits, importances, varNames);
2577}
2578
2579////////////////////////////////////////////////////////////////////////////////
2580
2581TH1F *TMVA::Factory::GetImportance(const int nbits, std::vector<Double_t> importances, std::vector<TString> varNames)
2582{
2583 TH1F *vih1 = new TH1F("vih1", "", nbits, 0, nbits);
2584
2585 gStyle->SetOptStat(000000);
2586
2587 Float_t normalization = 0.0;
2588 for (int i = 0; i < nbits; i++) {
2590 }
2591
2592 Float_t roc = 0.0;
2593
2594 gStyle->SetTitleXOffset(0.4);
2595 gStyle->SetTitleXOffset(1.2);
2596
2597 std::vector<Double_t> x_ie(nbits), y_ie(nbits);
2598 for (Int_t i = 1; i < nbits + 1; i++) {
2599 x_ie[i - 1] = (i - 1) * 1.;
2600 roc = 100.0 * importances[i - 1] / normalization;
2601 y_ie[i - 1] = roc;
2602 std::cout << "--- " << varNames[i - 1] << " = " << roc << " %" << std::endl;
2603 vih1->GetXaxis()->SetBinLabel(i, varNames[i - 1].Data());
2604 vih1->SetBinContent(i, roc);
2605 }
2606 TGraph *g_ie = new TGraph(nbits + 2, &x_ie[0], &y_ie[0]);
2607 g_ie->SetTitle("");
2608
2609 vih1->LabelsOption("v >", "X");
2610 vih1->SetBarWidth(0.97);
2611 Int_t ca = TColor::GetColor("#006600");
2612 vih1->SetFillColor(ca);
2613 // Int_t ci = TColor::GetColor("#990000");
2614
2615 vih1->GetYaxis()->SetTitle("Importance (%)");
2616 vih1->GetYaxis()->SetTitleSize(0.045);
2617 vih1->GetYaxis()->CenterTitle();
2618 vih1->GetYaxis()->SetTitleOffset(1.24);
2619
2620 vih1->GetYaxis()->SetRangeUser(-7, 50);
2621 vih1->SetDirectory(nullptr);
2622
2623 // vih1->Draw("B");
2624 return vih1;
2625}
#define MinNoTrainingEvents
#define h(i)
Definition RSha256.hxx:106
void printMatrix(const TMatrixD &mat)
write a matrix
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 char Point_t Rectangle_t WindowAttributes_t index
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
char name[80]
Definition TGX11.cxx:148
TMatrixT< Double_t > TMatrixD
Definition TMatrixDfwd.h:23
#define gROOT
Definition TROOT.h:417
char * Form(const char *fmt,...)
Formats a string in a circular formatting buffer.
Definition TString.cxx:2570
R__EXTERN TStyle * gStyle
Definition TStyle.h:442
R__EXTERN TSystem * gSystem
Definition TSystem.h:582
const_iterator begin() const
const_iterator end() const
virtual void SetFillColor(Color_t fcolor)
Set the fill area color.
Definition TAttFill.h:40
virtual void SetLineWidth(Width_t lwidth)
Set the line width.
Definition TAttLine.h:47
virtual void SetLineColor(Color_t lcolor)
Set the line color.
Definition TAttLine.h:44
The Canvas class.
Definition TCanvas.h:23
static Int_t GetColor(const char *hexcolor)
Static method returning color number for color specified by hex color string of form: "#rrggbb",...
Definition TColor.cxx:1926
A file, usually with extension .root, that stores data and code in the form of serialized objects in ...
Definition TFile.h:130
A TGraph is an object made of two arrays X and Y with npoints each.
Definition TGraph.h:41
TAxis * GetXaxis() const
Get x axis of the graph.
Definition TGraph.cxx:1598
TAxis * GetYaxis() const
Get y axis of the graph.
Definition TGraph.cxx:1607
void SetTitle(const char *title="") override
Change (i.e.
Definition TGraph.cxx:2444
1-D histogram with a float per channel (see TH1 documentation)
Definition TH1.h:878
static void AddDirectory(Bool_t add=kTRUE)
Sets the flag controlling the automatic add of histograms in memory.
Definition TH1.cxx:1325
Service class for 2-D histogram classes.
Definition TH2.h:30
static ClassifierFactory & Instance()
access to the ClassifierFactory singleton creates the instance if needed
TString fWeightFileDir
Definition Config.h:124
TString fWeightFileDirPrefix
Definition Config.h:123
void SetDrawProgressBar(Bool_t d)
Definition Config.h:69
void SetUseColor(Bool_t uc)
Definition Config.h:60
class TMVA::Config::VariablePlotting fVariablePlotting
void SetSilent(Bool_t s)
Definition Config.h:63
IONames & GetIONames()
Definition Config.h:98
void SetConfigDescription(const char *d)
OptionBase * DeclareOptionRef(T &ref, const TString &name, const TString &desc="")
void AddPreDefVal(const T &)
void SetConfigName(const char *n)
virtual void ParseOptions()
options parser
const TString & GetOptions() const
MsgLogger & Log() const
MsgLogger * fLogger
! message logger
void CheckForUnusedOptions() const
checks for unused options in option string
Class that contains all the data information.
Definition DataSetInfo.h:62
const TMatrixD * CorrelationMatrix(const TString &className) const
UInt_t GetNClasses() const
DataSet * GetDataSet() const
returns data set
TH2 * CreateCorrelationMatrixHist(const TMatrixD *m, const TString &hName, const TString &hTitle) const
const char * GetName() const override
Returns name of object.
Definition DataSetInfo.h:71
ClassInfo * GetClassInfo(Int_t clNum) const
Class that contains all the data information.
Definition DataSet.h:58
Results * GetResults(const TString &, Types::ETreeType type, Types::EAnalysisType analysistype)
Definition DataSet.cxx:265
void SetCurrentType(Types::ETreeType type) const
Definition DataSet.h:89
const std::vector< Event * > & GetEventCollection(Types::ETreeType type=Types::kMaxTreeType) const
Definition DataSet.h:216
static void SetIsTraining(Bool_t)
when this static function is called, it sets the flag whether events with negative event weight shoul...
Definition Event.cxx:399
void PrintHelpMessage(const TString &datasetname, const TString &methodTitle="") const
Print predefined help message of classifier.
Definition Factory.cxx:1324
Bool_t fCorrelations
! enable to calculate correlations
Definition Factory.h:224
std::vector< IMethod * > MVector
Definition Factory.h:84
void TrainAllMethods()
Iterates through all booked methods and calls training.
Definition Factory.cxx:1105
Bool_t Verbose(void) const
Definition Factory.h:143
void WriteDataInformation(DataSetInfo &fDataSetInfo)
Definition Factory.cxx:593
Factory(TString theJobName, TFile *theTargetFile, TString theOption="")
Standard constructor.
Definition Factory.cxx:109
void TestAllMethods()
Evaluates all booked methods on the testing data and adds the output to the Results in the corresponi...
Definition Factory.cxx:1262
Bool_t fVerbose
! verbose mode
Definition Factory.h:222
void EvaluateAllMethods(void)
Iterates over all MVAs that have been booked, and calls their evaluation methods.
Definition Factory.cxx:1367
TH1F * EvaluateImportanceRandom(DataLoader *loader, UInt_t nseeds, Types::EMVA theMethod, TString methodTitle, const char *theOption="")
Definition Factory.cxx:2463
TH1F * GetImportance(const int nbits, std::vector< Double_t > importances, std::vector< TString > varNames)
Definition Factory.cxx:2581
Bool_t fROC
! enable to calculate ROC values
Definition Factory.h:225
void EvaluateAllVariables(DataLoader *loader, TString options="")
Iterates over all MVA input variables and evaluates them.
Definition Factory.cxx:1351
TString fVerboseLevel
! verbosity level, controls granularity of logging
Definition Factory.h:223
TMultiGraph * GetROCCurveAsMultiGraph(DataLoader *loader, UInt_t iClass, Types::ETreeType type=Types::kTesting)
Generate a collection of graphs, for all methods for a given class.
Definition Factory.cxx:979
TH1F * EvaluateImportance(DataLoader *loader, VIType vitype, Types::EMVA theMethod, TString methodTitle, const char *theOption="")
Evaluate Variable Importance.
Definition Factory.cxx:2207
Double_t GetROCIntegral(DataLoader *loader, TString theMethodName, UInt_t iClass=0, Types::ETreeType type=Types::kTesting)
Calculate the integral of the ROC curve, also known as the area under curve (AUC),...
Definition Factory.cxx:840
virtual ~Factory()
Destructor.
Definition Factory.cxx:302
MethodBase * BookMethod(DataLoader *loader, MethodName theMethodName, TString methodTitle, TString theOption="")
Books an MVA classifier or regression method.
Definition Factory.cxx:354
virtual void MakeClass(const TString &datasetname, const TString &methodTitle="") const
Definition Factory.cxx:1296
MethodBase * BookMethodWeightfile(DataLoader *dataloader, TMVA::Types::EMVA methodType, const TString &weightfile)
Adds an already constructed method to be managed by this factory.
Definition Factory.cxx:492
Bool_t fModelPersistence
! option to save the trained model in xml file or using serialization
Definition Factory.h:231
std::map< TString, Double_t > OptimizeAllMethods(TString fomType="ROCIntegral", TString fitType="FitGA")
Iterates through all booked methods and sees if they use parameter tuning and if so does just that,...
Definition Factory.cxx:692
ROCCurve * GetROC(DataLoader *loader, TString theMethodName, UInt_t iClass=0, Types::ETreeType type=Types::kTesting)
Private method to generate a ROCCurve instance for a given method.
Definition Factory.cxx:740
TH1F * EvaluateImportanceShort(DataLoader *loader, Types::EMVA theMethod, TString methodTitle, const char *theOption="")
Definition Factory.cxx:2348
Types::EAnalysisType fAnalysisType
! the training type
Definition Factory.h:230
Bool_t HasMethod(const TString &datasetname, const TString &title) const
Checks whether a given method name is defined for a given dataset.
Definition Factory.cxx:577
TGraph * GetROCCurve(DataLoader *loader, TString theMethodName, Bool_t setTitles=kTRUE, UInt_t iClass=0, Types::ETreeType type=Types::kTesting)
Argument iClass specifies the class to generate the ROC curve in a multiclass setting.
Definition Factory.cxx:903
TH1F * EvaluateImportanceAll(DataLoader *loader, Types::EMVA theMethod, TString methodTitle, const char *theOption="")
Definition Factory.cxx:2236
void SetVerbose(Bool_t v=kTRUE)
Definition Factory.cxx:339
TFile * fgTargetFile
! ROOT output file
Definition Factory.h:214
IMethod * GetMethod(const TString &datasetname, const TString &title) const
Returns pointer to MVA that corresponds to given method title.
Definition Factory.cxx:557
void DeleteAllMethods(void)
Delete methods.
Definition Factory.cxx:320
TString fTransformations
! list of transformations to test
Definition Factory.h:221
void Greetings()
Print welcome message.
Definition Factory.cxx:291
Interface for all concrete MVA method implementations.
Definition IMethod.h:53
Virtual base Class for all MVA method.
Definition MethodBase.h:82
const TString & GetMethodName() const
Definition MethodBase.h:305
Class for boosting a TMVA method.
Definition MethodBoost.h:58
Class for categorizing the phase space.
ostringstream derivative to redirect and format output
Definition MsgLogger.h:57
void SetMinType(EMsgType minType)
Definition MsgLogger.h:70
void SetSource(const std::string &source)
Definition MsgLogger.h:68
static void InhibitOutput()
Definition MsgLogger.cxx:66
Ranking for variables in method (implementation)
Definition Ranking.h:48
Class that is the base-class for a vector of result.
Class which takes the results of a multiclass classification.
Class that is the base-class for a vector of result.
Definition Results.h:57
void FormattedOutput(const std::vector< Double_t > &, const std::vector< TString > &, const TString titleVars, const TString titleValues, MsgLogger &logger, TString format="%+1.3f")
formatted output of simple table
Definition Tools.cxx:862
void ROOTVersionMessage(MsgLogger &logger)
prints the ROOT release number and date
Definition Tools.cxx:1300
void UsefulSortDescending(std::vector< std::vector< Double_t > > &, std::vector< TString > *vs=nullptr)
sort 2D vector (AND in parallel a TString vector) in such a way that the "first vector is sorted" and...
Definition Tools.cxx:539
std::vector< TString > SplitString(const TString &theOpt, const char separator) const
splits the option string at 'separator' and fills the list 'splitV' with the primitive strings
Definition Tools.cxx:1174
const TString & Color(const TString &)
human readable color strings
Definition Tools.cxx:803
const TMatrixD * GetCorrelationMatrix(const TMatrixD *covMat)
turns covariance into correlation matrix
Definition Tools.cxx:299
@ kHtmlLink
Definition Tools.h:212
void UsefulSortAscending(std::vector< std::vector< Double_t > > &, std::vector< TString > *vs=nullptr)
sort 2D vector (AND in parallel a TString vector) in such a way that the "first vector is sorted" and...
Definition Tools.cxx:513
void TMVACitation(MsgLogger &logger, ECitation citType=kPlainText)
kinds of TMVA citation
Definition Tools.cxx:1415
void TMVAVersionMessage(MsgLogger &logger)
prints the TMVA release number and date
Definition Tools.cxx:1291
void TMVAWelcomeMessage()
direct output, eg, when starting ROOT session -> no use of Logger here
Definition Tools.cxx:1277
Class that contains all the data information.
Singleton class for Global types used by TMVA.
Definition Types.h:71
static Types & Instance()
The single instance of "Types" if existing already, or create it (Singleton)
Definition Types.cxx:70
@ kCategory
Definition Types.h:97
@ kMulticlass
Definition Types.h:129
@ kNoAnalysisType
Definition Types.h:130
@ kClassification
Definition Types.h:127
@ kMaxAnalysisType
Definition Types.h:131
@ kRegression
Definition Types.h:128
@ kTraining
Definition Types.h:143
A TMultiGraph is a collection of TGraph (or derived) objects.
Definition TMultiGraph.h:34
virtual void SetTitle(const char *title="")
Set the title of the TNamed.
Definition TNamed.cxx:173
const char * GetName() const override
Returns name of object.
Definition TNamed.h:49
TString fName
Definition TNamed.h:32
@ kOverwrite
overwrite existing object with same name
Definition TObject.h:101
virtual const char * GetName() const
Returns name of object.
Definition TObject.cxx:461
virtual Int_t Write(const char *name=nullptr, Int_t option=0, Int_t bufsize=0)
Write this object to the current directory.
Definition TObject.cxx:987
void SetGrid(Int_t valuex=1, Int_t valuey=1) override
Definition TPad.h:341
TLegend * BuildLegend(Double_t x1=0.3, Double_t y1=0.21, Double_t x2=0.3, Double_t y2=0.21, const char *title="", Option_t *option="") override
Build a legend from the graphical objects in the pad.
Definition TPad.cxx:556
Principal Components Analysis (PCA)
Definition TPrincipal.h:21
Random number generator class based on M.
Definition TRandom3.h:27
Basic string class.
Definition TString.h:138
void ToLower()
Change string to lower-case.
Definition TString.cxx:1189
int CompareTo(const char *cs, ECaseCompare cmp=kExact) const
Compare a string to char *cs2.
Definition TString.cxx:464
const char * Data() const
Definition TString.h:386
TString & ReplaceAll(const TString &s1, const TString &s2)
Definition TString.h:715
Bool_t IsNull() const
Definition TString.h:424
static TString Format(const char *fmt,...)
Static method which formats a string using a printf style format descriptor and return a TString.
Definition TString.cxx:2459
Bool_t Contains(const char *pat, ECaseCompare cmp=kExact) const
Definition TString.h:643
void SetOptStat(Int_t stat=1)
The type of information printed in the histogram statistics box can be selected via the parameter mod...
Definition TStyle.cxx:1641
void SetTitleXOffset(Float_t offset=1)
Definition TStyle.h:413
virtual int MakeDirectory(const char *name)
Make a directory.
Definition TSystem.cxx:840
Double_t y[n]
Definition legend1.C:17
Double_t x[n]
Definition legend1.C:17
const Int_t n
Definition legend1.C:16
void DataLoaderCopy(TMVA::DataLoader *des, TMVA::DataLoader *src)
Config & gConfig()
Tools & gTools()
void CreateVariableTransforms(const TString &trafoDefinition, TMVA::DataSetInfo &dataInfo, TMVA::TransformationHandler &transformationHandler, TMVA::MsgLogger &log)
MsgLogger & Endl(MsgLogger &ml)
Definition MsgLogger.h:148
Bool_t IsNaN(Double_t x)
Definition TMath.h:905
TMarker m
Definition textangle.C:8
#define VIBITS
Definition Factory.cxx:99
static uint64_t sum(uint64_t i)
Definition Factory.cxx:2335
const Int_t MinNoTrainingEvents
Definition Factory.cxx:92
#define READXML
Definition Factory.cxx:96