Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
TMVA_RNN_Classification.C
Go to the documentation of this file.
1/// \file
2/// \ingroup tutorial_ml
3/// \notebook
4/// TMVA Classification Example Using a Recurrent Neural Network
5///
6/// This is an example of using a RNN in TMVA. We do classification using a toy time dependent data set
7/// that is generated when running this example macro
8///
9/// \macro_code
10///
11/// \author Lorenzo Moneta
12/***
13
14 # TMVA Classification Example Using a Recurrent Neural Network
15
16 This is an example of using a RNN in TMVA.
17 We do the classification using a toy data set containing a time series of data sample ntimes
18 and with dimension ndim that is generated when running the provided function `MakeTimeData (nevents, ntime, ndim)`
19
20
21**/
22
23#include<TROOT.h>
24
25#include "TMVA/Factory.h"
26#include "TMVA/DataLoader.h"
27#include "TMVA/DataSetInfo.h"
28#include "TMVA/Config.h"
29#include "TMVA/MethodDL.h"
30
31
32#include "TFile.h"
33#include "TTree.h"
34
35/// Helper function to generate the time data set
36/// make some time data but not of fixed length.
37/// use a poisson with mu = 5 and truncated at 10
38///
39void MakeTimeData(int n, int ntime, int ndim )
40{
41
42 // const int ntime = 10;
43 // const int ndim = 30; // number of dim/time
44 TString fname = TString::Format("time_data_t%d_d%d.root", ntime, ndim);
45 std::vector<TH1 *> v1(ntime);
46 std::vector<TH1 *> v2(ntime);
47 int i = 0;
48 for (int i = 0; i < ntime; ++i) {
49 v1[i] = new TH1D(TString::Format("h1_%d", i), "h1", ndim, 0, 10);
50 v2[i] = new TH1D(TString::Format("h2_%d", i), "h2", ndim, 0, 10);
51 }
52
53 auto f1 = new TF1("f1", "gaus");
54 auto f2 = new TF1("f2", "gaus");
55
56 TFile f(fname, "RECREATE");
57 TTree sgn("sgn", "sgn");
58 TTree bkg("bkg", "bkg");
59
60 std::vector<std::vector<float>> x1(ntime);
61 std::vector<std::vector<float>> x2(ntime);
62
63 for (int i = 0; i < ntime; ++i) {
64 x1[i] = std::vector<float>(ndim);
65 x2[i] = std::vector<float>(ndim);
66 }
67
68 for (auto i = 0; i < ntime; i++) {
69 bkg.Branch(Form("vars_time%d", i), "std::vector<float>", &x1[i]);
70 sgn.Branch(Form("vars_time%d", i), "std::vector<float>", &x2[i]);
71 }
72
73 sgn.SetDirectory(&f);
74 bkg.SetDirectory(&f);
75 gRandom->SetSeed(0);
76
77 std::vector<double> mean1(ntime);
78 std::vector<double> mean2(ntime);
79 std::vector<double> sigma1(ntime);
80 std::vector<double> sigma2(ntime);
81 for (int j = 0; j < ntime; ++j) {
82 mean1[j] = 5. + 0.2 * sin(TMath::Pi() * j / double(ntime));
83 mean2[j] = 5. + 0.2 * cos(TMath::Pi() * j / double(ntime));
84 sigma1[j] = 4 + 0.3 * sin(TMath::Pi() * j / double(ntime));
85 sigma2[j] = 4 + 0.3 * cos(TMath::Pi() * j / double(ntime));
86 }
87 for (int i = 0; i < n; ++i) {
88
89 if (i % 1000 == 0)
90 std::cout << "Generating event ... " << i << std::endl;
91
92 for (int j = 0; j < ntime; ++j) {
93 auto h1 = v1[j];
94 auto h2 = v2[j];
95 h1->Reset();
96 h2->Reset();
97
98 f1->SetParameters(1, mean1[j], sigma1[j]);
99 f2->SetParameters(1, mean2[j], sigma2[j]);
100
101 h1->FillRandom("f1", 1000);
102 h2->FillRandom("f2", 1000);
103
104 for (int k = 0; k < ndim; ++k) {
105 // std::cout << j*10+k << " ";
106 x1[j][k] = h1->GetBinContent(k + 1) + gRandom->Gaus(0, 10);
107 x2[j][k] = h2->GetBinContent(k + 1) + gRandom->Gaus(0, 10);
108 }
109 }
110 // std::cout << std::endl;
111 sgn.Fill();
112 bkg.Fill();
113
114 if (n == 1) {
115 auto c1 = new TCanvas();
116 c1->Divide(ntime, 2);
117 for (int j = 0; j < ntime; ++j) {
118 c1->cd(j + 1);
119 v1[j]->Draw();
120 }
121 for (int j = 0; j < ntime; ++j) {
122 c1->cd(ntime + j + 1);
123 v2[j]->Draw();
124 }
125 gPad->Update();
126 }
127 }
128 if (n > 1) {
129 sgn.Write();
130 bkg.Write();
131 sgn.Print();
132 bkg.Print();
133 f.Close();
134 }
135}
136/// macro for performing a classification using a Recurrent Neural Network
137/// @param nevts = 2000 Number of events used. (increase for better classification results)
138/// @param use_type
139/// use_type = 0 use Simple RNN network
140/// use_type = 1 use LSTM network
141/// use_type = 2 use GRU
142/// use_type = 3 build 3 different networks with RNN, LSTM and GRU
143
144void TMVA_RNN_Classification(int nevts = 2000, int use_type = 1)
145{
146
147 const int ninput = 30;
148 const int ntime = 10;
149 const int batchSize = 100;
150 const int maxepochs = 20;
151
152 int nTotEvts = nevts; // total events to be generated for signal or background
153
154 bool useTMVA_RNN = true;
155 bool useTMVA_DNN = true;
156 bool useTMVA_BDT = false;
157
158 std::vector<std::string> rnn_types = {"RNN", "LSTM", "GRU"};
159 std::vector<bool> use_rnn_type = {1, 1, 1};
160 if (use_type >=0 && use_type < 3) {
161 use_rnn_type = {0,0,0};
162 use_rnn_type[use_type] = 1;
163 }
164 bool useGPU = true; // use GPU for TMVA if available
165
166#ifndef R__HAS_TMVAGPU
167 useGPU = false;
168#ifndef R__HAS_TMVACPU
169 Warning("TMVA_RNN_Classification", "TMVA is not build with GPU or CPU multi-thread support. Cannot use TMVA Deep Learning for RNN");
170 useTMVA_RNN = false;
171#endif
172#endif
173
174
175 TString archString = (useGPU) ? "GPU" : "CPU";
176
177 bool writeOutputFile = true;
178
179
180
181 const char *rnn_type = "RNN";
182
183#ifdef R__USE_IMT
184 int num_threads = 4; // use max 4 threads
185 // switch off MT in OpenBLAS to avoid conflict with tbb
186 gSystem->Setenv("OMP_NUM_THREADS", "1");
187
188 // do enable MT running
189 if (num_threads >= 0) {
190 ROOT::EnableImplicitMT(num_threads);
191 }
192#endif
193
195
196 std::cout << "Running with nthreads = " << ROOT::GetThreadPoolSize() << std::endl;
197
198 TString inputFileName = "time_data_t10_d30.root";
199
200 bool fileExist = !gSystem->AccessPathName(inputFileName);
201
202 // if file does not exists create it
203 if (!fileExist) {
204 MakeTimeData(nTotEvts,ntime, ninput);
205 }
206
207
208 auto inputFile = TFile::Open(inputFileName);
209 if (!inputFile) {
210 Error("TMVA_RNN_Classification", "Error opening input file %s - exit", inputFileName.Data());
211 return;
212 }
213
214
215 std::cout << "--- RNNClassification : Using input file: " << inputFile->GetName() << std::endl;
216
217 // Create a ROOT output file where TMVA will store ntuples, histograms, etc.
218 TString outfileName(TString::Format("data_RNN_%s.root", archString.Data()));
219 TFile *outputFile = nullptr;
220 if (writeOutputFile) outputFile = TFile::Open(outfileName, "RECREATE");
221
222 /**
223 ## Declare Factory
224
225 Create the Factory class. Later you can choose the methods
226 whose performance you'd like to investigate.
227
228 The factory is the major TMVA object you have to interact with. Here is the list of parameters you need to
229pass
230
231 - The first argument is the base of the name of all the output
232 weightfiles in the directory weight/ that will be created with the
233 method parameters
234
235 - The second argument is the output file for the training results
236
237 - The third argument is a string option defining some general configuration for the TMVA session.
238 For example all TMVA output can be suppressed by removing the "!" (not) in front of the "Silent" argument in
239the option string
240
241 **/
242
243 // Creating the factory object
244 TMVA::Factory *factory = new TMVA::Factory("TMVAClassification", outputFile,
245 "!V:!Silent:Color:DrawProgressBar:Transformations=None:!Correlations:"
246 "AnalysisType=Classification:ModelPersistence");
247 TMVA::DataLoader *dataloader = new TMVA::DataLoader("dataset");
248
249 TTree *signalTree = (TTree *)inputFile->Get("sgn");
250 TTree *background = (TTree *)inputFile->Get("bkg");
251
252 const int nvar = ninput * ntime;
253
254 /// add variables - use new AddVariablesArray function
255 for (auto i = 0; i < ntime; i++) {
256 dataloader->AddVariablesArray(Form("vars_time%d", i), ninput);
257 }
258
259 dataloader->AddSignalTree(signalTree, 1.0);
260 dataloader->AddBackgroundTree(background, 1.0);
261
262 // check given input
263 auto &datainfo = dataloader->GetDataSetInfo();
264 auto vars = datainfo.GetListOfVariables();
265 std::cout << "number of variables is " << vars.size() << std::endl;
266 for (auto &v : vars)
267 std::cout << v << ",";
268 std::cout << std::endl;
269
270 int nTrainSig = 0.8 * nTotEvts;
271 int nTrainBkg = 0.8 * nTotEvts;
272
273 // build the string options for DataLoader::PrepareTrainingAndTestTree
274 TString prepareOptions = TString::Format("nTrain_Signal=%d:nTrain_Background=%d:SplitMode=Random:SplitSeed=100:NormMode=NumEvents:!V:!CalcCorrelations", nTrainSig, nTrainBkg);
275
276 // Apply additional cuts on the signal and background samples (can be different)
277 TCut mycuts = ""; // for example: TCut mycuts = "abs(var1)<0.5 && abs(var2-0.5)<1";
278 TCut mycutb = "";
279
280 dataloader->PrepareTrainingAndTestTree(mycuts, mycutb, prepareOptions);
281
282 std::cout << "prepared DATA LOADER " << std::endl;
283
284 /**
285 ## Book TMVA recurrent models
286
287 Book the different types of recurrent models in TMVA (SimpleRNN, LSTM or GRU)
288
289 **/
290
291 if (useTMVA_RNN) {
292
293 for (int i = 0; i < 3; ++i) {
294
295 if (!use_rnn_type[i])
296 continue;
297
298 const char *rnn_type = rnn_types[i].c_str();
299
300 /// define the inputlayout string for RNN
301 /// the input data should be organize as following:
302 //// input layout for RNN: time x ndim
303
304 TString inputLayoutString = TString::Format("InputLayout=%d|%d", ntime, ninput);
305
306 /// Define RNN layer layout
307 /// it should be LayerType (RNN or LSTM or GRU) | number of units | number of inputs | time steps | remember output (typically no=0 | return full sequence
308 TString rnnLayout = TString::Format("%s|10|%d|%d|0|1", rnn_type, ninput, ntime);
309
310 /// add after RNN a reshape layer (needed top flatten the output) and a dense layer with 64 units and a last one
311 /// Note the last layer is linear because when using Crossentropy a Sigmoid is applied already
312 TString layoutString = TString("Layout=") + rnnLayout + TString(",RESHAPE|FLAT,DENSE|64|TANH,LINEAR");
313
314 /// Defining Training strategies. Different training strings can be concatenate. Use however only one
315 TString trainingString1 = TString::Format("LearningRate=1e-3,Momentum=0.0,Repetitions=1,"
316 "ConvergenceSteps=5,BatchSize=%d,TestRepetitions=1,"
317 "WeightDecay=1e-2,Regularization=None,MaxEpochs=%d,"
318 "Optimizer=ADAM,DropConfig=0.0+0.+0.+0.",
319 batchSize,maxepochs);
320
321 TString trainingStrategyString("TrainingStrategy=");
322 trainingStrategyString += trainingString1; // + "|" + trainingString2
323
324 /// Define the full RNN Noption string adding the final options for all network
325 TString rnnOptions("!H:V:ErrorStrategy=CROSSENTROPY:VarTransform=None:"
326 "WeightInitialization=XAVIERUNIFORM:ValidationSize=0.2:RandomSeed=1234");
327
328 rnnOptions.Append(":");
329 rnnOptions.Append(inputLayoutString);
330 rnnOptions.Append(":");
331 rnnOptions.Append(layoutString);
332 rnnOptions.Append(":");
333 rnnOptions.Append(trainingStrategyString);
334 rnnOptions.Append(":");
335 rnnOptions.Append(TString::Format("Architecture=%s", archString.Data()));
336
337 TString rnnName = "TMVA_" + TString(rnn_type);
338 factory->BookMethod(dataloader, TMVA::Types::kDL, rnnName, rnnOptions);
339
340 }
341 }
342
343 /**
344 ## Book TMVA fully connected dense layer models
345
346 **/
347
348 if (useTMVA_DNN) {
349 // Method DL with Dense Layer
350 TString inputLayoutString = TString::Format("InputLayout=1|1|%d", ntime * ninput);
351
352 TString layoutString("Layout=DENSE|64|TANH,DENSE|TANH|64,DENSE|TANH|64,LINEAR");
353 // Training strategies.
354 TString trainingString1("LearningRate=1e-3,Momentum=0.0,Repetitions=1,"
355 "ConvergenceSteps=10,BatchSize=256,TestRepetitions=1,"
356 "WeightDecay=1e-4,Regularization=None,MaxEpochs=20"
357 "DropConfig=0.0+0.+0.+0.,Optimizer=ADAM");
358 TString trainingStrategyString("TrainingStrategy=");
359 trainingStrategyString += trainingString1; // + "|" + trainingString2
360
361 // General Options.
362 TString dnnOptions("!H:V:ErrorStrategy=CROSSENTROPY:VarTransform=None:"
363 "WeightInitialization=XAVIER:RandomSeed=0");
364
365 dnnOptions.Append(":");
366 dnnOptions.Append(inputLayoutString);
367 dnnOptions.Append(":");
368 dnnOptions.Append(layoutString);
369 dnnOptions.Append(":");
370 dnnOptions.Append(trainingStrategyString);
371 dnnOptions.Append(":");
372 dnnOptions.Append(archString);
373
374 TString dnnName = "TMVA_DNN";
375 factory->BookMethod(dataloader, TMVA::Types::kDL, dnnName, dnnOptions);
376 }
377
378 useTMVA_BDT = true;
379
380 /**
381 ## Book TMVA BDT
382 **/
383
384 if (useTMVA_BDT) {
385
386 factory->BookMethod(dataloader, TMVA::Types::kBDT, "BDTG",
387 "!H:!V:NTrees=100:MinNodeSize=2.5%:BoostType=Grad:Shrinkage=0.10:UseBaggedBoost:"
388 "BaggedSampleFraction=0.5:nCuts=20:"
389 "MaxDepth=2");
390
391 }
392
393 /// Train all methods
394 factory->TrainAllMethods();
395
396 std::cout << "nthreads = " << ROOT::GetThreadPoolSize() << std::endl;
397
398 // ---- Evaluate all MVAs using the set of test events
399 factory->TestAllMethods();
400
401 // ----- Evaluate and compare performance of all configured MVAs
402 factory->EvaluateAllMethods();
403
404 // check method
405
406 // plot ROC curve
407 auto c1 = factory->GetROCCurve(dataloader);
408 c1->Draw();
409
410 if (outputFile) outputFile->Close();
411}
#define f(i)
Definition RSha256.hxx:104
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
char * Form(const char *fmt,...)
Formats a string in a circular formatting buffer.
Definition TString.cxx:2571
R__EXTERN TSystem * gSystem
Definition TSystem.h:582
#define gPad
The Canvas class.
Definition TCanvas.h:23
A specialized string object used for TTree selections.
Definition TCut.h:25
1-Dim function class
Definition TF1.h:182
virtual void SetParameters(const Double_t *params)
Definition TF1.h:618
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 Draw(Option_t *chopt="") override
Draw this graph with its current attributes.
Definition TGraph.cxx:859
1-D histogram with a double per channel (see TH1 documentation)
Definition TH1.h:926
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
static Config & Instance()
static function: returns TMVA instance
Definition Config.cxx:97
void AddVariablesArray(const TString &expression, int size, char type='F', Double_t min=0, Double_t max=0)
user inserts discriminating array of variables in data set info in case input tree provides an array ...
void AddSignalTree(TTree *signal, Double_t weight=1.0, Types::ETreeType treetype=Types::kMaxTreeType)
number of signal events (used to compute significance)
void PrepareTrainingAndTestTree(const TCut &cut, const TString &splitOpt)
prepare the training and test trees -> same cuts for signal and background
void AddBackgroundTree(TTree *background, Double_t weight=1.0, Types::ETreeType treetype=Types::kMaxTreeType)
number of signal events (used to compute significance)
DataSetInfo & GetDataSetInfo()
std::vector< TString > GetListOfVariables() const
returns list of variables
This is the main MVA steering class.
Definition Factory.h:80
void TrainAllMethods()
Iterates through all booked methods and calls training.
Definition Factory.cxx:1105
void TestAllMethods()
Evaluates all booked methods on the testing data and adds the output to the Results in the corresponi...
Definition Factory.cxx:1262
void EvaluateAllMethods(void)
Iterates over all MVAs that have been booked, and calls their evaluation methods.
Definition Factory.cxx:1367
MethodBase * BookMethod(DataLoader *loader, MethodName theMethodName, TString methodTitle, TString theOption="")
Books an MVA classifier or regression method.
Definition Factory.cxx:354
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
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
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
RVec< PromoteType< T > > cos(const RVec< T > &v)
Definition RVec.hxx:1832
RVec< PromoteType< T > > sin(const RVec< T > &v)
Definition RVec.hxx:1831
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
constexpr Double_t Pi()
Definition TMath.h:40