Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
TMVA_CNN_Classification.C
Go to the documentation of this file.
1/// \file
2/// \ingroup tutorial_ml
3/// \notebook -nodraw
4/// TMVA Classification Example Using a Convolutional Neural Network
5///
6/// This is an example of using a CNN in TMVA. We do classification using a toy image data set
7/// that is generated when running the example macro
8///
9/// \macro_image
10/// \macro_code
11/// \macro_output
12///
13/// \author Lorenzo Moneta
14
15/***
16
17 # TMVA Classification Example Using a Convolutional Neural Network
18
19
20**/
21
22/// Helper function to create input images data
23/// we create a signal and background 2D histograms from 2d gaussians
24/// with a location (means in X and Y) different for each event
25/// The difference between signal and background is in the gaussian width.
26/// The width for the background gaussian is slightly larger than the signal width by few % values
27///
28///
29void MakeImagesTree(int n, int nh, int nw)
30{
31
32 // image size (nh x nw)
33 const int ntot = nh * nw;
34 const TString fileOutName = TString::Format("images_data_%dx%d.root", nh, nw);
35 TFile f(fileOutName, "RECREATE");
36
37 const int nRndmEvts = 10000; // number of events we use to fill each image
38 double delta_sigma = 0.1; // 5% difference in the sigma
39 double pixelNoise = 5;
40
41 double sX1 = 3;
42 double sY1 = 3;
43 double sX2 = sX1 + delta_sigma;
44 double sY2 = sY1 - delta_sigma;
45
46 TH2D h1("h1", "h1", nh, 0, 10, nw, 0, 10);
47 TH2D h2("h2", "h2", nh, 0, 10, nw, 0, 10);
48
49 TF2 f1("f1", "xygaus");
50 TF2 f2("f2", "xygaus");
51
52 TTree sgn("sig_tree", "signal_tree");
53 TTree bkg("bkg_tree", "background_tree");
54
55
56 std::vector<float> x1(ntot);
57 std::vector<float> x2(ntot);
58
59 // create signal and background trees with a single branch
60 // an std::vector<float> of size nh x nw containing the image data
61
62 std::vector<float> *px1 = &x1;
63 std::vector<float> *px2 = &x2;
64
65 bkg.Branch("vars", "std::vector<float>", &px1);
66 sgn.Branch("vars", "std::vector<float>", &px2);
67
68 // std::cout << "create tree " << std::endl;
69
70 sgn.SetDirectory(&f);
71 bkg.SetDirectory(&f);
72
73 f1.SetParameters(1, 5, sX1, 5, sY1);
74 f2.SetParameters(1, 5, sX2, 5, sY2);
75 gRandom->SetSeed(0);
76 std::cout << "Filling ROOT tree " << std::endl;
77 for (int i = 0; i < n; ++i) {
78 if (i % 1000 == 0)
79 std::cout << "Generating image event ... " << i << std::endl;
80 h1.Reset();
81 h2.Reset();
82 // generate random means in range [3,7] to be not too much on the border
83 f1.SetParameter(1, gRandom->Uniform(3, 7));
84 f1.SetParameter(3, gRandom->Uniform(3, 7));
85 f2.SetParameter(1, gRandom->Uniform(3, 7));
86 f2.SetParameter(3, gRandom->Uniform(3, 7));
87
88 h1.FillRandom("f1", nRndmEvts);
89 h2.FillRandom("f2", nRndmEvts);
90
91 for (int k = 0; k < nh; ++k) {
92 for (int l = 0; l < nw; ++l) {
93 int m = k * nw + l;
94 // add some noise in each bin
95 x1[m] = h1.GetBinContent(k + 1, l + 1) + gRandom->Gaus(0, pixelNoise);
96 x2[m] = h2.GetBinContent(k + 1, l + 1) + gRandom->Gaus(0, pixelNoise);
97 }
98 }
99 sgn.Fill();
100 bkg.Fill();
101 }
102 sgn.Write();
103 bkg.Write();
104
105 Info("MakeImagesTree", "Signal and background tree with images data written to the file %s", f.GetName());
106 sgn.Print();
107 bkg.Print();
108 f.Close();
109}
110
111/// @brief Run the TMVA CNN Classification example
112/// @param nevts : number of signal/background events. Use by default a low value (1000)
113/// but increase to at least 5000 to get a good result
114/// @param opt : vector of bool with method used (default all on if available). The order is:
115/// - TMVA CNN
116/// - Keras CNN
117/// - TMVA DNN
118/// - TMVA BDT
119/// - PyTorch CNN
120void TMVA_CNN_Classification(int nevts = 1000, std::vector<bool> opt = {1, 1, 1, 1, 1})
121{
122
123 int imgSize = 16 * 16;
124 TString inputFileName = "images_data_16x16.root";
125
126 bool fileExist = !gSystem->AccessPathName(inputFileName);
127
128 // if file does not exists create it
129 if (!fileExist) {
130 MakeImagesTree(nevts, 16, 16);
131 }
132
133 bool useTMVACNN = (opt.size() > 0) ? opt[0] : false;
134 bool useTMVADNN = (opt.size() > 2) ? opt[2] : false;
135 bool useTMVABDT = (opt.size() > 3) ? opt[3] : false;
136#ifndef R__HAS_TMVACPU
137#ifndef R__HAS_TMVAGPU
138 Warning("TMVA_CNN_Classification",
139 "TMVA is not build with GPU or CPU multi-thread support. Cannot use TMVA Deep Learning for CNN");
140 useTMVACNN = false;
141#endif
142#endif
143
144 bool writeOutputFile = true;
145
146#ifdef R__USE_IMT
147 int num_threads = 4; // use by default 4 threads if value is not set before
148 // switch off MT in OpenBLAS to avoid conflict with tbb
149 gSystem->Setenv("OMP_NUM_THREADS", "1");
150
151 // do enable MT running
152 if (num_threads >= 0) {
153 ROOT::EnableImplicitMT(num_threads);
154 }
155#endif
156
158
159
160 std::cout << "Running with nthreads = " << ROOT::GetThreadPoolSize() << std::endl;
161
162 TFile *outputFile = nullptr;
163 if (writeOutputFile)
164 outputFile = TFile::Open("TMVA_CNN_ClassificationOutput.root", "RECREATE");
165
166 /***
167 ## Create TMVA Factory
168
169 Create the Factory class. Later you can choose the methods
170 whose performance you'd like to investigate.
171
172 The factory is the major TMVA object you have to interact with. Here is the list of parameters you need to pass
173
174 - The first argument is the base of the name of all the output
175 weight files in the directory weight/ that will be created with the
176 method parameters
177
178 - The second argument is the output file for the training results
179
180 - The third argument is a string option defining some general configuration for the TMVA session.
181 For example all TMVA output can be suppressed by removing the "!" (not) in front of the "Silent" argument in the
182 option string
183
184 - note that we disable any pre-transformation of the input variables and we avoid computing correlations between
185 input variables
186 ***/
187
188 TMVA::Factory factory(
189 "TMVA_CNN_Classification", outputFile,
190 "!V:ROC:!Silent:Color:AnalysisType=Classification:Transformations=None:!Correlations");
191
192 /***
193
194 ## Declare DataLoader(s)
195
196 The next step is to declare the DataLoader class that deals with input variables
197
198 Define the input variables that shall be used for the MVA training
199 note that you may also use variable expressions, which can be parsed by TTree::Draw( "expression" )]
200
201 In this case the input data consists of an image of 16x16 pixels. Each single pixel is a branch in a ROOT TTree
202
203 **/
204
205 TMVA::DataLoader loader("dataset");
206
207 /***
208
209 ## Setup Dataset(s)
210
211 Define input data file and signal and background trees
212
213 **/
214
215 std::unique_ptr<TFile> inputFile{TFile::Open(inputFileName)};
216 if (!inputFile) {
217 Error("TMVA_CNN_Classification", "Error opening input file %s - exit", inputFileName.Data());
218 return;
219 }
220
221 // --- Register the training and test trees
222
223 auto signalTree = inputFile->Get<TTree>("sig_tree");
224 auto backgroundTree = inputFile->Get<TTree>("bkg_tree");
225
226 if (!signalTree) {
227 Error("TMVA_CNN_Classification", "Could not find signal tree in file '%s'", inputFileName.Data());
228 return;
229 }
230 if (!backgroundTree) {
231 Error("TMVA_CNN_Classification", "Could not find background tree in file '%s'", inputFileName.Data());
232 return;
233 }
234
235 int nEventsSig = signalTree->GetEntries();
236 int nEventsBkg = backgroundTree->GetEntries();
237
238 // global event weights per tree (see below for setting event-wise weights)
239 Double_t signalWeight = 1.0;
240 Double_t backgroundWeight = 1.0;
241
242 // You can add an arbitrary number of signal or background trees
243 loader.AddSignalTree(signalTree, signalWeight);
244 loader.AddBackgroundTree(backgroundTree, backgroundWeight);
245
246 /// add event variables (image)
247 /// use new method (from ROOT 6.20 to add a variable array for all image data)
248 loader.AddVariablesArray("vars", imgSize);
249
250 // Set individual event weights (the variables must exist in the original TTree)
251 // for signal : factory->SetSignalWeightExpression ("weight1*weight2");
252 // for background: factory->SetBackgroundWeightExpression("weight1*weight2");
253 // loader.SetBackgroundWeightExpression( "weight" );
254
255 // Apply additional cuts on the signal and background samples (can be different)
256 TCut mycuts = ""; // for example: TCut mycuts = "abs(var1)<0.5 && abs(var2-0.5)<1";
257 TCut mycutb = ""; // for example: TCut mycutb = "abs(var1)<0.5";
258
259 // Tell the factory how to use the training and testing events
260 //
261 // If no numbers of events are given, half of the events in the tree are used
262 // for training, and the other half for testing:
263 // loader.PrepareTrainingAndTestTree( mycut, "SplitMode=random:!V" );
264 // It is possible also to specify the number of training and testing events,
265 // note we disable the computation of the correlation matrix of the input variables
266
267 int nTrainSig = 0.8 * nEventsSig;
268 int nTrainBkg = 0.8 * nEventsBkg;
269
270 // build the string options for DataLoader::PrepareTrainingAndTestTree
271 TString prepareOptions = TString::Format(
272 "nTrain_Signal=%d:nTrain_Background=%d:SplitMode=Random:SplitSeed=100:NormMode=NumEvents:!V:!CalcCorrelations",
273 nTrainSig, nTrainBkg);
274
275 loader.PrepareTrainingAndTestTree(mycuts, mycutb, prepareOptions);
276
277 /***
278
279 DataSetInfo : [dataset] : Added class "Signal"
280 : Add Tree sig_tree of type Signal with 10000 events
281 DataSetInfo : [dataset] : Added class "Background"
282 : Add Tree bkg_tree of type Background with 10000 events
283
284
285
286 **/
287
288 /****
289 # Booking Methods
290
291 Here we book the TMVA methods. We book a Boosted Decision Tree method (BDT)
292
293 **/
294
295 // Boosted Decision Trees
296 if (useTMVABDT) {
297 factory.BookMethod(&loader, TMVA::Types::kBDT, "BDT",
298 "!V:NTrees=200:MinNodeSize=2.5%:MaxDepth=2:BoostType=AdaBoost:AdaBoostBeta=0.5:"
299 "UseBaggedBoost:BaggedSampleFraction=0.5:SeparationType=GiniIndex:nCuts=20");
300 }
301 /**
302
303 #### Booking Deep Neural Network
304
305 Here we book the DNN of TMVA. See the example TMVA_Higgs_Classification.C for a detailed description of the
306 options
307
308 **/
309
310 if (useTMVADNN) {
311
312 TString layoutString(
313 "Layout=DENSE|100|RELU,BNORM,DENSE|100|RELU,BNORM,DENSE|100|RELU,BNORM,DENSE|100|RELU,DENSE|1|LINEAR");
314
315 // Training strategies
316 // one can catenate several training strings with different parameters (e.g. learning rates or regularizations
317 // parameters) The training string must be concatenates with the `|` delimiter
318 TString trainingString1("LearningRate=1e-3,Momentum=0.9,Repetitions=1,"
319 "ConvergenceSteps=5,BatchSize=100,TestRepetitions=1,"
320 "MaxEpochs=10,WeightDecay=1e-4,Regularization=None,"
321 "Optimizer=ADAM,DropConfig=0.0+0.0+0.0+0.");
322
323 TString trainingStrategyString("TrainingStrategy=");
324 trainingStrategyString += trainingString1; // + "|" + trainingString2 + ....
325
326 // Build now the full DNN Option string
327
328 TString dnnOptions("!H:V:ErrorStrategy=CROSSENTROPY:VarTransform=None:"
329 "WeightInitialization=XAVIER");
330 dnnOptions.Append(":");
331 dnnOptions.Append(layoutString);
332 dnnOptions.Append(":");
333 dnnOptions.Append(trainingStrategyString);
334
335 TString dnnMethodName = "TMVA_DNN_CPU";
336// use GPU if available
337#ifdef R__HAS_TMVAGPU
338 dnnOptions += ":Architecture=GPU";
339 dnnMethodName = "TMVA_DNN_GPU";
340#elif defined(R__HAS_TMVACPU)
341 dnnOptions += ":Architecture=CPU";
342#endif
343
344 factory.BookMethod(&loader, TMVA::Types::kDL, dnnMethodName, dnnOptions);
345 }
346
347 /***
348 ### Book Convolutional Neural Network in TMVA
349
350 For building a CNN one needs to define
351
352 - Input Layout : number of channels (in this case = 1) | image height | image width
353 - Batch Layout : batch size | number of channels | image size = (height*width)
354
355 Then one add Convolutional layers and MaxPool layers.
356
357 - For Convolutional layer the option string has to be:
358 - CONV | number of units | filter height | filter width | stride height | stride width | padding height | paddig
359 width | activation function
360
361 - note in this case we are using a filer 3x3 and padding=1 and stride=1 so we get the output dimension of the
362 conv layer equal to the input
363
364 - note we use after the first convolutional layer a batch normalization layer. This seems to help significantly the
365 convergence
366
367 - For the MaxPool layer:
368 - MAXPOOL | pool height | pool width | stride height | stride width
369
370 The RESHAPE layer is needed to flatten the output before the Dense layer
371
372
373 Note that to run the CNN is required to have CPU or GPU support
374
375 ***/
376
377 if (useTMVACNN) {
378
379 TString inputLayoutString("InputLayout=1|16|16");
380
381 // Batch Layout
382 TString layoutString("Layout=CONV|10|3|3|1|1|1|1|RELU,BNORM,CONV|10|3|3|1|1|1|1|RELU,MAXPOOL|2|2|1|1,"
383 "RESHAPE|FLAT,DENSE|100|RELU,DENSE|1|LINEAR");
384
385 // Training strategies.
386 TString trainingString1("LearningRate=1e-3,Momentum=0.9,Repetitions=1,"
387 "ConvergenceSteps=5,BatchSize=100,TestRepetitions=1,"
388 "MaxEpochs=10,WeightDecay=1e-4,Regularization=None,"
389 "Optimizer=ADAM,DropConfig=0.0+0.0+0.0+0.0");
390
391 TString trainingStrategyString("TrainingStrategy=");
392 trainingStrategyString +=
393 trainingString1; // + "|" + trainingString2 + "|" + trainingString3; for concatenating more training strings
394
395 // Build full CNN Options.
396 TString cnnOptions("!H:V:ErrorStrategy=CROSSENTROPY:VarTransform=None:"
397 "WeightInitialization=XAVIER");
398
399 cnnOptions.Append(":");
400 cnnOptions.Append(inputLayoutString);
401 cnnOptions.Append(":");
402 cnnOptions.Append(layoutString);
403 cnnOptions.Append(":");
404 cnnOptions.Append(trainingStrategyString);
405
406 //// New DL (CNN)
407 TString cnnMethodName = "TMVA_CNN_CPU";
408// use GPU if available
409#ifdef R__HAS_TMVAGPU
410 cnnOptions += ":Architecture=GPU";
411 cnnMethodName = "TMVA_CNN_GPU";
412#else
413 cnnOptions += ":Architecture=CPU";
414 cnnMethodName = "TMVA_CNN_CPU";
415#endif
416
417 factory.BookMethod(&loader, TMVA::Types::kDL, cnnMethodName, cnnOptions);
418 }
419
420 /**
421 ### Book Convolutional Neural Network in Keras using a generated model
422
423 **/
424
425 //// ## Train Methods
426
427 factory.TrainAllMethods();
428
429 /// ## Test and Evaluate Methods
430
431 factory.TestAllMethods();
432
433 factory.EvaluateAllMethods();
434
435 /// ## Plot ROC Curve
436
437 auto c1 = factory.GetROCCurve(&loader);
438 c1->Draw();
439
440 // close outputfile to save output file
441 outputFile->Close();
442}
#define f(i)
Definition RSha256.hxx:104
double Double_t
Double 8 bytes.
Definition RtypesCore.h:74
void Info(const char *location, const char *msgfmt,...)
Use this function for informational messages.
Definition TError.cxx:241
void Error(const char *location, const char *msgfmt,...)
Use this function in case an error occurred.
Definition TError.cxx:208
void Warning(const char *location, const char *msgfmt,...)
Use this function in warning situations.
Definition TError.cxx:252
Option_t Option_t TPoint TPoint const char x2
Option_t Option_t TPoint TPoint const char x1
R__EXTERN TRandom * gRandom
Definition TRandom.h:73
R__EXTERN TSystem * gSystem
Definition TSystem.h:582
A specialized string object used for TTree selections.
Definition TCut.h:25
virtual void SetParameters(const Double_t *params)
Definition TF1.h:618
virtual void SetParameter(Int_t param, Double_t value)
Definition TF1.h:608
A 2-Dim function with parameters.
Definition TF2.h:29
A file, usually with extension .root, that stores data and code in the form of serialized objects in ...
Definition TFile.h:130
static TFile * Open(const char *name, Option_t *option="", const char *ftitle="", Int_t compress=ROOT::RCompressionSetting::EDefaults::kUseCompiledDefault, Int_t netopt=0)
Create / open a file.
Definition TFile.cxx:3802
void Close(Option_t *option="") override
Close a file.
Definition TFile.cxx:992
void Reset(Option_t *option="") override
Reset.
Definition TH1.cxx:10516
virtual void FillRandom(TF1 *f1, Int_t ntimes=5000, TRandom *rng=nullptr)
Definition TH1.cxx:3673
virtual Double_t GetBinContent(Int_t bin) const
Return content of bin number bin.
Definition TH1.cxx:5239
2-D histogram with a double per channel (see TH1 documentation)
Definition TH2.h:400
This is the main MVA steering class.
Definition Factory.h:80
static Tools & Instance()
Definition Tools.cxx:72
virtual Double_t Gaus(Double_t mean=0, Double_t sigma=1)
Samples a random number from the standard Normal (Gaussian) Distribution with the given mean and sigm...
Definition TRandom.cxx:274
virtual void SetSeed(ULong_t seed=0)
Set the random generator seed.
Definition TRandom.cxx:614
virtual Double_t Uniform(Double_t x1=1)
Returns a uniform deviate on the interval (0, x1).
Definition TRandom.cxx:681
Basic string class.
Definition TString.h:137
const char * Data() const
Definition TString.h:385
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
virtual Bool_t AccessPathName(const char *path, EAccessMode mode=kFileExists)
Returns FALSE if one can access a file using the specified access mode.
Definition TSystem.cxx:1318
virtual void Setenv(const char *name, const char *value)
Set environment variable.
Definition TSystem.cxx:1671
A TTree represents a columnar dataset.
Definition TTree.h:95
virtual Long64_t GetEntries() const
Definition TTree.h:524
return c1
Definition legend1.C:41
const Int_t n
Definition legend1.C:16
TH1F * h1
Definition legend1.C:5
TF1 * f1
Definition legend1.C:11
void EnableImplicitMT(UInt_t numthreads=0)
Enable ROOT's implicit multi-threading for all objects and methods that provide an internal paralleli...
Definition TROOT.cxx:617
UInt_t GetThreadPoolSize()
Returns the size of ROOT's thread pool.
Definition TROOT.cxx:680
TMarker m
Definition textangle.C:8
TLine l
Definition textangle.C:4