Logo ROOT   6.08/07
Reference Guide
MethodCFMlpANN.cxx
Go to the documentation of this file.
1 // @(#)root/tmva $Id$
2 // Author: Andreas Hoecker, Joerg Stelzer, Helge Voss, Kai Voss
3 
4 /**********************************************************************************
5  * Project: TMVA - a Root-integrated toolkit for multivariate Data analysis *
6  * Package: TMVA *
7  * Class : TMVA::MethodCFMlpANN *
8  * Web : http://tmva.sourceforge.net *
9  * *
10  * Description: *
11  * Implementation (see header for description) *
12  * *
13  * Authors (alphabetical): *
14  * Andreas Hoecker <Andreas.Hocker@cern.ch> - CERN, Switzerland *
15  * Xavier Prudent <prudent@lapp.in2p3.fr> - LAPP, France *
16  * Helge Voss <Helge.Voss@cern.ch> - MPI-K Heidelberg, Germany *
17  * Kai Voss <Kai.Voss@cern.ch> - U. of Victoria, Canada *
18  * *
19  * Copyright (c) 2005: *
20  * CERN, Switzerland *
21  * U. of Victoria, Canada *
22  * MPI-K Heidelberg, Germany *
23  * LAPP, Annecy, France *
24  * *
25  * Redistribution and use in source and binary forms, with or without *
26  * modification, are permitted according to the terms listed in LICENSE *
27  * (http://tmva.sourceforge.net/LICENSE) *
28  **********************************************************************************/
29 
30 //_______________________________________________________________________
31 //
32 // Begin_Html
33 /*
34  Interface to Clermond-Ferrand artificial neural network
35 
36  <p>
37  The CFMlpANN belong to the class of Multilayer Perceptrons (MLP), which are
38  feed-forward networks according to the following propagation schema:<br>
39  <center>
40  <img vspace=10 src="gif/tmva_mlp.gif" align="bottom" alt="Schema for artificial neural network">
41  </center>
42  The input layer contains as many neurons as input variables used in the MVA.
43  The output layer contains two neurons for the signal and background
44  event classes. In between the input and output layers are a variable number
45  of <i>k</i> hidden layers with arbitrary numbers of neurons. (While the
46  structure of the input and output layers is determined by the problem, the
47  hidden layers can be configured by the user through the option string
48  of the method booking.) <br>
49 
50  As indicated in the sketch, all neuron inputs to a layer are linear
51  combinations of the neuron output of the previous layer. The transfer
52  from input to output within a neuron is performed by means of an "activation
53  function". In general, the activation function of a neuron can be
54  zero (deactivated), one (linear), or non-linear. The above example uses
55  a sigmoid activation function. The transfer function of the output layer
56  is usually linear. As a consequence: an ANN without hidden layer should
57  give identical discrimination power as a linear discriminant analysis (Fisher).
58  In case of one hidden layer, the ANN computes a linear combination of
59  sigmoid. <br>
60 
61  The learning method used by the CFMlpANN is only stochastic.
62 */
63 // End_Html
64 //_______________________________________________________________________
65 
66 #include "TMVA/MethodCFMlpANN.h"
67 
68 #include "TMVA/ClassifierFactory.h"
69 #include "TMVA/Configurable.h"
70 #include "TMVA/DataSet.h"
71 #include "TMVA/DataSetInfo.h"
72 #include "TMVA/IMethod.h"
73 #include "TMVA/MethodBase.h"
75 #include "TMVA/MsgLogger.h"
76 #include "TMVA/Tools.h"
77 #include "TMVA/Types.h"
78 
79 #include "TMatrix.h"
80 #include "TObjString.h"
81 #include "Riostream.h"
82 #include "TMath.h"
83 
84 #include <cstdlib>
85 #include <iostream>
86 #include <string>
87 
88 
89 
90 REGISTER_METHOD(CFMlpANN)
91 
92 using std::stringstream;
93 using std::make_pair;
94 using std::atoi;
95 
97 
98 
99 
100 ////////////////////////////////////////////////////////////////////////////////
101 /// standard constructor
102 /// option string: "n_training_cycles:n_hidden_layers"
103 /// default is: n_training_cycles = 5000, n_layers = 4
104 ///
105 /// * note that the number of hidden layers in the NN is:
106 /// n_hidden_layers = n_layers - 2
107 ///
108 /// * since there is one input and one output layer. The number of
109 /// nodes (neurons) is predefined to be:
110 /// n_nodes[i] = nvars + 1 - i (where i=1..n_layers)
111 ///
112 /// with nvars being the number of variables used in the NN.
113 ///
114 /// Hence, the default case is: n_neurons(layer 1 (input)) : nvars
115 /// n_neurons(layer 2 (hidden)): nvars-1
116 /// n_neurons(layer 3 (hidden)): nvars-1
117 /// n_neurons(layer 4 (out)) : 2
118 ///
119 /// This artificial neural network usually needs a relatively large
120 /// number of cycles to converge (8000 and more). Overtraining can
121 /// be efficienctly tested by comparing the signal and background
122 /// output of the NN for the events that were used for training and
123 /// an independent data sample (with equal properties). If the separation
124 /// performance is significantly better for the training sample, the
125 /// NN interprets statistical effects, and is hence overtrained. In
126 /// this case, the number of cycles should be reduced, or the size
127 /// of the training sample increased.
128 
130  const TString& methodTitle,
131  DataSetInfo& theData,
132  const TString& theOption ) :
133  TMVA::MethodBase( jobName, Types::kCFMlpANN, methodTitle, theData, theOption),
134  fData(0),
135  fClass(0),
136  fNlayers(0),
137  fNcycles(0),
138  fNodes(0),
139  fYNN(0),
140  MethodCFMlpANN_nsel(0)
141 {
142  MethodCFMlpANN_Utils::SetLogger(&Log());
143 }
144 
145 ////////////////////////////////////////////////////////////////////////////////
146 /// constructor from weight file
147 
149  const TString& theWeightFile):
150  TMVA::MethodBase( Types::kCFMlpANN, theData, theWeightFile),
151  fData(0),
152  fClass(0),
153  fNlayers(0),
154  fNcycles(0),
155  fNodes(0),
156  fYNN(0),
157  MethodCFMlpANN_nsel(0)
158 {
159 }
160 
161 ////////////////////////////////////////////////////////////////////////////////
162 /// CFMlpANN can handle classification with 2 classes
163 
165 {
166  if (type == Types::kClassification && numberClasses == 2) return kTRUE;
167  return kFALSE;
168 }
169 
170 ////////////////////////////////////////////////////////////////////////////////
171 /// define the options (their key words) that can be set in the option string
172 /// know options: NCycles=xx :the number of training cycles
173 /// HiddenLayser="N-1,N-2" :the specification of the hidden layers
174 
176 {
177  DeclareOptionRef( fNcycles =3000, "NCycles", "Number of training cycles" );
178  DeclareOptionRef( fLayerSpec="N,N-1", "HiddenLayers", "Specification of hidden layer architecture" );
179 }
180 
181 ////////////////////////////////////////////////////////////////////////////////
182 /// decode the options in the option string
183 
185 {
186  fNodes = new Int_t[20]; // number of nodes per layer (maximum 20 layers)
187  fNlayers = 2;
188  Int_t currentHiddenLayer = 1;
189  TString layerSpec(fLayerSpec);
190  while(layerSpec.Length()>0) {
191  TString sToAdd = "";
192  if (layerSpec.First(',')<0) {
193  sToAdd = layerSpec;
194  layerSpec = "";
195  }
196  else {
197  sToAdd = layerSpec(0,layerSpec.First(','));
198  layerSpec = layerSpec(layerSpec.First(',')+1,layerSpec.Length());
199  }
200  Int_t nNodes = 0;
201  if (sToAdd.BeginsWith("N") || sToAdd.BeginsWith("n")) { sToAdd.Remove(0,1); nNodes = GetNvar(); }
202  nNodes += atoi(sToAdd);
203  fNodes[currentHiddenLayer++] = nNodes;
204  fNlayers++;
205  }
206  fNodes[0] = GetNvar(); // number of input nodes
207  fNodes[fNlayers-1] = 2; // number of output nodes
208 
210  Log() << kFATAL << "Mechanism to ignore events with negative weights in training not yet available for method: "
211  << GetMethodTypeName()
212  << " --> please remove \"IgnoreNegWeightsInTraining\" option from booking string."
213  << Endl;
214  }
215 
216  Log() << kINFO << "Use configuration (nodes per layer): in=";
217  for (Int_t i=0; i<fNlayers-1; i++) Log() << kINFO << fNodes[i] << ":";
218  Log() << kINFO << fNodes[fNlayers-1] << "=out" << Endl;
219 
220  // some info
221  Log() << "Use " << fNcycles << " training cycles" << Endl;
222 
223  Int_t nEvtTrain = Data()->GetNTrainingEvents();
224 
225  // note that one variable is type
226  if (nEvtTrain>0) {
227 
228  // Data LUT
229  fData = new TMatrix( nEvtTrain, GetNvar() );
230  fClass = new std::vector<Int_t>( nEvtTrain );
231 
232  // ---- fill LUTs
233 
234  UInt_t ivar;
235  for (Int_t ievt=0; ievt<nEvtTrain; ievt++) {
236  const Event * ev = GetEvent(ievt);
237 
238  // identify signal and background events
239  (*fClass)[ievt] = DataInfo().IsSignal(ev) ? 1 : 2;
240 
241  // use normalized input Data
242  for (ivar=0; ivar<GetNvar(); ivar++) {
243  (*fData)( ievt, ivar ) = ev->GetValue(ivar);
244  }
245  }
246 
247  //Log() << kVERBOSE << Data()->GetNEvtSigTrain() << " Signal and "
248  // << Data()->GetNEvtBkgdTrain() << " background" << " events in trainingTree" << Endl;
249  }
250 
251 }
252 
253 ////////////////////////////////////////////////////////////////////////////////
254 /// default initialisation called by all constructors
255 
257 {
258  // CFMlpANN prefers normalised input variables
259  SetNormalised( kTRUE );
260 
261  // initialize dimensions
262  MethodCFMlpANN_nsel = 0;
263 }
264 
265 ////////////////////////////////////////////////////////////////////////////////
266 /// destructor
267 
269 {
270  delete fData;
271  delete fClass;
272  delete[] fNodes;
273 
274  if (fYNN!=0) {
275  for (Int_t i=0; i<fNlayers; i++) delete[] fYNN[i];
276  delete[] fYNN;
277  fYNN=0;
278  }
279 }
280 
281 ////////////////////////////////////////////////////////////////////////////////
282 /// training of the Clement-Ferrand NN classifier
283 
285 {
286  Double_t dumDat(0);
287  Int_t ntrain(Data()->GetNTrainingEvents());
288  Int_t ntest(0);
289  Int_t nvar(GetNvar());
290  Int_t nlayers(fNlayers);
291  Int_t *nodes = new Int_t[nlayers];
292  Int_t ncycles(fNcycles);
293 
294  for (Int_t i=0; i<nlayers; i++) nodes[i] = fNodes[i]; // full copy of class member
295 
296  if (fYNN != 0) {
297  for (Int_t i=0; i<fNlayers; i++) delete[] fYNN[i];
298  delete[] fYNN;
299  fYNN = 0;
300  }
301  fYNN = new Double_t*[nlayers];
302  for (Int_t layer=0; layer<nlayers; layer++)
303  fYNN[layer] = new Double_t[fNodes[layer]];
304 
305  // please check
306 #ifndef R__WIN32
307  Train_nn( &dumDat, &dumDat, &ntrain, &ntest, &nvar, &nlayers, nodes, &ncycles );
308 #else
309  Log() << kWARNING << "<Train> sorry CFMlpANN does not run on Windows" << Endl;
310 #endif
311 
312  delete [] nodes;
313 
315 }
316 
317 ////////////////////////////////////////////////////////////////////////////////
318 /// returns CFMlpANN output (normalised within [0,1])
319 
321 {
322  Bool_t isOK = kTRUE;
323 
324  const Event* ev = GetEvent();
325 
326  // copy of input variables
327  std::vector<Double_t> inputVec( GetNvar() );
328  for (UInt_t ivar=0; ivar<GetNvar(); ivar++) inputVec[ivar] = ev->GetValue(ivar);
329 
330  Double_t myMVA = EvalANN( inputVec, isOK );
331  if (!isOK) Log() << kFATAL << "EvalANN returns (!isOK) for event " << Endl;
332 
333  // cannot determine error
334  NoErrorCalc(err, errUpper);
335 
336  return myMVA;
337 }
338 
339 ////////////////////////////////////////////////////////////////////////////////
340 /// evaluates NN value as function of input variables
341 
342 Double_t TMVA::MethodCFMlpANN::EvalANN( std::vector<Double_t>& inVar, Bool_t& isOK )
343 {
344  // hardcopy of input variables (necessary because they are update later)
345  Double_t* xeev = new Double_t[GetNvar()];
346  for (UInt_t ivar=0; ivar<GetNvar(); ivar++) xeev[ivar] = inVar[ivar];
347 
348  // ---- now apply the weights: get NN output
349  isOK = kTRUE;
350  for (UInt_t jvar=0; jvar<GetNvar(); jvar++) {
351 
352  if (fVarn_1.xmax[jvar] < xeev[jvar]) xeev[jvar] = fVarn_1.xmax[jvar];
353  if (fVarn_1.xmin[jvar] > xeev[jvar]) xeev[jvar] = fVarn_1.xmin[jvar];
354  if (fVarn_1.xmax[jvar] == fVarn_1.xmin[jvar]) {
355  isOK = kFALSE;
356  xeev[jvar] = 0;
357  }
358  else {
359  xeev[jvar] = xeev[jvar] - ((fVarn_1.xmax[jvar] + fVarn_1.xmin[jvar])/2);
360  xeev[jvar] = xeev[jvar] / ((fVarn_1.xmax[jvar] - fVarn_1.xmin[jvar])/2);
361  }
362  }
363 
364  NN_ava( xeev );
365 
366  Double_t retval = 0.5*(1.0 + fYNN[fParam_1.layerm-1][0]);
367 
368  delete [] xeev;
369 
370  return retval;
371 }
372 
373 ////////////////////////////////////////////////////////////////////////////////
374 /// auxiliary functions
375 
377 {
378  for (Int_t ivar=0; ivar<fNeur_1.neuron[0]; ivar++) fYNN[0][ivar] = xeev[ivar];
379 
380  for (Int_t layer=1; layer<fParam_1.layerm; layer++) {
381  for (Int_t j=1; j<=fNeur_1.neuron[layer]; j++) {
382 
383  Double_t x = Ww_ref(fNeur_1.ww, layer+1,j); // init with the bias layer
384 
385  for (Int_t k=1; k<=fNeur_1.neuron[layer-1]; k++) { // neurons of originating layer
386  x += fYNN[layer-1][k-1]*W_ref(fNeur_1.w, layer+1, j, k);
387  }
388  fYNN[layer][j-1] = NN_fonc( layer, x );
389  }
390  }
391 }
392 
393 ////////////////////////////////////////////////////////////////////////////////
394 /// activation function
395 
397 {
398  Double_t f(0);
399 
400  if (u/fDel_1.temp[i] > 170) f = +1;
401  else if (u/fDel_1.temp[i] < -170) f = -1;
402  else {
403  Double_t yy = TMath::Exp(-u/fDel_1.temp[i]);
404  f = (1 - yy)/(1 + yy);
405  }
406 
407  return f;
408 }
409 
410 ////////////////////////////////////////////////////////////////////////////////
411 /// read back the weight from the training from file (stream)
412 
414 {
415  TString var;
416 
417  // read number of variables and classes
418  UInt_t nva(0), lclass(0);
419  istr >> nva >> lclass;
420 
421  if (GetNvar() != nva) // wrong file
422  Log() << kFATAL << "<ReadWeightsFromFile> mismatch in number of variables" << Endl;
423 
424  // number of output classes must be 2
425  if (lclass != 2) // wrong file
426  Log() << kFATAL << "<ReadWeightsFromFile> mismatch in number of classes" << Endl;
427 
428  // check that we are not at the end of the file
429  if (istr.eof( ))
430  Log() << kFATAL << "<ReadWeightsFromStream> reached EOF prematurely " << Endl;
431 
432  // read extrema of input variables
433  for (UInt_t ivar=0; ivar<GetNvar(); ivar++)
434  istr >> fVarn_1.xmax[ivar] >> fVarn_1.xmin[ivar];
435 
436  // read number of layers (sum of: input + output + hidden)
437  istr >> fParam_1.layerm;
438 
439  if (fYNN != 0) {
440  for (Int_t i=0; i<fNlayers; i++) delete[] fYNN[i];
441  delete[] fYNN;
442  fYNN = 0;
443  }
444  fYNN = new Double_t*[fParam_1.layerm];
445  for (Int_t layer=0; layer<fParam_1.layerm; layer++) {
446  // read number of neurons for each layer
447  // coverity[tainted_data_argument]
448  istr >> fNeur_1.neuron[layer];
449  fYNN[layer] = new Double_t[fNeur_1.neuron[layer]];
450  }
451 
452  // to read dummy lines
453  const Int_t nchar( 100 );
454  char* dumchar = new char[nchar];
455 
456  // read weights
457  for (Int_t layer=1; layer<=fParam_1.layerm-1; layer++) {
458 
459  Int_t nq = fNeur_1.neuron[layer]/10;
460  Int_t nr = fNeur_1.neuron[layer] - nq*10;
461 
462  Int_t kk(0);
463  if (nr==0) kk = nq;
464  else kk = nq+1;
465 
466  for (Int_t k=1; k<=kk; k++) {
467  Int_t jmin = 10*k - 9;
468  Int_t jmax = 10*k;
469  if (fNeur_1.neuron[layer]<jmax) jmax = fNeur_1.neuron[layer];
470  for (Int_t j=jmin; j<=jmax; j++) {
471  istr >> Ww_ref(fNeur_1.ww, layer+1, j);
472  }
473  for (Int_t i=1; i<=fNeur_1.neuron[layer-1]; i++) {
474  for (Int_t j=jmin; j<=jmax; j++) {
475  istr >> W_ref(fNeur_1.w, layer+1, j, i);
476  }
477  }
478  // skip two empty lines
479  istr.getline( dumchar, nchar );
480  }
481  }
482 
483  for (Int_t layer=0; layer<fParam_1.layerm; layer++) {
484 
485  // skip 2 empty lines
486  istr.getline( dumchar, nchar );
487  istr.getline( dumchar, nchar );
488 
489  istr >> fDel_1.temp[layer];
490  }
491 
492  // sanity check
493  if ((Int_t)GetNvar() != fNeur_1.neuron[0]) {
494  Log() << kFATAL << "<ReadWeightsFromFile> mismatch in zeroth layer:"
495  << GetNvar() << " " << fNeur_1.neuron[0] << Endl;
496  }
497 
498  fNlayers = fParam_1.layerm;
499  delete[] dumchar;
500 }
501 
502 ////////////////////////////////////////////////////////////////////////////////
503 /// data interface function
504 
506  Int_t* /* icode*/, Int_t* /*flag*/,
507  Int_t* /*nalire*/, Int_t* nvar,
508  Double_t* xpg, Int_t* iclass, Int_t* ikend )
509 {
510  // icode and ikend are dummies needed to match f2c mlpl3 functions
511  *ikend = 0;
512 
513 
514  // sanity checks
515  if (0 == xpg) {
516  Log() << kFATAL << "ERROR in MethodCFMlpANN_DataInterface zero pointer xpg" << Endl;
517  }
518  if (*nvar != (Int_t)this->GetNvar()) {
519  Log() << kFATAL << "ERROR in MethodCFMlpANN_DataInterface mismatch in num of variables: "
520  << *nvar << " " << this->GetNvar() << Endl;
521  }
522 
523  // fill variables
524  *iclass = (int)this->GetClass( MethodCFMlpANN_nsel );
525  for (UInt_t ivar=0; ivar<this->GetNvar(); ivar++)
526  xpg[ivar] = (double)this->GetData( MethodCFMlpANN_nsel, ivar );
527 
529 
530  return 0;
531 }
532 
533 ////////////////////////////////////////////////////////////////////////////////
534 /// write weights to xml file
535 
536 void TMVA::MethodCFMlpANN::AddWeightsXMLTo( void* parent ) const
537 {
538  void *wght = gTools().AddChild(parent, "Weights");
539  gTools().AddAttr(wght,"NVars",fParam_1.nvar);
540  gTools().AddAttr(wght,"NClasses",fParam_1.lclass);
541  gTools().AddAttr(wght,"NLayers",fParam_1.layerm);
542  void* minmaxnode = gTools().AddChild(wght, "VarMinMax");
543  stringstream s;
544  s.precision( 16 );
545  for (Int_t ivar=0; ivar<fParam_1.nvar; ivar++)
546  s << std::scientific << fVarn_1.xmin[ivar] << " " << fVarn_1.xmax[ivar] << " ";
547  gTools().AddRawLine( minmaxnode, s.str().c_str() );
548  void* neurons = gTools().AddChild(wght, "NNeurons");
549  stringstream n;
550  n.precision( 16 );
551  for (Int_t layer=0; layer<fParam_1.layerm; layer++)
552  n << std::scientific << fNeur_1.neuron[layer] << " ";
553  gTools().AddRawLine( neurons, n.str().c_str() );
554  for (Int_t layer=1; layer<fParam_1.layerm; layer++) {
555  void* layernode = gTools().AddChild(wght, "Layer"+gTools().StringFromInt(layer));
556  gTools().AddAttr(layernode,"NNeurons",fNeur_1.neuron[layer]);
557  void* neuronnode=NULL;
558  for (Int_t neuron=0; neuron<fNeur_1.neuron[layer]; neuron++) {
559  neuronnode = gTools().AddChild(layernode,"Neuron"+gTools().StringFromInt(neuron));
560  stringstream weights;
561  weights.precision( 16 );
562  weights << std::scientific << Ww_ref(fNeur_1.ww, layer+1, neuron+1);
563  for (Int_t i=0; i<fNeur_1.neuron[layer-1]; i++) {
564  weights << " " << std::scientific << W_ref(fNeur_1.w, layer+1, neuron+1, i+1);
565  }
566  gTools().AddRawLine( neuronnode, weights.str().c_str() );
567  }
568  }
569  void* tempnode = gTools().AddChild(wght, "LayerTemp");
570  stringstream temp;
571  temp.precision( 16 );
572  for (Int_t layer=0; layer<fParam_1.layerm; layer++) {
573  temp << std::scientific << fDel_1.temp[layer] << " ";
574  }
575  gTools().AddRawLine(tempnode, temp.str().c_str() );
576 }
577 ////////////////////////////////////////////////////////////////////////////////
578 /// read weights from xml file
579 
581 {
582  gTools().ReadAttr( wghtnode, "NLayers",fParam_1.layerm );
583  void* minmaxnode = gTools().GetChild(wghtnode);
584  const char* minmaxcontent = gTools().GetContent(minmaxnode);
585  stringstream content(minmaxcontent);
586  for (UInt_t ivar=0; ivar<GetNvar(); ivar++)
587  content >> fVarn_1.xmin[ivar] >> fVarn_1.xmax[ivar];
588  if (fYNN != 0) {
589  for (Int_t i=0; i<fNlayers; i++) delete[] fYNN[i];
590  delete[] fYNN;
591  fYNN = 0;
592  }
593  fYNN = new Double_t*[fParam_1.layerm];
594  void *layernode=gTools().GetNextChild(minmaxnode);
595  const char* neuronscontent = gTools().GetContent(layernode);
596  stringstream ncontent(neuronscontent);
597  for (Int_t layer=0; layer<fParam_1.layerm; layer++) {
598  // read number of neurons for each layer;
599  // coverity[tainted_data_argument]
600  ncontent >> fNeur_1.neuron[layer];
601  fYNN[layer] = new Double_t[fNeur_1.neuron[layer]];
602  }
603  for (Int_t layer=1; layer<fParam_1.layerm; layer++) {
604  layernode=gTools().GetNextChild(layernode);
605  void* neuronnode=NULL;
606  neuronnode = gTools().GetChild(layernode);
607  for (Int_t neuron=0; neuron<fNeur_1.neuron[layer]; neuron++) {
608  const char* neuronweights = gTools().GetContent(neuronnode);
609  stringstream weights(neuronweights);
610  weights >> Ww_ref(fNeur_1.ww, layer+1, neuron+1);
611  for (Int_t i=0; i<fNeur_1.neuron[layer-1]; i++) {
612  weights >> W_ref(fNeur_1.w, layer+1, neuron+1, i+1);
613  }
614  neuronnode=gTools().GetNextChild(neuronnode);
615  }
616  }
617  void* tempnode=gTools().GetNextChild(layernode);
618  const char* temp = gTools().GetContent(tempnode);
619  stringstream t(temp);
620  for (Int_t layer=0; layer<fParam_1.layerm; layer++) {
621  t >> fDel_1.temp[layer];
622  }
623  fNlayers = fParam_1.layerm;
624 }
625 
626 ////////////////////////////////////////////////////////////////////////////////
627 /// write the weights of the neural net
628 
629 void TMVA::MethodCFMlpANN::PrintWeights( std::ostream & o ) const
630 {
631  // write number of variables and classes
632  o << "Number of vars " << fParam_1.nvar << std::endl;
633  o << "Output nodes " << fParam_1.lclass << std::endl;
634 
635  // write extrema of input variables
636  for (Int_t ivar=0; ivar<fParam_1.nvar; ivar++)
637  o << "Var " << ivar << " [" << fVarn_1.xmin[ivar] << " - " << fVarn_1.xmax[ivar] << "]" << std::endl;
638 
639  // write number of layers (sum of: input + output + hidden)
640  o << "Number of layers " << fParam_1.layerm << std::endl;
641 
642  o << "Nodes per layer ";
643  for (Int_t layer=0; layer<fParam_1.layerm; layer++)
644  // write number of neurons for each layer
645  o << fNeur_1.neuron[layer] << " ";
646  o << std::endl;
647 
648  // write weights
649  for (Int_t layer=1; layer<=fParam_1.layerm-1; layer++) {
650 
651  Int_t nq = fNeur_1.neuron[layer]/10;
652  Int_t nr = fNeur_1.neuron[layer] - nq*10;
653 
654  Int_t kk(0);
655  if (nr==0) kk = nq;
656  else kk = nq+1;
657 
658  for (Int_t k=1; k<=kk; k++) {
659  Int_t jmin = 10*k - 9;
660  Int_t jmax = 10*k;
661  Int_t i, j;
662  if (fNeur_1.neuron[layer]<jmax) jmax = fNeur_1.neuron[layer];
663  for (j=jmin; j<=jmax; j++) {
664 
665  //o << fNeur_1.ww[j*max_nLayers_ + layer - 6] << " ";
666  o << Ww_ref(fNeur_1.ww, layer+1, j) << " ";
667 
668  }
669  o << std::endl;
670  //for (i=1; i<=fNeur_1.neuron[layer-1]; i++) {
671  for (i=1; i<=fNeur_1.neuron[layer-1]; i++) {
672  for (j=jmin; j<=jmax; j++) {
673  // o << fNeur_1.w[(i*max_nNodes_ + j)*max_nLayers_ + layer - 186] << " ";
674  o << W_ref(fNeur_1.w, layer+1, j, i) << " ";
675  }
676  o << std::endl;
677  }
678 
679  // skip two empty lines
680  o << std::endl;
681  }
682  }
683  for (Int_t layer=0; layer<fParam_1.layerm; layer++) {
684  o << "Del.temp in layer " << layer << " : " << fDel_1.temp[layer] << std::endl;
685  }
686 }
687 
688 void TMVA::MethodCFMlpANN::MakeClassSpecific( std::ostream& fout, const TString& className ) const
689 {
690  // write specific classifier response
691  fout << " // not implemented for class: \"" << className << "\"" << std::endl;
692  fout << "};" << std::endl;
693 }
694 
695 ////////////////////////////////////////////////////////////////////////////////
696 /// write specific classifier response for header
697 
698 void TMVA::MethodCFMlpANN::MakeClassSpecificHeader( std::ostream& , const TString& ) const
699 {
700 }
701 
702 ////////////////////////////////////////////////////////////////////////////////
703 /// get help message text
704 ///
705 /// typical length of text line:
706 /// "|--------------------------------------------------------------|"
707 
709 {
710  Log() << Endl;
711  Log() << gTools().Color("bold") << "--- Short description:" << gTools().Color("reset") << Endl;
712  Log() << Endl;
713  Log() << "<None>" << Endl;
714  Log() << Endl;
715  Log() << gTools().Color("bold") << "--- Performance optimisation:" << gTools().Color("reset") << Endl;
716  Log() << Endl;
717  Log() << "<None>" << Endl;
718  Log() << Endl;
719  Log() << gTools().Color("bold") << "--- Performance tuning via configuration options:" << gTools().Color("reset") << Endl;
720  Log() << Endl;
721  Log() << "<None>" << Endl;
722 }
for(Int_t i=0;i< n;i++)
Definition: legend1.C:18
struct TMVA::MethodCFMlpANN_Utils::@183 fDel_1
Double_t GetData(Int_t isel, Int_t ivar) const
void Train(void)
training of the Clement-Ferrand NN classifier
void DeclareOptions()
define the options (their key words) that can be set in the option string know options: NCycles=xx :t...
MsgLogger & Endl(MsgLogger &ml)
Definition: MsgLogger.h:162
Double_t temp[max_nLayers_]
void NN_ava(Double_t *)
auxiliary functions
void MakeClassSpecificHeader(std::ostream &, const TString &="") const
write specific classifier response for header
Double_t Log(Double_t x)
Definition: TMath.h:526
Int_t GetClass(Int_t ivar) const
void ReadWeightsFromXML(void *wghtnode)
read weights from xml file
void MakeClassSpecific(std::ostream &, const TString &) const
UInt_t GetNvar() const
Definition: MethodBase.h:340
MsgLogger & Log() const
Definition: Configurable.h:128
OptionBase * DeclareOptionRef(T &ref, const TString &name, const TString &desc="")
EAnalysisType
Definition: Types.h:129
Basic string class.
Definition: TString.h:137
int Int_t
Definition: RtypesCore.h:41
bool Bool_t
Definition: RtypesCore.h:59
const Bool_t kFALSE
Definition: Rtypes.h:92
Double_t W_ref(const Double_t wNN[], Int_t a_1, Int_t a_2, Int_t a_3) const
void AddAttr(void *node, const char *, const T &value, Int_t precision=16)
Definition: Tools.h:309
Int_t DataInterface(Double_t *, Double_t *, Int_t *, Int_t *, Int_t *, Int_t *, Double_t *, Int_t *, Int_t *)
data interface function
void * AddChild(void *parent, const char *childname, const char *content=0, bool isRootNode=false)
add child node
Definition: Tools.cxx:1134
virtual ~MethodCFMlpANN(void)
destructor
Tools & gTools()
Definition: Tools.cxx:79
const Event * GetEvent() const
Definition: MethodBase.h:745
std::vector< Int_t > * fClass
DataSet * Data() const
Definition: MethodBase.h:405
virtual Bool_t HasAnalysisType(Types::EAnalysisType type, UInt_t numberClasses, UInt_t)
CFMlpANN can handle classification with 2 classes.
void * GetChild(void *parent, const char *childname=0)
get child node
Definition: Tools.cxx:1158
DataSetInfo & DataInfo() const
Definition: MethodBase.h:406
Ssiz_t First(char c) const
Find first occurrence of a character c.
Definition: TString.cxx:467
void PrintWeights(std::ostream &o) const
write the weights of the neural net
Long64_t GetNTrainingEvents() const
Definition: DataSet.h:93
Bool_t AddRawLine(void *node, const char *raw)
XML helpers.
Definition: Tools.cxx:1198
Double_t GetMvaValue(Double_t *err=0, Double_t *errUpper=0)
returns CFMlpANN output (normalised within [0,1])
Double_t NN_fonc(Int_t, Double_t) const
activation function
void Train_nn(Double_t *tin2, Double_t *tout2, Int_t *ntrain, Int_t *ntest, Int_t *nvar2, Int_t *nlayer, Int_t *nodes, Int_t *ncycle)
Double_t Ww_ref(const Double_t wwNN[], Int_t a_1, Int_t a_2) const
Bool_t BeginsWith(const char *s, ECaseCompare cmp=kExact) const
Definition: TString.h:558
unsigned int UInt_t
Definition: RtypesCore.h:42
Double_t x[max_nLayers_ *max_nNodes_]
Ssiz_t Length() const
Definition: TString.h:390
void GetHelpMessage() const
get help message text
struct TMVA::MethodCFMlpANN_Utils::@182 fNeur_1
const char * GetContent(void *node)
XML helpers.
Definition: Tools.cxx:1182
void ReadAttr(void *node, const char *, T &value)
Definition: Tools.h:296
Double_t EvalANN(std::vector< Double_t > &, Bool_t &isOK)
evaluates NN value as function of input variables
void ReadWeightsFromStream(std::istream &istr)
read back the weight from the training from file (stream)
void SetNormalised(Bool_t norm)
Definition: MethodBase.h:491
Float_t GetValue(UInt_t ivar) const
return value of i&#39;th variable
Definition: Event.cxx:233
TString & Remove(Ssiz_t pos)
Definition: TString.h:616
Bool_t IgnoreEventsWithNegWeightsInTraining() const
Definition: MethodBase.h:680
Double_t Exp(Double_t x)
Definition: TMath.h:495
#define ClassImp(name)
Definition: Rtypes.h:279
double f(double x)
double Double_t
Definition: RtypesCore.h:55
int type
Definition: TGX11.cxx:120
void * GetNextChild(void *prevchild, const char *childname=0)
XML helpers.
Definition: Tools.cxx:1170
void AddWeightsXMLTo(void *parent) const
write weights to xml file
TMatrixT< Float_t > TMatrix
Definition: TMatrix.h:26
void Init(void)
default initialisation called by all constructors
void ProcessOptions()
decode the options in the option string
void ExitFromTraining()
Definition: MethodBase.h:458
const TString & Color(const TString &)
human readable color strings
Definition: Tools.cxx:837
#define REGISTER_METHOD(CLASS)
for example
Abstract ClassifierFactory template that handles arbitrary types.
TString GetMethodTypeName() const
Definition: MethodBase.h:328
#define NULL
Definition: Rtypes.h:82
struct TMVA::MethodCFMlpANN_Utils::@181 fVarn_1
Bool_t IsSignal(const Event *ev) const
const Bool_t kTRUE
Definition: Rtypes.h:91
MethodCFMlpANN(const TString &jobName, const TString &methodTitle, DataSetInfo &theData, const TString &theOption="3000:N-1:N-2")
standard constructor option string: "n_training_cycles:n_hidden_layers" default is: n_training_cycles...
struct TMVA::MethodCFMlpANN_Utils::@180 fParam_1
const Int_t n
Definition: legend1.C:16
void NoErrorCalc(Double_t *const err, Double_t *const errUpper)
Definition: MethodBase.cxx:819
if(line.BeginsWith("/*"))
Definition: HLFactory.cxx:443