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
109TMVA::Factory::Factory(TString jobName, TFile *theTargetFile, TString theOption)
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";
115 fgTargetFile = theTargetFile;
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);
129 Bool_t silent = 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;
134 Bool_t drawProgressBar = kFALSE;
135#else
136 Bool_t color = !gROOT->IsBatch();
137 Bool_t drawProgressBar = kTRUE;
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);
181 gConfig().SetSilent(silent);
182 gConfig().SetDrawProgressBar(drawProgressBar);
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
219 Bool_t silent = kFALSE;
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;
224 Bool_t drawProgressBar = kFALSE;
225#else
226 Bool_t color = !gROOT->IsBatch();
227 Bool_t drawProgressBar = kTRUE;
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);
271 gConfig().SetSilent(silent);
272 gConfig().SetDrawProgressBar(drawProgressBar);
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;
390 TMVA::Configurable *conf = new TMVA::Configurable(theOption);
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
395 TString fileDir;
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();
404 fileDir += "/" + gConfig().GetIONames().fWeightFileDir;
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
498 IMethod *im = ClassifierFactory::Instance().Create(methodTypeName, dsi, weightfile);
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
508 TString fileDir;
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();
517 fileDir += "/" + gConfig().GetIONames().fWeightFileDir;
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
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
557TMVA::IMethod *TMVA::Factory::GetMethod(const TString &datasetname, const TString &methodTitle) const
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
577Bool_t TMVA::Factory::HasMethod(const TString &datasetname, const TString &methodTitle) const
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);
586 Bool_t isMethodNameExisting = std::any_of(methods->begin(), methods->end(), isEqualToMethodName);
587
588 return isMethodNameExisting;
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;
652 TransformationHandler *identityTrHandler = 0;
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 }
678 if (identityTrHandler)
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
692std::map<TString, Double_t> TMVA::Factory::OptimizeAllMethods(TString fomType, TString fitType)
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
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
741{
742 return GetROC((TString)loader->GetName(), theMethodName, iClass, type);
743}
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
800 rocCurve = new TMVA::ROCCurve(*mvaRes, *mvaResTypes, mvaResWeights);
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
825 rocCurve = new TMVA::ROCCurve(mvaRes, mvaResTypes, mvaResWeights);
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
841{
842 return GetROCIntegral((TString)loader->GetName(), theMethodName, iClass, type);
843}
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
873 TMVA::ROCCurve *rocCurve = GetROC(datasetname, theMethodName, iClass, type);
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
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
903TGraph *TMVA::Factory::GetROCCurve(DataLoader *loader, TString theMethodName, Bool_t setTitles, UInt_t iClass,
905{
906 return GetROCCurve((TString)loader->GetName(), theMethodName, setTitles, iClass, type);
907}
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
923TGraph *TMVA::Factory::GetROCCurve(TString datasetname, TString theMethodName, Bool_t setTitles, UInt_t iClass,
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
944 TMVA::ROCCurve *rocCurve = GetROC(datasetname, theMethodName, iClass, type);
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
980{
981 return GetROCCurveAsMultiGraph((TString)loader->GetName(), iClass, type);
982}
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
1000 TMultiGraph *multigraph = new TMultiGraph();
1001
1002 MVector *methods = fMethodsMap[datasetname.Data()];
1003 for (auto *method_raw : *methods) {
1004 TMVA::MethodBase *method = dynamic_cast<TMVA::MethodBase *>(method_raw);
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
1053{
1054 return GetROCCurve((TString)loader->GetName(), iClass, type);
1055}
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
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();
1241 wfileDir += "/" + gConfig().GetIONames().fWeightFileDir;
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++) {
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
1434 MVector methodsNoCuts;
1435
1436 Bool_t doRegression = kFALSE;
1437 Bool_t doMulticlass = kFALSE;
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()) {
1451 doRegression = kTRUE;
1452
1453 Log() << kINFO << "Evaluate regression method: " << theMethod->GetMethodName() << Endl;
1454 Double_t bias, dev, rms, mInf;
1455 Double_t biasT, devT, rmsT, mInfT;
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;
1488 }
1489 } else if (theMethod->DoMulticlass()) {
1490 // ====================================================================
1491 // === Multiclass evaluation
1492 // ====================================================================
1493 doMulticlass = kTRUE;
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;
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;
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]);
1580 gTools().UsefulSortAscending(vtmp, &vtemps);
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];
1623 gTools().UsefulSortDescending(vtemp, &vtemps);
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
1679 TMatrixD *overlapS = new TMatrixD(nmeth, nmeth);
1680 TMatrixD *overlapB = new TMatrixD(nmeth, nmeth);
1681 (*overlapS) *= 0; // init...
1682 (*overlapB) *= 0; // init...
1683
1684 // loop over test tree
1685 DataSet *defDs = method->fDataSetInfo.GetDataSet();
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
1734 const TMatrixD *corrMatS = gTools().GetCorrelationMatrix(covMatS);
1735 const TMatrixD *corrMatB = gTools().GetCorrelationMatrix(covMatB);
1736
1737 // print correlation matrices
1738 if (corrMatS != 0 && corrMatB != 0) {
1739
1740 // extract MVA matrix
1741 TMatrixD mvaMatS(nmeth, nmeth);
1742 TMatrixD mvaMatB(nmeth, nmeth);
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;
1766 gTools().FormattedOutput(mvaMatS, *theVars, Log());
1767 Log() << kINFO << Endl;
1768
1769 Log() << kINFO << Form("Dataset[%s] : ", method->fDataSetInfo.GetName())
1770 << "Inter-MVA correlation matrix (background):" << Endl;
1771 gTools().FormattedOutput(mvaMatB, *theVars, Log());
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;
1777 gTools().FormattedOutput(varmvaMatS, theInputVars, *theVars, Log());
1778 Log() << kINFO << Endl;
1779
1780 Log() << kINFO << Form("Dataset[%s] : ", method->fDataSetInfo.GetName())
1781 << "Correlations between input variables and MVA response (background):" << Endl;
1782 gTools().FormattedOutput(varmvaMatB, theInputVars, *theVars, Log());
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;
1808 gTools().FormattedOutput(*overlapS, *theVars, Log());
1809 Log() << kINFO << Endl;
1810
1811 Log() << kINFO << Form("Dataset[%s] : ", method->fDataSetInfo.GetName())
1812 << "Inter-MVA overlap matrix (background):" << Endl;
1813 gTools().FormattedOutput(*overlapB, *theVars, Log());
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
1964 ROCCurve *rocCurveTrain = GetROC(datasetName, mvaName, iClass, Types::kTraining);
1965 ROCCurve *rocCurveTest = GetROC(datasetName, mvaName, iClass, Types::kTesting);
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 {
2019 Double_t trainValue = matTraining[iRow][iCol];
2020 Double_t testValue = matTesting[iRow][iCol];
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;
2054 printMatrix(multiclass_testConfusionEffB01[iMethod], multiclass_trainConfusionEffB01[iMethod], classnames,
2055 numClasses, Log());
2056 Log() << kINFO << Endl;
2057
2058 Log() << kINFO << "(Signal Efficiency for Background Efficiency 0.10%)" << Endl;
2059 Log() << kINFO << "---------------------------------------------------" << Endl;
2060 printMatrix(multiclass_testConfusionEffB10[iMethod], multiclass_trainConfusionEffB10[iMethod], classnames,
2061 numClasses, Log());
2062 Log() << kINFO << Endl;
2063
2064 Log() << kINFO << "(Signal Efficiency for Background Efficiency 0.30%)" << Endl;
2065 Log() << kINFO << "---------------------------------------------------" << Endl;
2066 printMatrix(multiclass_testConfusionEffB30[iMethod], multiclass_trainConfusionEffB30[iMethod], classnames,
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()) {
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
2207TH1F *TMVA::Factory::EvaluateImportance(DataLoader *loader, VIType vitype, Types::EMVA theMethod, TString methodTitle,
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
2273 TMVA::DataLoader *seedloader = new TMVA::DataLoader(xbitset.to_string());
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
2281 DataLoaderCopy(seedloader, loader);
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
2378 TMVA::DataLoader *seedloader = new TMVA::DataLoader(xbitset.to_string());
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
2387 DataLoaderCopy(seedloader, loader);
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
2425 TMVA::DataLoader *subseedloader = new TMVA::DataLoader(ybitset.to_string());
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
2433 DataLoaderCopy(subseedloader, loader);
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
2491 TMVA::DataLoader *seedloader = new TMVA::DataLoader(xbitset.to_string());
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
2500 DataLoaderCopy(seedloader, loader);
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
2540 TMVA::DataLoader *subseedloader = new TMVA::DataLoader(ybitset.to_string());
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
2548 DataLoaderCopy(subseedloader, loader);
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
2564 TMVA::MethodBase *ssmethod =
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++) {
2589 normalization = normalization + importances[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 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
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:142
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:2571
R__EXTERN TStyle * gStyle
Definition TStyle.h:442
R__EXTERN TSystem * gSystem
Definition TSystem.h:582
virtual void SetTitleOffset(Float_t offset=1)
Set distance between the axis and the axis title.
Definition TAttAxis.cxx:279
virtual void SetTitleSize(Float_t size=0.04)
Set size of axis title.
Definition TAttAxis.cxx:290
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
virtual void SetBinLabel(Int_t bin, const char *label)
Set label for bin.
Definition TAxis.cxx:898
void CenterTitle(Bool_t center=kTRUE)
Center axis title.
Definition TAxis.h:196
virtual void SetRangeUser(Double_t ufirst, Double_t ulast)
Set the viewing range for the axis from ufirst to ulast (in user coordinates, that is,...
Definition TAxis.cxx:1097
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:1939
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:1595
TAxis * GetYaxis() const
Get y axis of the graph.
Definition TGraph.cxx:1604
void SetTitle(const char *title="") override
Change (i.e.
Definition TGraph.cxx:2441
1-D histogram with a float per channel (see TH1 documentation)
Definition TH1.h:878
virtual void SetDirectory(TDirectory *dir)
By default, when a histogram is created, it is added to the list of histogram objects in the current ...
Definition TH1.cxx:9170
void SetTitle(const char *title) override
Change/set the title.
Definition TH1.cxx:6932
virtual void LabelsOption(Option_t *option="h", Option_t *axis="X")
Sort bins with labels or set option(s) to draw axis with labels.
Definition TH1.cxx:5560
static void AddDirectory(Bool_t add=kTRUE)
Sets the flag controlling the automatic add of histograms in memory.
Definition TH1.cxx:1325
TAxis * GetXaxis()
Definition TH1.h:571
TAxis * GetYaxis()
Definition TH1.h:572
virtual void SetBinContent(Int_t bin, Double_t content)
Set bin content see convention for numbering bins in TH1::GetBin In case the bin number is greater th...
Definition TH1.cxx:9452
virtual void SetBarWidth(Float_t width=0.5)
Set the width of bars as fraction of the bin width for drawing mode "B".
Definition TH1.h:613
Service class for 2-D histogram classes.
Definition TH2.h:30
IMethod * Create(const std::string &name, const TString &job, const TString &title, DataSetInfo &dsi, const TString &option)
creates the method if needed based on the method name using the creator function the factory has stor...
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
UInt_t GetEntries(const TString &name) const
void PrepareTrainingAndTestTree(const TCut &cut, const TString &splitOpt)
prepare the training and test trees -> same cuts for signal and background
DataSetInfo & GetDataSetInfo()
void AddVariable(const TString &expression, const TString &title, const TString &unit, char type='F', Double_t min=0, Double_t max=0)
user inserts discriminating variable in data set info
Class that contains all the data information.
Definition DataSetInfo.h:62
UInt_t GetNVariables() const
const TMatrixD * CorrelationMatrix(const TString &className) const
UInt_t GetNClasses() const
const TString & GetSplitOptions() const
UInt_t GetNTargets() const
DataSet * GetDataSet() const
returns data set
TH2 * CreateCorrelationMatrixHist(const TMatrixD *m, const TString &hName, const TString &hTitle) const
std::vector< TString > GetListOfVariables() const
returns list of variables
const char * GetName() const override
Returns name of object.
Definition DataSetInfo.h:71
ClassInfo * GetClassInfo(Int_t clNum) const
const TCut & GetCut(Int_t i) const
VariableInfo & GetVariableInfo(Int_t i)
Bool_t IsSignal(const Event *ev) const
DataSetManager * GetDataSetManager()
DataInputHandler & DataInput()
Class that contains all the data information.
Definition DataSet.h:58
Long64_t GetNEvtSigTest()
return number of signal test events in dataset
Definition DataSet.cxx:427
TTree * GetTree(Types::ETreeType type)
create the test/trainings tree with all the variables, the weights, the classes, the targets,...
Definition DataSet.cxx:609
const Event * GetEvent() const
returns event without transformations
Definition DataSet.cxx:202
Long64_t GetNEvents(Types::ETreeType type=Types::kMaxTreeType) const
Definition DataSet.h:206
Results * GetResults(const TString &, Types::ETreeType type, Types::EAnalysisType analysistype)
Definition DataSet.cxx:265
Long64_t GetNTrainingEvents() const
Definition DataSet.h:68
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
Long64_t GetNEvtBkgdTest()
return number of background test events in dataset
Definition DataSet.cxx:435
Float_t GetValue(UInt_t ivar) const
return value of i'th variable
Definition Event.cxx:236
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
TString const & tString() const
Definition Factory.h:109
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 void PrintHelpMessage() const =0
virtual Bool_t HasAnalysisType(Types::EAnalysisType type, UInt_t numberClasses, UInt_t numberTargets)=0
virtual void MakeClass(const TString &classFileName=TString("")) const =0
Virtual base Class for all MVA method.
Definition MethodBase.h:79
void PrintHelpMessage() const override
prints out method-specific help method
virtual Double_t GetSeparation(TH1 *, TH1 *) const
compute "separation" defined as
const char * GetName() const override
Definition MethodBase.h:304
void SetSilentFile(Bool_t status)
Definition MethodBase.h:348
void SetWeightFileDir(TString fileDir)
set directory of weight file
virtual void TestRegression(Double_t &bias, Double_t &biasT, Double_t &dev, Double_t &devT, Double_t &rms, Double_t &rmsT, Double_t &mInf, Double_t &mInfT, Double_t &corr, Types::ETreeType type)
calculate <sum-of-deviation-squared> of regression output versus "true" value from test sample
virtual void DeclareCompatibilityOptions()
options that are used ONLY for the READER to ensure backward compatibility they are hence without any...
TString GetMethodTypeName() const
Definition MethodBase.h:302
Bool_t DoMulticlass() const
Definition MethodBase.h:409
virtual Double_t GetSignificance() const
compute significance of mean difference
Types::EAnalysisType GetAnalysisType() const
Definition MethodBase.h:407
virtual TMatrixD GetMulticlassConfusionMatrix(Double_t effB, Types::ETreeType type)
Construct a confusion matrix for a multiclass classifier.
virtual void WriteEvaluationHistosToFile(Types::ETreeType treetype)
writes all MVA evaluation histograms to file
virtual void TestMulticlass()
test multiclass classification
void SetupMethod()
setup of methods
virtual Double_t GetEfficiency(const TString &, Types::ETreeType, Double_t &err)
fill background efficiency (resp.
virtual void SetAnalysisType(Types::EAnalysisType type)
Definition MethodBase.h:406
const TString & GetMethodName() const
Definition MethodBase.h:301
Bool_t DoRegression() const
Definition MethodBase.h:408
void ProcessSetup()
process all options the "CheckForUnusedOptions" is done in an independent call, since it may be overr...
virtual Double_t GetTrainingEfficiency(const TString &)
DataSetInfo & DataInfo() const
Definition MethodBase.h:380
virtual void TestClassification()
initialization
void AddOutput(Types::ETreeType type, Types::EAnalysisType analysisType)
void MakeClass(const TString &classFileName=TString("")) const override
create reader class for method (classification only at present)
void ReadStateFromFile()
Function to write options and weights to file.
virtual std::map< TString, Double_t > OptimizeTuningParameters(TString fomType="ROCIntegral", TString fitType="FitGA")
call the Optimizer with the set of parameters and ranges that are meant to be tuned.
DataSetInfo & fDataSetInfo
! the data set information (sometimes needed)
Definition MethodBase.h:540
Types::EMVA GetMethodType() const
Definition MethodBase.h:303
void SetFile(TFile *file)
Definition MethodBase.h:345
DataSet * Data() const
Definition MethodBase.h:379
void SetModelPersistence(Bool_t status)
Definition MethodBase.h:352
virtual Double_t GetROCIntegral(TH1D *histS, TH1D *histB) const
calculate the area (integral) under the ROC curve as a overall quality measure of the classification
virtual void CheckSetup()
check may be overridden by derived class (sometimes, eg, fitters are used which can only be implement...
Class for boosting a TMVA method.
Definition MethodBoost.h:55
void SetBoostedMethodName(TString methodName)
Definition MethodBoost.h:82
DataSetManager * fDataSetManager
DSMTEST.
Class for categorizing the phase space.
DataSetManager * fDataSetManager
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
Double_t GetEffSForEffB(Double_t effB, const UInt_t num_points=41)
Calculate the signal efficiency (sensitivity) for a given background efficiency (sensitivity).
Definition ROCCurve.cxx:217
Double_t GetROCIntegral(const UInt_t points=41)
Calculates the ROC integral (AUC)
Definition ROCCurve.cxx:248
TGraph * GetROCCurve(const UInt_t points=100)
Returns a new TGraph containing the ROC curve.
Definition ROCCurve.cxx:274
Ranking for variables in method (implementation)
Definition Ranking.h:48
virtual void Print() const
get maximum length of variable names
Definition Ranking.cxx:110
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.
void PrintVariableRanking() const
prints ranking of input variables
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
const TString & GetLabel() const
A TMultiGraph is a collection of TGraph (or derived) objects.
Definition TMultiGraph.h:34
TList * GetListOfGraphs() const
Definition TMultiGraph.h:70
virtual void Add(TGraph *graph, Option_t *chopt="")
Add a new graph to the list of graphs.
TH1F * GetHistogram()
Returns a pointer to the histogram used to draw the axis.
void Draw(Option_t *chopt="") override
Draw this multigraph with its current attributes.
TAxis * GetYaxis()
Get y axis of the graph.
TAxis * GetXaxis()
Get x axis of the graph.
TObject * Clone(const char *newname="") const override
Make a clone of an object using the Streamer facility.
Definition TNamed.cxx:73
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
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
@ kOverwrite
overwrite existing object with same name
Definition TObject.h:101
void SetGrid(Int_t valuex=1, Int_t valuey=1) override
Definition TPad.h:353
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:619
Principal Components Analysis (PCA)
Definition TPrincipal.h:21
virtual void AddRow(const Double_t *x)
Add a data point and update the covariance matrix.
const TMatrixD * GetCovarianceMatrix() const
Return the covariance matrix.
Definition TPrincipal.h:60
virtual void MakePrincipals()
Perform the principal components analysis.
Random number generator class based on M.
Definition TRandom3.h:27
virtual UInt_t Integer(UInt_t imax)
Returns a random integer uniformly distributed on the interval [ 0, imax-1 ].
Definition TRandom.cxx:360
Basic string class.
Definition TString.h:137
Ssiz_t Length() const
Definition TString.h:426
void ToLower()
Change string to lower-case.
Definition TString.cxx:1190
int CompareTo(const char *cs, ECaseCompare cmp=kExact) const
Compare a string to char *cs2.
Definition TString.cxx:465
const char * Data() const
Definition TString.h:385
TString & ReplaceAll(const TString &s1, const TString &s2)
Definition TString.h:714
Bool_t BeginsWith(const char *s, ECaseCompare cmp=kExact) const
Definition TString.h:633
Bool_t IsNull() const
Definition TString.h:423
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:2460
Bool_t Contains(const char *pat, ECaseCompare cmp=kExact) const
Definition TString.h:642
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:841
Int_t Write(const char *name=nullptr, Int_t option=0, Int_t bufsize=0) override
Write this object to the current directory.
Definition TTree.cxx:10181
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