Belle II Software light-2405-quaxo
PythonExpert Class Reference

Expert for the Python MVA method. More...

#include <Python.h>

Inheritance diagram for PythonExpert:
Collaboration diagram for PythonExpert:

Public Member Functions

 PythonExpert ()
 Constructs a new Python Expert.
 
virtual void load (Weightfile &weightfile) override
 Load the expert from a Weightfile.
 
virtual std::vector< float > apply (Dataset &test_data) const override
 Apply this expert onto a dataset.
 
virtual std::vector< std::vector< float > > applyMulticlass (Dataset &test_data) const override
 Apply this expert onto a dataset for multiclass problem.
 

Protected Attributes

PythonOptions m_specific_options
 Method specific options.
 
boost::python::object m_framework
 Framework module.
 
boost::python::object m_state
 current state object of method
 
std::vector< float > m_means
 Means of all features for normalization.
 
std::vector< float > m_stds
 Stds of all features for normalization.
 
GeneralOptions m_general_options
 General options loaded from the weightfile.
 

Detailed Description

Expert for the Python MVA method.

Definition at line 113 of file Python.h.

Constructor & Destructor Documentation

◆ PythonExpert()

Constructs a new Python Expert.

Definition at line 382 of file Python.cc.

383 {
385 }
static PythonInitializerSingleton & GetInstance()
Return static instance of PythonInitializerSingleton.
Definition: Python.cc:145

Member Function Documentation

◆ apply()

std::vector< float > apply ( Dataset test_data) const
overridevirtual

Apply this expert onto a dataset.

Parameters
test_datadataset

Implements Expert.

Definition at line 426 of file Python.cc.

427 {
428
429 uint64_t numberOfFeatures = test_data.getNumberOfFeatures();
430 uint64_t numberOfEvents = test_data.getNumberOfEvents();
431
432 auto X = std::unique_ptr<float[]>(new float[numberOfEvents * numberOfFeatures]);
433 npy_intp dimensions_X[2] = {static_cast<npy_intp>(numberOfEvents), static_cast<npy_intp>(numberOfFeatures)};
434
435 for (uint64_t iEvent = 0; iEvent < numberOfEvents; ++iEvent) {
436 test_data.loadEvent(iEvent);
438 for (uint64_t iFeature = 0; iFeature < numberOfFeatures; ++iFeature)
439 X[iEvent * numberOfFeatures + iFeature] = (test_data.m_input[iFeature] - m_means[iFeature]) / m_stds[iFeature];
440 } else {
441 for (uint64_t iFeature = 0; iFeature < numberOfFeatures; ++iFeature)
442 X[iEvent * numberOfFeatures + iFeature] = test_data.m_input[iFeature];
443 }
444 }
445
446 std::vector<float> probabilities(test_data.getNumberOfEvents(), std::numeric_limits<float>::quiet_NaN());
447
448 try {
449 auto ndarray_X = boost::python::handle<>(PyArray_SimpleNewFromData(2, dimensions_X, NPY_FLOAT32, X.get()));
450 auto result = m_framework.attr("apply")(m_state, ndarray_X);
451 for (uint64_t iEvent = 0; iEvent < numberOfEvents; ++iEvent) {
452 // We have to do some nasty casting here, because the Python C-Api uses structs which are binary compatible
453 // to a PyObject but do not inherit from it!
454 probabilities[iEvent] = static_cast<float>(*static_cast<float*>(PyArray_GETPTR1(reinterpret_cast<PyArrayObject*>(result.ptr()),
455 iEvent)));
456 }
457 } catch (...) {
458 PyErr_Print();
459 PyErr_Clear();
460 B2ERROR("Failed calling applying PythonExpert");
461 throw std::runtime_error("Failed calling applying PythonExpert");
462 }
463
464 return probabilities;
465 }
boost::python::object m_state
current state object of method
Definition: Python.h:142
std::vector< float > m_stds
Stds of all features for normalization.
Definition: Python.h:144
boost::python::object m_framework
Framework module.
Definition: Python.h:141
PythonOptions m_specific_options
Method specific options.
Definition: Python.h:140
std::vector< float > m_means
Means of all features for normalization.
Definition: Python.h:143
bool m_normalize
Normalize the inputs (shift mean to zero and std to 1)
Definition: Python.h:83

◆ applyMulticlass()

std::vector< std::vector< float > > applyMulticlass ( Dataset test_data) const
overridevirtual

Apply this expert onto a dataset for multiclass problem.

Parameters
test_datadataset

Reimplemented from Expert.

Definition at line 467 of file Python.cc.

468 {
469
470 uint64_t numberOfFeatures = test_data.getNumberOfFeatures();
471 uint64_t numberOfEvents = test_data.getNumberOfEvents();
472
473 auto X = std::unique_ptr<float[]>(new float[numberOfEvents * numberOfFeatures]);
474 npy_intp dimensions_X[2] = {static_cast<npy_intp>(numberOfEvents), static_cast<npy_intp>(numberOfFeatures)};
475
476 for (uint64_t iEvent = 0; iEvent < numberOfEvents; ++iEvent) {
477 test_data.loadEvent(iEvent);
479 for (uint64_t iFeature = 0; iFeature < numberOfFeatures; ++iFeature)
480 X[iEvent * numberOfFeatures + iFeature] = (test_data.m_input[iFeature] - m_means[iFeature]) / m_stds[iFeature];
481 } else {
482 for (uint64_t iFeature = 0; iFeature < numberOfFeatures; ++iFeature)
483 X[iEvent * numberOfFeatures + iFeature] = test_data.m_input[iFeature];
484 }
485 }
486
487 unsigned int nClasses = m_general_options.m_nClasses;
488 std::vector<std::vector<float>> probabilities(test_data.getNumberOfEvents(), std::vector<float>(nClasses,
489 std::numeric_limits<float>::quiet_NaN()));
490
491 try {
492 auto ndarray_X = boost::python::handle<>(PyArray_SimpleNewFromData(2, dimensions_X, NPY_FLOAT32, X.get()));
493 auto result = m_framework.attr("apply")(m_state, ndarray_X);
494 for (uint64_t iEvent = 0; iEvent < numberOfEvents; ++iEvent) {
495 // We have to do some nasty casting here, because the Python C-Api uses structs which are binary compatible
496 // to a PyObject but do not inherit from it!
497 for (uint64_t iClass = 0; iClass < nClasses; ++iClass) {
498 probabilities[iEvent][iClass] = static_cast<float>(*static_cast<float*>(PyArray_GETPTR2(reinterpret_cast<PyArrayObject*>
499 (result.ptr()),
500 iEvent, iClass)));
501 }
502 }
503 } catch (...) {
504 PyErr_Print();
505 PyErr_Clear();
506 B2ERROR("Failed calling applying PythonExpert");
507 throw std::runtime_error("Failed calling applying PythonExpert");
508 }
509
510 return probabilities;
511 }
GeneralOptions m_general_options
General options loaded from the weightfile.
Definition: Expert.h:70
unsigned int m_nClasses
Number of classes in a classification problem.
Definition: Options.h:89

◆ load()

void load ( Weightfile weightfile)
overridevirtual

Load the expert from a Weightfile.

Parameters
weightfilecontaining all information necessary to build the expert

Implements Expert.

Definition at line 388 of file Python.cc.

389 {
390
391 std::string custom_weightfile = weightfile.generateFileName();
392 weightfile.getFile("Python_Weightfile", custom_weightfile);
393 weightfile.getOptions(m_general_options);
394 weightfile.getOptions(m_specific_options);
395
397 m_means = weightfile.getVector<float>("Python_Means");
398 m_stds = weightfile.getVector<float>("Python_Stds");
399 }
400
401 try {
402 auto pickle = boost::python::import("pickle");
403 auto builtins = boost::python::import("builtins");
404 m_framework = boost::python::import((std::string("basf2_mva_python_interface.") + m_specific_options.m_framework).c_str());
405
406 if (weightfile.containsElement("Python_Steeringfile")) {
407 std::string custom_steeringfile = weightfile.generateFileName();
408 weightfile.getFile("Python_Steeringfile", custom_steeringfile);
409 auto steeringfile = builtins.attr("open")(custom_steeringfile.c_str(), "rb");
410 auto source_code = pickle.attr("load")(steeringfile);
411 builtins.attr("exec")(boost::python::object(source_code), boost::python::object(m_framework.attr("__dict__")));
412 }
413
414 auto file = builtins.attr("open")(custom_weightfile.c_str(), "rb");
415 auto unpickled_fit_object = pickle.attr("load")(file);
416 m_state = m_framework.attr("load")(unpickled_fit_object);
417 } catch (...) {
418 PyErr_Print();
419 PyErr_Clear();
420 B2ERROR("Failed calling load in PythonExpert");
421 throw std::runtime_error("Failed calling load in PythonExpert");
422 }
423
424 }
std::string m_framework
framework to use e.g.
Definition: Python.h:77

Member Data Documentation

◆ m_framework

boost::python::object m_framework
protected

Framework module.

Definition at line 141 of file Python.h.

◆ m_general_options

GeneralOptions m_general_options
protectedinherited

General options loaded from the weightfile.

Definition at line 70 of file Expert.h.

◆ m_means

std::vector<float> m_means
protected

Means of all features for normalization.

Definition at line 143 of file Python.h.

◆ m_specific_options

PythonOptions m_specific_options
protected

Method specific options.

Definition at line 140 of file Python.h.

◆ m_state

boost::python::object m_state
protected

current state object of method

Definition at line 142 of file Python.h.

◆ m_stds

std::vector<float> m_stds
protected

Stds of all features for normalization.

Definition at line 144 of file Python.h.


The documentation for this class was generated from the following files: