Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
MethodTMlpANN.cxx
Go to the documentation of this file.
1// @(#)root/tmva $Id$
2// Author: Andreas Hoecker, Joerg Stelzer, Helge Voss, Kai Voss, Eckhard von Toerne
3/**********************************************************************************
4 * Project: TMVA - a Root-integrated toolkit for multivariate data analysis *
5 * Package: TMVA *
6 * Class : MethodTMlpANN *
7 * *
8 * *
9 * Description: *
10 * Implementation (see header for description) *
11 * *
12 * Authors (alphabetical): *
13 * Andreas Hoecker <Andreas.Hocker@cern.ch> - CERN, Switzerland *
14 * Helge Voss <Helge.Voss@cern.ch> - MPI-K Heidelberg, Germany *
15 * Kai Voss <Kai.Voss@cern.ch> - U. of Victoria, Canada *
16 * *
17 * Copyright (c) 2005: *
18 * CERN, Switzerland *
19 * U. of Victoria, Canada *
20 * MPI-K Heidelberg, Germany *
21 * *
22 * Redistribution and use in source and binary forms, with or without *
23 * modification, are permitted according to the terms listed in LICENSE *
24 * (see tmva/doc/LICENSE) *
25 **********************************************************************************/
26
27/*! \class TMVA::MethodTMlpANN
28\ingroup TMVA
29
30This is the TMVA TMultiLayerPerceptron interface class. It provides the
31training and testing the ROOT internal MLP class in the TMVA framework.
32
33Available learning methods:<br>
34
35 - Stochastic
36 - Batch
37 - SteepestDescent
38 - RibierePolak
39 - FletcherReeves
40 - BFGS
41
42See the TMultiLayerPerceptron class description
43for details on this ANN.
44*/
45
46#include "TMVA/MethodTMlpANN.h"
47
48#include "TMVA/Config.h"
49#include "TMVA/DataSet.h"
50#include "TMVA/DataSetInfo.h"
51#include "TMVA/IMethod.h"
52#include "TMVA/MethodBase.h"
53#include "TMVA/MsgLogger.h"
54#include "TMVA/Types.h"
55#include "TMVA/VariableInfo.h"
56
58#include "TMVA/Tools.h"
59
60#include "TROOT.h"
62#include "ThreadLocalStorage.h"
63
64#include <cstdlib>
65#include <iostream>
66#include <fstream>
67
68
69using std::atoi;
70
71// some additional TMlpANN options
73
75
76
77////////////////////////////////////////////////////////////////////////////////
78/// standard constructor
79
81 const TString& methodTitle,
84 TMVA::MethodBase( jobName, Types::kTMlpANN, methodTitle, theData, theOption),
85 fMLP(0),
86 fLocalTrainingTree(0),
87 fNcycles(100),
88 fValidationFraction(0.5),
89 fLearningMethod( "" )
90{
91}
92
93////////////////////////////////////////////////////////////////////////////////
94/// constructor from weight file
95
97 const TString& theWeightFile) :
99 fMLP(0),
100 fLocalTrainingTree(0),
101 fNcycles(100),
102 fValidationFraction(0.5),
103 fLearningMethod( "" )
104{
105}
106
107////////////////////////////////////////////////////////////////////////////////
108/// TMlpANN can handle classification with 2 classes
109
116
117
118////////////////////////////////////////////////////////////////////////////////
119/// default initialisations
120
122{
123}
124
125////////////////////////////////////////////////////////////////////////////////
126/// destructor
127
129{
130 if (fMLP) delete fMLP;
131}
132
133////////////////////////////////////////////////////////////////////////////////
134/// translates options from option string into TMlpANN language
135
137{
138 fHiddenLayer = ":";
139
140 while (layerSpec.Length()>0) {
141 TString sToAdd="";
142 if (layerSpec.First(',')<0) {
144 layerSpec = "";
145 }
146 else {
147 sToAdd = layerSpec(0,layerSpec.First(','));
148 layerSpec = layerSpec(layerSpec.First(',')+1,layerSpec.Length());
149 }
150 int nNodes = 0;
151 if (sToAdd.BeginsWith("N")) { sToAdd.Remove(0,1); nNodes = GetNvar(); }
152 nNodes += atoi(sToAdd);
153 fHiddenLayer = TString::Format( "%s%i:", (const char*)fHiddenLayer, nNodes );
154 }
155
156 // set input vars
157 std::vector<TString>::iterator itrVar = (*fInputVars).begin();
158 std::vector<TString>::iterator itrVarEnd = (*fInputVars).end();
159 fMLPBuildOptions = "";
160 for (; itrVar != itrVarEnd; ++itrVar) {
161 if (EnforceNormalization__) fMLPBuildOptions += "@";
162 TString myVar = *itrVar; ;
163 fMLPBuildOptions += myVar;
164 fMLPBuildOptions += ",";
165 }
166 fMLPBuildOptions.Chop(); // remove last ","
167
168 // prepare final options for MLP kernel
169 fMLPBuildOptions += fHiddenLayer;
170 fMLPBuildOptions += "type";
171
172 Log() << kINFO << "Use " << fNcycles << " training cycles" << Endl;
173 Log() << kINFO << "Use configuration (nodes per hidden layer): " << fHiddenLayer << Endl;
174}
175
176////////////////////////////////////////////////////////////////////////////////
177/// define the options (their key words) that can be set in the option string
178///
179/// know options:
180///
181/// - NCycles `<integer>` Number of training cycles (too many cycles could overtrain the network)
182/// - HiddenLayers `<string>` Layout of the hidden layers (nodes per layer)
183/// * specifications for each hidden layer are separated by comma
184/// * for each layer the number of nodes can be either absolut (simply a number)
185/// or relative to the number of input nodes to the neural net (N)
186/// * there is always a single node in the output layer
187///
188/// example: a net with 6 input nodes and "Hiddenlayers=N-1,N-2" has 6,5,4,1 nodes in the
189/// layers 1,2,3,4, respectively
190
192{
193 DeclareOptionRef( fNcycles = 200, "NCycles", "Number of training cycles" );
194 DeclareOptionRef( fLayerSpec = "N,N-1", "HiddenLayers", "Specification of hidden layer architecture (N stands for number of variables; any integers may also be used)" );
195
196 DeclareOptionRef( fValidationFraction = 0.5, "ValidationFraction",
197 "Fraction of events in training tree used for cross validation" );
198
199 DeclareOptionRef( fLearningMethod = "Stochastic", "LearningMethod", "Learning method" );
200 AddPreDefVal( TString("Stochastic") );
201 AddPreDefVal( TString("Batch") );
202 AddPreDefVal( TString("SteepestDescent") );
203 AddPreDefVal( TString("RibierePolak") );
204 AddPreDefVal( TString("FletcherReeves") );
205 AddPreDefVal( TString("BFGS") );
206}
207
208////////////////////////////////////////////////////////////////////////////////
209/// builds the neural network as specified by the user
210
212{
213 CreateMLPOptions(fLayerSpec);
214
215 if (IgnoreEventsWithNegWeightsInTraining()) {
216 Log() << kFATAL << "Mechanism to ignore events with negative weights in training not available for method"
217 << GetMethodTypeName()
218 << " --> please remove \"IgnoreNegWeightsInTraining\" option from booking string."
219 << Endl;
220 }
221}
222
223////////////////////////////////////////////////////////////////////////////////
224/// calculate the value of the neural net for the current event
225
227{
228 const Event* ev = GetEvent();
229 TTHREAD_TLS_DECL_ARG(Double_t*, d, new Double_t[Data()->GetNVariables()]);
230
231 for (UInt_t ivar = 0; ivar<Data()->GetNVariables(); ivar++) {
232 d[ivar] = (Double_t)ev->GetValue(ivar);
233 }
234 Double_t mvaVal = fMLP->Evaluate(0,d);
235
236 // cannot determine error
237 NoErrorCalc(err, errUpper);
238
239 return mvaVal;
240}
241
242////////////////////////////////////////////////////////////////////////////////
243/// performs TMlpANN training
244/// available learning methods:
245///
246/// - TMultiLayerPerceptron::kStochastic
247/// - TMultiLayerPerceptron::kBatch
248/// - TMultiLayerPerceptron::kSteepestDescent
249/// - TMultiLayerPerceptron::kRibierePolak
250/// - TMultiLayerPerceptron::kFletcherReeves
251/// - TMultiLayerPerceptron::kBFGS
252///
253/// TMultiLayerPerceptron wants test and training tree at once
254/// so merge the training and testing trees from the MVA factory first:
255
257{
258 Int_t type;
259 Float_t weight;
260 const Long_t basketsize = 128000;
261 Float_t* vArr = new Float_t[GetNvar()];
262
263 TTree *localTrainingTree = new TTree( "TMLPtrain", "Local training tree for TMlpANN" );
264 localTrainingTree->Branch( "type", &type, "type/I", basketsize );
265 localTrainingTree->Branch( "weight", &weight, "weight/F", basketsize );
266
267 for (UInt_t ivar=0; ivar<GetNvar(); ivar++) {
268 TString myVar = GetInternalVarName(ivar);
269 TString myTyp = TString::Format("Var%02i/F", ivar);
270 localTrainingTree->Branch( myVar.Data(), &vArr[ivar], myTyp.Data(), basketsize );
271 }
272
273 for (UInt_t ievt=0; ievt<Data()->GetNEvents(); ievt++) {
274 const Event *ev = GetEvent(ievt);
275 for (UInt_t i=0; i<GetNvar(); i++) {
276 vArr[i] = ev->GetValue( i );
277 }
278 type = DataInfo().IsSignal( ev ) ? 1 : 0;
279 weight = ev->GetWeight();
280 localTrainingTree->Fill();
281 }
282
283 // These are the event lists for the mlp train method
284 // first events in the tree are for training
285 // the rest for internal testing (cross validation)...
286 // NOTE: the training events are ordered: first part is signal, second part background
287 TString trainList = "Entry$<";
288 trainList += 1.0-fValidationFraction;
289 trainList += "*";
290 trainList += (Int_t)Data()->GetNEvtSigTrain();
291 trainList += " || (Entry$>";
292 trainList += (Int_t)Data()->GetNEvtSigTrain();
293 trainList += " && Entry$<";
294 trainList += (Int_t)(Data()->GetNEvtSigTrain() + (1.0 - fValidationFraction)*Data()->GetNEvtBkgdTrain());
295 trainList += ")";
296 TString testList = TString("!(") + trainList + ")";
297
298 // print the requirements
299 Log() << kHEADER << "Requirement for training events: \"" << trainList << "\"" << Endl;
300 Log() << kINFO << "Requirement for validation events: \"" << testList << "\"" << Endl;
301
302 // localTrainingTree->Print();
303
304 // create NN
305 if (fMLP) { delete fMLP; fMLP = nullptr; }
306 fMLP = new TMultiLayerPerceptron( fMLPBuildOptions.Data(),
308 trainList,
309 testList );
310 fMLP->SetEventWeight( "weight" );
311
312 // set learning method
314
315 fLearningMethod.ToLower();
316 if (fLearningMethod == "stochastic" ) learningMethod = TMultiLayerPerceptron::kStochastic;
317 else if (fLearningMethod == "batch" ) learningMethod = TMultiLayerPerceptron::kBatch;
318 else if (fLearningMethod == "steepestdescent" ) learningMethod = TMultiLayerPerceptron::kSteepestDescent;
319 else if (fLearningMethod == "ribierepolak" ) learningMethod = TMultiLayerPerceptron::kRibierePolak;
320 else if (fLearningMethod == "fletcherreeves" ) learningMethod = TMultiLayerPerceptron::kFletcherReeves;
321 else if (fLearningMethod == "bfgs" ) learningMethod = TMultiLayerPerceptron::kBFGS;
322 else {
323 Log() << kFATAL << "Unknown Learning Method: \"" << fLearningMethod << "\"" << Endl;
324 }
325 fMLP->SetLearningMethod( learningMethod );
326
327 // train NN
328 fMLP->Train(fNcycles, "" ); //"text,update=50" );
329
330 // write weights to File;
331 // this is not nice, but fMLP gets deleted at the end of Train()
332 delete localTrainingTree;
333 delete [] vArr;
334}
335
336////////////////////////////////////////////////////////////////////////////////
337/// write weights to xml file
338
339void TMVA::MethodTMlpANN::AddWeightsXMLTo( void* parent ) const
340{
341 // first the architecture
342 void *wght = gTools().AddChild(parent, "Weights");
343 void* arch = gTools().AddChild( wght, "Architecture" );
344 gTools().AddAttr( arch, "BuildOptions", fMLPBuildOptions.Data() );
345
346 // dump weights first in temporary txt file, read from there into xml
347 const TString tmpfile=GetWeightFileDir()+"/TMlp.nn.weights.temp";
348 fMLP->DumpWeights( tmpfile.Data() );
349 std::ifstream inf( tmpfile.Data() );
350 char temp[256];
351 TString data("");
352 void *ch = nullptr;
353 while (inf.getline(temp,256)) {
354 TString dummy(temp);
355 //std::cout << dummy << std::endl; // remove annoying debug printout with std::cout
356 if (dummy.BeginsWith('#')) {
357 if (ch) gTools().AddRawLine( ch, data.Data() );
358 dummy = dummy.Strip(TString::kLeading, '#');
359 dummy = dummy(0,dummy.First(' '));
360 ch = gTools().AddChild(wght, dummy);
361 data.Resize(0);
362 continue;
363 }
364 data += (dummy + " ");
365 }
366 if (ch) gTools().AddRawLine( ch, data.Data() );
367
368 inf.close();
369}
370
371////////////////////////////////////////////////////////////////////////////////
372/// rebuild temporary textfile from xml weightfile and load this
373/// file into MLP
374
376{
377 void* ch = gTools().GetChild(wghtnode);
378 gTools().ReadAttr( ch, "BuildOptions", fMLPBuildOptions );
379
380 ch = gTools().GetNextChild(ch);
381 const TString fname = GetWeightFileDir()+"/TMlp.nn.weights.temp";
382 std::ofstream fout( fname.Data() );
383 double temp1=0,temp2=0;
384 while (ch) {
385 const char* nodecontent = gTools().GetContent(ch);
386 std::stringstream content(nodecontent);
387 if (strcmp(gTools().GetName(ch),"input")==0) {
388 fout << "#input normalization" << std::endl;
389 while ((content >> temp1) &&(content >> temp2)) {
390 fout << temp1 << " " << temp2 << std::endl;
391 }
392 }
393 if (strcmp(gTools().GetName(ch),"output")==0) {
394 fout << "#output normalization" << std::endl;
395 while ((content >> temp1) &&(content >> temp2)) {
396 fout << temp1 << " " << temp2 << std::endl;
397 }
398 }
399 if (strcmp(gTools().GetName(ch),"neurons")==0) {
400 fout << "#neurons weights" << std::endl;
401 while (content >> temp1) {
402 fout << temp1 << std::endl;
403 }
404 }
405 if (strcmp(gTools().GetName(ch),"synapses")==0) {
406 fout << "#synapses weights" ;
407 while (content >> temp1) {
408 fout << std::endl << temp1 ;
409 }
410 }
411 ch = gTools().GetNextChild(ch);
412 }
413 fout.close();
414
415 // Here we create a dummy tree necessary to create a minimal NN
416 // to be used for testing, evaluation and application
417 TTHREAD_TLS_DECL_ARG(Double_t*, d, new Double_t[Data()->GetNVariables()]);
419
420 gROOT->cd();
421 TTree * dummyTree = new TTree("dummy","Empty dummy tree", 1);
422 for (UInt_t ivar = 0; ivar<Data()->GetNVariables(); ivar++) {
423 TString vn = DataInfo().GetVariableInfo(ivar).GetInternalName();
424 TString vt = TString::Format("%s/D", vn.Data());
425 dummyTree->Branch(vn.Data(), d+ivar, vt.Data());
426 }
427 dummyTree->Branch("type", &type, "type/I");
428
429 if (fMLP) { delete fMLP; fMLP = nullptr; }
430 fMLP = new TMultiLayerPerceptron( fMLPBuildOptions.Data(), dummyTree );
431 fMLP->LoadWeights( fname );
432}
433
434////////////////////////////////////////////////////////////////////////////////
435/// read weights from stream
436/// since the MLP can not read from the stream, we
437/// 1st: write the weights to temporary file
438
440{
441 std::ofstream fout( "./TMlp.nn.weights.temp" );
442 fout << istr.rdbuf();
443 fout.close();
444 // 2nd: load the weights from the temporary file into the MLP
445 // the MLP is already build
446 Log() << kINFO << "Load TMLP weights into " << fMLP << Endl;
447
448 Double_t *d = new Double_t[Data()->GetNVariables()] ;
449 Int_t type;
450 gROOT->cd();
451 TTree * dummyTree = new TTree("dummy","Empty dummy tree", 1);
452 for (UInt_t ivar = 0; ivar<Data()->GetNVariables(); ivar++) {
453 TString vn = DataInfo().GetVariableInfo(ivar).GetLabel();
454 TString vt = TString::Format("%s/D", vn.Data());
455 dummyTree->Branch(vn.Data(), d+ivar, vt.Data());
456 }
457 dummyTree->Branch("type", &type, "type/I");
458
459 if (fMLP) { delete fMLP; fMLP = nullptr; }
460 fMLP = new TMultiLayerPerceptron( fMLPBuildOptions.Data(), dummyTree );
461
462 fMLP->LoadWeights( "./TMlp.nn.weights.temp" );
463 // here we can delete the temporary file
464 // how?
465 delete [] d;
466}
467
468////////////////////////////////////////////////////////////////////////////////
469/// create reader class for classifier -> overwrites base class function
470/// create specific class for TMultiLayerPerceptron
471
473{
474 // the default consists of
476 if (theClassFileName == "")
477 classFileName = GetWeightFileDir() + "/" + GetJobName() + "_" + GetMethodName() + ".class";
478 else
480
481 classFileName.ReplaceAll(".class","");
482 Log() << kINFO << "Creating specific (TMultiLayerPerceptron) standalone response class: " << classFileName << Endl;
483 fMLP->Export( classFileName.Data() );
484}
485
486////////////////////////////////////////////////////////////////////////////////
487/// write specific classifier response
488/// nothing to do here - all taken care of by TMultiLayerPerceptron
489
490void TMVA::MethodTMlpANN::MakeClassSpecific( std::ostream& /*fout*/, const TString& /*className*/ ) const
491{
492}
493
494////////////////////////////////////////////////////////////////////////////////
495/// get help message text
496///
497/// typical length of text line:
498/// "|--------------------------------------------------------------|"
499
501{
502 Log() << Endl;
503 Log() << gTools().Color("bold") << "--- Short description:" << gTools().Color("reset") << Endl;
504 Log() << Endl;
505 Log() << "This feed-forward multilayer perceptron neural network is the " << Endl;
506 Log() << "standard implementation distributed with ROOT (class TMultiLayerPerceptron)." << Endl;
507 Log() << Endl;
508 Log() << "Detailed information is available here:" << Endl;
509 if (gConfig().WriteOptionsReference()) {
510 Log() << "<a href=\"https://root.cern/doc/master/classTMultiLayerPerceptron.html\">";
511 Log() << "https://root.cern/doc/master/classTMultiLayerPerceptron.html</a>" << Endl;
512 }
513 else Log() << "https://root.cern/doc/master/classTMultiLayerPerceptron.html" << Endl;
514 Log() << Endl;
515}
#define REGISTER_METHOD(CLASS)
for example
const Bool_t EnforceNormalization__
#define d(i)
Definition RSha256.hxx:102
bool Bool_t
Boolean (0=false, 1=true) (bool)
Definition RtypesCore.h:78
int Int_t
Signed integer 4 bytes (int)
Definition RtypesCore.h:60
long Long_t
Signed long integer 4 bytes (long). Size depends on architecture.
Definition RtypesCore.h:69
float Float_t
Float 4 bytes (float)
Definition RtypesCore.h:72
constexpr Bool_t kFALSE
Definition RtypesCore.h:109
double Double_t
Double 8 bytes.
Definition RtypesCore.h:74
constexpr Bool_t kTRUE
Definition RtypesCore.h:108
ROOT::Detail::TRangeCast< T, true > TRangeDynCast
TRangeDynCast is an adapter class that allows the typed iteration through a TCollection.
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void data
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
#define gROOT
Definition TROOT.h:417
const_iterator begin() const
const_iterator end() const
Class that contains all the data information.
Definition DataSetInfo.h:62
Virtual base Class for all MVA method.
Definition MethodBase.h:82
This is the TMVA TMultiLayerPerceptron interface class.
void ReadWeightsFromStream(std::istream &istr) override
read weights from stream since the MLP can not read from the stream, we 1st: write the weights to tem...
void MakeClass(const TString &classFileName=TString("")) const override
create reader class for classifier -> overwrites base class function create specific class for TMulti...
void Train(void) override
performs TMlpANN training available learning methods:
void ReadWeightsFromXML(void *wghtnode) override
rebuild temporary textfile from xml weightfile and load this file into MLP
void AddWeightsXMLTo(void *parent) const override
write weights to xml file
void DeclareOptions() override
define the options (their key words) that can be set in the option string
void CreateMLPOptions(TString)
translates options from option string into TMlpANN language
void ProcessOptions() override
builds the neural network as specified by the user
MethodTMlpANN(const TString &jobName, const TString &methodTitle, DataSetInfo &theData, const TString &theOption="3000:N-1:N-2")
standard constructor
Double_t GetMvaValue(Double_t *err=nullptr, Double_t *errUpper=nullptr) override
calculate the value of the neural net for the current event
void Init(void) override
default initialisations
virtual ~MethodTMlpANN(void)
destructor
Bool_t HasAnalysisType(Types::EAnalysisType type, UInt_t numberClasses, UInt_t numberTargets) override
TMlpANN can handle classification with 2 classes.
void GetHelpMessage() const override
get help message text
void MakeClassSpecific(std::ostream &, const TString &) const override
write specific classifier response nothing to do here - all taken care of by TMultiLayerPerceptron
Bool_t AddRawLine(void *node, const char *raw)
XML helpers.
Definition Tools.cxx:1165
const TString & Color(const TString &)
human readable color strings
Definition Tools.cxx:803
const char * GetContent(void *node)
XML helpers.
Definition Tools.cxx:1149
void ReadAttr(void *node, const char *, T &value)
read attribute from xml
Definition Tools.h:329
void * GetChild(void *parent, const char *childname=nullptr)
get child node
Definition Tools.cxx:1125
void AddAttr(void *node, const char *, const T &value, Int_t precision=16)
add attribute to xml
Definition Tools.h:347
void * AddChild(void *parent, const char *childname, const char *content=nullptr, bool isRootNode=false)
add child node
Definition Tools.cxx:1099
void * GetNextChild(void *prevchild, const char *childname=nullptr)
XML helpers.
Definition Tools.cxx:1137
Singleton class for Global types used by TMVA.
Definition Types.h:71
@ kClassification
Definition Types.h:127
This class describes a neural network.
Basic string class.
Definition TString.h:138
TSubString Strip(EStripType s=kTrailing, char c=' ') const
Return a substring of self stripped at beginning and/or end.
Definition TString.cxx:1170
Ssiz_t First(char c) const
Find first occurrence of a character c.
Definition TString.cxx:545
@ kLeading
Definition TString.h:284
Bool_t BeginsWith(const char *s, ECaseCompare cmp=kExact) const
Definition TString.h:634
static TString Format(const char *fmt,...)
Static method which formats a string using a printf style format descriptor and return a TString.
Definition TString.cxx:2459
A TTree represents a columnar dataset.
Definition TTree.h:89
create variable transformations
Config & gConfig()
Tools & gTools()
MsgLogger & Endl(MsgLogger &ml)
Definition MsgLogger.h:148