Logo ROOT   6.14/05
Reference Guide
MethodPyKeras.cxx
Go to the documentation of this file.
1 // @(#)root/tmva/pymva $Id$
2 // Author: Stefan Wunsch, 2016
3 
4 #include <Python.h>
5 #include "TMVA/MethodPyKeras.h"
6 
7 #define NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION
8 #include <numpy/arrayobject.h>
9 
10 #include "TMVA/Types.h"
11 #include "TMVA/Config.h"
12 #include "TMVA/ClassifierFactory.h"
13 #include "TMVA/Results.h"
16 #include "TMVA/Tools.h"
17 
18 using namespace TMVA;
19 
20 REGISTER_METHOD(PyKeras)
21 
23 
24 MethodPyKeras::MethodPyKeras(const TString &jobName, const TString &methodTitle, DataSetInfo &dsi, const TString &theOption)
25  : PyMethodBase(jobName, Types::kPyKeras, methodTitle, dsi, theOption) {
26  fNumEpochs = 10;
27  fBatchSize = 100;
28  fVerbose = 1;
29  fContinueTraining = false;
30  fSaveBestOnly = true;
32  fLearningRateSchedule = ""; // empty string deactivates learning rate scheduler
33  fFilenameTrainedModel = ""; // empty string sets output model filename to default (in weights/)
34  fTensorBoard = ""; // empty string deactivates TensorBoard callback
35 }
36 
37 MethodPyKeras::MethodPyKeras(DataSetInfo &theData, const TString &theWeightFile)
38  : PyMethodBase(Types::kPyKeras, theData, theWeightFile) {
39  fNumEpochs = 10;
40  fBatchSize = 100;
41  fVerbose = 1;
42  fContinueTraining = false;
43  fSaveBestOnly = true;
45  fLearningRateSchedule = ""; // empty string deactivates learning rate scheduler
46  fFilenameTrainedModel = ""; // empty string sets output model filename to default (in weights/)
47  fTensorBoard = ""; // empty string deactivates TensorBoard callback
48 }
49 
51 }
52 
54  if (type == Types::kRegression) return kTRUE;
55  if (type == Types::kClassification && numberClasses == 2) return kTRUE;
56  if (type == Types::kMulticlass && numberClasses >= 2) return kTRUE;
57  return kFALSE;
58 }
59 
60 ///////////////////////////////////////////////////////////////////////////////
61 
63  DeclareOptionRef(fFilenameModel, "FilenameModel", "Filename of the initial Keras model");
64  DeclareOptionRef(fFilenameTrainedModel, "FilenameTrainedModel", "Filename of the trained output Keras model");
65  DeclareOptionRef(fBatchSize, "BatchSize", "Training batch size");
66  DeclareOptionRef(fNumEpochs, "NumEpochs", "Number of training epochs");
67  DeclareOptionRef(fVerbose, "Verbose", "Keras verbosity during training");
68  DeclareOptionRef(fContinueTraining, "ContinueTraining", "Load weights from previous training");
69  DeclareOptionRef(fSaveBestOnly, "SaveBestOnly", "Store only weights with smallest validation loss");
70  DeclareOptionRef(fTriesEarlyStopping, "TriesEarlyStopping", "Number of epochs with no improvement in validation loss after which training will be stopped. The default or a negative number deactivates this option.");
71  DeclareOptionRef(fLearningRateSchedule, "LearningRateSchedule", "Set new learning rate during training at specific epochs, e.g., \"50,0.01;70,0.005\"");
72  DeclareOptionRef(fTensorBoard, "TensorBoard",
73  "Write a log during training to visualize and monitor the training performance with TensorBoard");
74 }
75 
77  // Set default filename for trained model if option is not used
78  if (fFilenameTrainedModel.IsNull()) {
79  fFilenameTrainedModel = GetWeightFileDir() + "/TrainedModel_" + GetName() + ".h5";
80  }
81  // Setup model, either the initial model from `fFilenameModel` or
82  // the trained model from `fFilenameTrainedModel`
83  if (fContinueTraining) Log() << kINFO << "Continue training with trained model" << Endl;
85 }
86 
87 void MethodPyKeras::SetupKerasModel(bool loadTrainedModel) {
88  /*
89  * Load Keras model from file
90  */
91 
92  // Load initial model or already trained model
93  TString filenameLoadModel;
94  if (loadTrainedModel) {
95  filenameLoadModel = fFilenameTrainedModel;
96  }
97  else {
98  filenameLoadModel = fFilenameModel;
99  }
100  PyRunString("model = keras.models.load_model('"+filenameLoadModel+"')",
101  "Failed to load Keras model from file: "+filenameLoadModel);
102  Log() << kINFO << "Load model from file: " << filenameLoadModel << Endl;
103 
104  /*
105  * Init variables and weights
106  */
107 
108  // Get variables, classes and target numbers
109  fNVars = GetNVariables();
112  else Log() << kFATAL << "Selected analysis type is not implemented" << Endl;
113 
114  // Init evaluation (needed for getMvaValue)
115  fVals = new float[fNVars]; // holds values used for classification and regression
116  npy_intp dimsVals[2] = {(npy_intp)1, (npy_intp)fNVars};
117  PyArrayObject* pVals = (PyArrayObject*)PyArray_SimpleNewFromData(2, dimsVals, NPY_FLOAT, (void*)fVals);
118  PyDict_SetItemString(fLocalNS, "vals", (PyObject*)pVals);
119 
120  fOutput.resize(fNOutputs); // holds classification probabilities or regression output
121  npy_intp dimsOutput[2] = {(npy_intp)1, (npy_intp)fNOutputs};
122  PyArrayObject* pOutput = (PyArrayObject*)PyArray_SimpleNewFromData(2, dimsOutput, NPY_FLOAT, (void*)&fOutput[0]);
123  PyDict_SetItemString(fLocalNS, "output", (PyObject*)pOutput);
124 
125  // Mark the model as setup
126  fModelIsSetup = true;
127 }
128 
130  if (!PyIsInitialized()) {
131  Log() << kFATAL << "Python is not initialized" << Endl;
132  }
133  _import_array(); // required to use numpy arrays
134 
135  // Import Keras
136  // NOTE: sys.argv has to be cleared because otherwise TensorFlow breaks
137  PyRunString("import sys; sys.argv = ['']", "Set sys.argv failed");
138  PyRunString("import keras", "Import Keras failed");
139 
140  // Set flag that model is not setup
141  fModelIsSetup = false;
142 }
143 
145  if(!fModelIsSetup) Log() << kFATAL << "Model is not setup for training" << Endl;
146 
147  /*
148  * Load training data to numpy array
149  */
150 
151  UInt_t nTrainingEvents = Data()->GetNTrainingEvents();
152 
153  float* trainDataX = new float[nTrainingEvents*fNVars];
154  float* trainDataY = new float[nTrainingEvents*fNOutputs];
155  float* trainDataWeights = new float[nTrainingEvents];
156  for (UInt_t i=0; i<nTrainingEvents; i++) {
157  const TMVA::Event* e = GetTrainingEvent(i);
158  // Fill variables
159  for (UInt_t j=0; j<fNVars; j++) {
160  trainDataX[j + i*fNVars] = e->GetValue(j);
161  }
162  // Fill targets
163  // NOTE: For classification, convert class number in one-hot vector,
164  // e.g., 1 -> [0, 1] or 0 -> [1, 0] for binary classification
166  for (UInt_t j=0; j<fNOutputs; j++) {
167  trainDataY[j + i*fNOutputs] = 0;
168  }
169  trainDataY[e->GetClass() + i*fNOutputs] = 1;
170  }
171  else if (GetAnalysisType() == Types::kRegression) {
172  for (UInt_t j=0; j<fNOutputs; j++) {
173  trainDataY[j + i*fNOutputs] = e->GetTarget(j);
174  }
175  }
176  else Log() << kFATAL << "Can not fill target vector because analysis type is not known" << Endl;
177  // Fill weights
178  // NOTE: If no weight branch is given, this defaults to ones for all events
179  trainDataWeights[i] = e->GetWeight();
180  }
181 
182  npy_intp dimsTrainX[2] = {(npy_intp)nTrainingEvents, (npy_intp)fNVars};
183  npy_intp dimsTrainY[2] = {(npy_intp)nTrainingEvents, (npy_intp)fNOutputs};
184  npy_intp dimsTrainWeights[1] = {(npy_intp)nTrainingEvents};
185  PyArrayObject* pTrainDataX = (PyArrayObject*)PyArray_SimpleNewFromData(2, dimsTrainX, NPY_FLOAT, (void*)trainDataX);
186  PyArrayObject* pTrainDataY = (PyArrayObject*)PyArray_SimpleNewFromData(2, dimsTrainY, NPY_FLOAT, (void*)trainDataY);
187  PyArrayObject* pTrainDataWeights = (PyArrayObject*)PyArray_SimpleNewFromData(1, dimsTrainWeights, NPY_FLOAT, (void*)trainDataWeights);
188  PyDict_SetItemString(fLocalNS, "trainX", (PyObject*)pTrainDataX);
189  PyDict_SetItemString(fLocalNS, "trainY", (PyObject*)pTrainDataY);
190  PyDict_SetItemString(fLocalNS, "trainWeights", (PyObject*)pTrainDataWeights);
191 
192  /*
193  * Load validation data to numpy array
194  */
195 
196  // NOTE: In TMVA, test data is actually validation data
197 
198  UInt_t nValEvents = Data()->GetNTestEvents();
199 
200  float* valDataX = new float[nValEvents*fNVars];
201  float* valDataY = new float[nValEvents*fNOutputs];
202  float* valDataWeights = new float[nValEvents];
203  for (UInt_t i=0; i<nValEvents; i++) {
204  const TMVA::Event* e = GetTestingEvent(i);
205  // Fill variables
206  for (UInt_t j=0; j<fNVars; j++) {
207  valDataX[j + i*fNVars] = e->GetValue(j);
208  }
209  // Fill targets
211  for (UInt_t j=0; j<fNOutputs; j++) {
212  valDataY[j + i*fNOutputs] = 0;
213  }
214  valDataY[e->GetClass() + i*fNOutputs] = 1;
215  }
216  else if (GetAnalysisType() == Types::kRegression) {
217  for (UInt_t j=0; j<fNOutputs; j++) {
218  valDataY[j + i*fNOutputs] = e->GetTarget(j);
219  }
220  }
221  else Log() << kFATAL << "Can not fill target vector because analysis type is not known" << Endl;
222  // Fill weights
223  valDataWeights[i] = e->GetWeight();
224  }
225 
226  npy_intp dimsValX[2] = {(npy_intp)nValEvents, (npy_intp)fNVars};
227  npy_intp dimsValY[2] = {(npy_intp)nValEvents, (npy_intp)fNOutputs};
228  npy_intp dimsValWeights[1] = {(npy_intp)nValEvents};
229  PyArrayObject* pValDataX = (PyArrayObject*)PyArray_SimpleNewFromData(2, dimsValX, NPY_FLOAT, (void*)valDataX);
230  PyArrayObject* pValDataY = (PyArrayObject*)PyArray_SimpleNewFromData(2, dimsValY, NPY_FLOAT, (void*)valDataY);
231  PyArrayObject* pValDataWeights = (PyArrayObject*)PyArray_SimpleNewFromData(1, dimsValWeights, NPY_FLOAT, (void*)valDataWeights);
232  PyDict_SetItemString(fLocalNS, "valX", (PyObject*)pValDataX);
233  PyDict_SetItemString(fLocalNS, "valY", (PyObject*)pValDataY);
234  PyDict_SetItemString(fLocalNS, "valWeights", (PyObject*)pValDataWeights);
235 
236  /*
237  * Train Keras model
238  */
239 
240  // Setup parameters
241 
242  PyObject* pBatchSize = PyLong_FromLong(fBatchSize);
243  PyObject* pNumEpochs = PyLong_FromLong(fNumEpochs);
244  PyObject* pVerbose = PyLong_FromLong(fVerbose);
245  PyDict_SetItemString(fLocalNS, "batchSize", pBatchSize);
246  PyDict_SetItemString(fLocalNS, "numEpochs", pNumEpochs);
247  PyDict_SetItemString(fLocalNS, "verbose", pVerbose);
248 
249  // Setup training callbacks
250  PyRunString("callbacks = []");
251 
252  // Callback: Save only weights with smallest validation loss
253  if (fSaveBestOnly) {
254  PyRunString("callbacks.append(keras.callbacks.ModelCheckpoint('"+fFilenameTrainedModel+"', monitor='val_loss', verbose=verbose, save_best_only=True, mode='auto'))", "Failed to setup training callback: SaveBestOnly");
255  Log() << kINFO << "Option SaveBestOnly: Only model weights with smallest validation loss will be stored" << Endl;
256  }
257 
258  // Callback: Stop training early if no improvement in validation loss is observed
259  if (fTriesEarlyStopping>=0) {
260  TString tries;
261  tries.Form("%i", fTriesEarlyStopping);
262  PyRunString("callbacks.append(keras.callbacks.EarlyStopping(monitor='val_loss', patience="+tries+", verbose=verbose, mode='auto'))", "Failed to setup training callback: TriesEarlyStopping");
263  Log() << kINFO << "Option TriesEarlyStopping: Training will stop after " << tries << " number of epochs with no improvement of validation loss" << Endl;
264  }
265 
266  // Callback: Learning rate scheduler
267  if (fLearningRateSchedule!="") {
268  // Setup a python dictionary with the desired learning rate steps
269  PyRunString("strScheduleSteps = '"+fLearningRateSchedule+"'\n"
270  "schedulerSteps = {}\n"
271  "for c in strScheduleSteps.split(';'):\n"
272  " x = c.split(',')\n"
273  " schedulerSteps[int(x[0])] = float(x[1])\n",
274  "Failed to setup steps for scheduler function from string: "+fLearningRateSchedule,
275  Py_file_input);
276  // Set scheduler function as piecewise function with given steps
277  PyRunString("def schedule(epoch, model=model, schedulerSteps=schedulerSteps):\n"
278  " if epoch in schedulerSteps: return float(schedulerSteps[epoch])\n"
279  " else: return float(model.optimizer.lr.get_value())\n",
280  "Failed to setup scheduler function with string: "+fLearningRateSchedule,
281  Py_file_input);
282  // Setup callback
283  PyRunString("callbacks.append(keras.callbacks.LearningRateScheduler(schedule))",
284  "Failed to setup training callback: LearningRateSchedule");
285  Log() << kINFO << "Option LearningRateSchedule: Set learning rate during training: " << fLearningRateSchedule << Endl;
286  }
287 
288  // Callback: TensorBoard
289  if (fTensorBoard != "") {
290  TString logdir = TString("'") + fTensorBoard + TString("'");
291  PyRunString(
292  "callbacks.append(keras.callbacks.TensorBoard(log_dir=" + logdir +
293  ", histogram_freq=0, batch_size=batchSize, write_graph=True, write_grads=False, write_images=False))",
294  "Failed to setup training callback: TensorBoard");
295  Log() << kINFO << "Option TensorBoard: Log files for training monitoring are stored in: " << logdir << Endl;
296  }
297 
298  // Train model
299  PyRunString("history = model.fit(trainX, trainY, sample_weight=trainWeights, batch_size=batchSize, nb_epoch=numEpochs, verbose=verbose, validation_data=(valX, valY, valWeights), callbacks=callbacks)",
300  "Failed to train model");
301 
302  /*
303  * Store trained model to file (only if option 'SaveBestOnly' is NOT activated,
304  * because we do not want to override the best model checkpoint)
305  */
306 
307  if (!fSaveBestOnly) {
308  PyRunString("model.save('"+fFilenameTrainedModel+"', overwrite=True)",
309  "Failed to save trained model: "+fFilenameTrainedModel);
310  Log() << kINFO << "Trained model written to file: " << fFilenameTrainedModel << Endl;
311  }
312 
313  /*
314  * Clean-up
315  */
316 
317  delete[] trainDataX;
318  delete[] trainDataY;
319  delete[] trainDataWeights;
320  delete[] valDataX;
321  delete[] valDataY;
322  delete[] valDataWeights;
323 }
324 
327 }
328 
330  // Cannot determine error
331  NoErrorCalc(errLower, errUpper);
332 
333  // Check whether the model is setup
334  // NOTE: unfortunately this is needed because during evaluation ProcessOptions is not called again
335  if (!fModelIsSetup) {
336  // Setup the trained model
337  SetupKerasModel(true);
338  }
339 
340  // Get signal probability (called mvaValue here)
341  const TMVA::Event* e = GetEvent();
342  for (UInt_t i=0; i<fNVars; i++) fVals[i] = e->GetValue(i);
343  PyRunString("for i,p in enumerate(model.predict(vals)): output[i]=p\n",
344  "Failed to get predictions");
345 
347 }
348 
349 std::vector<Double_t> MethodPyKeras::GetMvaValues(Long64_t firstEvt, Long64_t lastEvt, Bool_t) {
350  // Check whether the model is setup
351  // NOTE: Unfortunately this is needed because during evaluation ProcessOptions is not called again
352  if (!fModelIsSetup) {
353  // Setup the trained model
354  SetupKerasModel(true);
355  }
356 
357  // Load data to numpy array
358  Long64_t nEvents = Data()->GetNEvents();
359  if (firstEvt > lastEvt || lastEvt > nEvents) lastEvt = nEvents;
360  if (firstEvt < 0) firstEvt = 0;
361  nEvents = lastEvt-firstEvt;
362 
363  float* data = new float[nEvents*fNVars];
364  for (UInt_t i=0; i<nEvents; i++) {
365  Data()->SetCurrentEvent(i);
366  const TMVA::Event *e = GetEvent();
367  for (UInt_t j=0; j<fNVars; j++) {
368  data[j + i*fNVars] = e->GetValue(j);
369  }
370  }
371 
372  npy_intp dimsData[2] = {(npy_intp)nEvents, (npy_intp)fNVars};
373  PyArrayObject* pDataMvaValues = (PyArrayObject*)PyArray_SimpleNewFromData(2, dimsData, NPY_FLOAT, (void*)data);
374  if (pDataMvaValues==0) Log() << "Failed to load data to Python array" << Endl;
375 
376  // Get prediction for all events
377  PyObject* pModel = PyDict_GetItemString(fLocalNS, "model");
378  if (pModel==0) Log() << kFATAL << "Failed to get model Python object" << Endl;
379  PyArrayObject* pPredictions = (PyArrayObject*) PyObject_CallMethod(pModel, (char*)"predict", (char*)"O", pDataMvaValues);
380  if (pPredictions==0) Log() << kFATAL << "Failed to get predictions" << Endl;
381  delete[] data;
382 
383  // Load predictions to double vector
384  // NOTE: The signal probability is given at the output
385  std::vector<double> mvaValues(nEvents);
386  float* predictionsData = (float*) PyArray_DATA(pPredictions);
387  for (UInt_t i=0; i<nEvents; i++) {
388  mvaValues[i] = (double) predictionsData[i*fNOutputs + TMVA::Types::kSignal];
389  }
390 
391  return mvaValues;
392 }
393 
394 std::vector<Float_t>& MethodPyKeras::GetRegressionValues() {
395  // Check whether the model is setup
396  // NOTE: unfortunately this is needed because during evaluation ProcessOptions is not called again
397  if (!fModelIsSetup){
398  // Setup the model and load weights
399  SetupKerasModel(true);
400  }
401 
402  // Get regression values
403  const TMVA::Event* e = GetEvent();
404  for (UInt_t i=0; i<fNVars; i++) fVals[i] = e->GetValue(i);
405  PyRunString("for i,p in enumerate(model.predict(vals)): output[i]=p\n",
406  "Failed to get predictions");
407 
408  // Use inverse transformation of targets to get final regression values
409  Event * eTrans = new Event(*e);
410  for (UInt_t i=0; i<fNOutputs; ++i) {
411  eTrans->SetTarget(i,fOutput[i]);
412  }
413 
414  const Event* eTrans2 = GetTransformationHandler().InverseTransform(eTrans);
415  for (UInt_t i=0; i<fNOutputs; ++i) {
416  fOutput[i] = eTrans2->GetTarget(i);
417  }
418 
419  return fOutput;
420 }
421 
422 std::vector<Float_t>& MethodPyKeras::GetMulticlassValues() {
423  // Check whether the model is setup
424  // NOTE: unfortunately this is needed because during evaluation ProcessOptions is not called again
425  if (!fModelIsSetup){
426  // Setup the model and load weights
427  SetupKerasModel(true);
428  }
429 
430  // Get class probabilites
431  const TMVA::Event* e = GetEvent();
432  for (UInt_t i=0; i<fNVars; i++) fVals[i] = e->GetValue(i);
433  PyRunString("for i,p in enumerate(model.predict(vals)): output[i]=p\n",
434  "Failed to get predictions");
435 
436  return fOutput;
437 }
438 
440 }
441 
443 // typical length of text line:
444 // "|--------------------------------------------------------------|"
445  Log() << Endl;
446  Log() << "Keras is a high-level API for the Theano and Tensorflow packages." << Endl;
447  Log() << "This method wraps the training and predictions steps of the Keras" << Endl;
448  Log() << "Python package for TMVA, so that dataloading, preprocessing and" << Endl;
449  Log() << "evaluation can be done within the TMVA system. To use this Keras" << Endl;
450  Log() << "interface, you have to generate a model with Keras first. Then," << Endl;
451  Log() << "this model can be loaded and trained in TMVA." << Endl;
452  Log() << Endl;
453 }
Double_t GetMvaValue(Double_t *errLower, Double_t *errUpper)
void SetCurrentEvent(Long64_t ievt) const
Definition: DataSet.h:99
MsgLogger & Endl(MsgLogger &ml)
Definition: MsgLogger.h:158
Singleton class for Global types used by TMVA.
Definition: Types.h:73
long long Long64_t
Definition: RtypesCore.h:69
MsgLogger & Log() const
Definition: Configurable.h:122
OptionBase * DeclareOptionRef(T &ref, const TString &name, const TString &desc="")
EAnalysisType
Definition: Types.h:127
TransformationHandler & GetTransformationHandler(Bool_t takeReroutedIfAvailable=true)
Definition: MethodBase.h:385
bool Bool_t
Definition: RtypesCore.h:59
UInt_t GetNClasses() const
Definition: DataSetInfo.h:136
static int PyIsInitialized()
Check Python interpreter initialization status.
const TString & GetWeightFileDir() const
Definition: MethodBase.h:481
std::vector< Float_t > & GetRegressionValues()
void PyRunString(TString code, TString errorMessage="Failed to run python code", int start=Py_single_input)
Execute Python code from string.
void GetHelpMessage() const
const Event * GetEvent() const
Definition: MethodBase.h:740
DataSet * Data() const
Definition: MethodBase.h:400
TString fFilenameTrainedModel
Definition: MethodPyKeras.h:89
UInt_t GetClass() const
Definition: Event.h:81
DataSetInfo & DataInfo() const
Definition: MethodBase.h:401
Class that contains all the data information.
Definition: DataSetInfo.h:60
Bool_t HasAnalysisType(Types::EAnalysisType type, UInt_t numberClasses, UInt_t)
Double_t GetWeight() const
return the event weight - depending on whether the flag IgnoreNegWeightsInTraining is or not...
Definition: Event.cxx:382
Long64_t GetNTrainingEvents() const
Definition: DataSet.h:79
const Event * GetTrainingEvent(Long64_t ievt) const
Definition: MethodBase.h:760
TString fLearningRateSchedule
Definition: MethodPyKeras.h:81
const Event * GetTestingEvent(Long64_t ievt) const
Definition: MethodBase.h:766
Float_t GetTarget(UInt_t itgt) const
Definition: Event.h:97
UInt_t GetNTargets() const
Definition: DataSetInfo.h:111
const char * GetName() const
Definition: MethodBase.h:325
unsigned int UInt_t
Definition: RtypesCore.h:42
const Event * InverseTransform(const Event *, Bool_t suppressIfNoTargets=true) const
void SetTarget(UInt_t itgt, Float_t value)
set the target value (dimension itgt) to value
Definition: Event.cxx:360
std::vector< Float_t > & GetMulticlassValues()
Long64_t GetNTestEvents() const
Definition: DataSet.h:80
UInt_t GetNVariables() const
Definition: MethodBase.h:336
const Bool_t kFALSE
Definition: RtypesCore.h:88
Float_t GetValue(UInt_t ivar) const
return value of i&#39;th variable
Definition: Event.cxx:237
void SetupKerasModel(Bool_t loadTrainedModel)
#define ClassImp(name)
Definition: Rtypes.h:359
double Double_t
Definition: RtypesCore.h:55
std::vector< Double_t > GetMvaValues(Long64_t firstEvt, Long64_t lastEvt, Bool_t logProgress)
get all the MVA values for the events of the current Data type
int type
Definition: TGX11.cxx:120
virtual void TestClassification()
initialization
you should not use this method at all Int_t Int_t Double_t Double_t Double_t e
Definition: TRolke.cxx:630
#define REGISTER_METHOD(CLASS)
for example
Abstract ClassifierFactory template that handles arbitrary types.
PyObject * fLocalNS
Definition: PyMethodBase.h:143
Long64_t GetNEvents(Types::ETreeType type=Types::kMaxTreeType) const
Definition: DataSet.h:217
Types::EAnalysisType GetAnalysisType() const
Definition: MethodBase.h:428
MethodPyKeras(const TString &jobName, const TString &methodTitle, DataSetInfo &dsi, const TString &theOption="")
const Bool_t kTRUE
Definition: RtypesCore.h:87
virtual void TestClassification()
initialization
std::vector< float > fOutput
Definition: MethodPyKeras.h:86
_object PyObject
Definition: TPyArg.h:20
void NoErrorCalc(Double_t *const err, Double_t *const errUpper)
Definition: MethodBase.cxx:841