24#define NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION
25#include <numpy/arrayobject.h>
28namespace Experimental{
116 std::string fLayerType =
PyStringAsString(PyDict_GetItemString(fLayer,
"layerType"));
128 PyObject* fAttributes=PyDict_GetItemString(fLayer,
"layerAttributes");
130 std::string fLayerName =
PyStringAsString(PyDict_GetItemString(fAttributes,
"name"));
131 std::string fLayerActivation =
PyStringAsString(PyDict_GetItemString(fAttributes,
"activation"));
133 if(fLayerActivation ==
"selu" || fLayerActivation ==
"sigmoid")
137 if(fLayerActivation !=
"linear"){
138 PyObject* fOutputs = PyDict_GetItemString(fLayer,
"layerOutput");
139 PyObject* fInputs = PyDict_GetItemString(fLayer,
"layerInput");
140 std::string fActivationLayerOutput =
PyStringAsString(PyList_GetItem(fOutputs,0));
143 PyList_SetItem(fOutputs,0,PyUnicode_FromString((fLayerName+fLayerType).c_str()));
144 PyDict_SetItemString(fLayer,
"layerOutput",fOutputs);
147 std::string fActivationLayerInput =
PyStringAsString(PyList_GetItem(fOutputs,0));
148 PyList_SetItem(fInputs,0,PyUnicode_FromString(fActivationLayerInput.c_str()));
149 PyList_SetItem(fOutputs,0,PyUnicode_FromString(fActivationLayerOutput.c_str()));
150 PyDict_SetItemString(fLayer,
"layerInput",fInputs);
151 PyDict_SetItemString(fLayer,
"layerOutput",fOutputs);
153 auto findActivationLayer =
mapKerasLayer.find(fLayerActivation);
155 throw std::runtime_error(
"TMVA::SOFIE - Parsing Keras Activation layer " + fLayerActivation +
" is not yet supported");
157 rmodel.
AddOperator((findActivationLayer->second)(fLayer));
166 throw std::runtime_error(
"TMVA::SOFIE - Parsing Keras layer " + fLayerType +
" is not yet supported");
181 PyObject* fInputs = PyDict_GetItemString(fLayer,
"layerInput");
182 PyObject* fOutputs = PyDict_GetItemString(fLayer,
"layerOutput");
183 std::string fLayerDType =
PyStringAsString(PyDict_GetItemString(fLayer,
"layerDType"));
186 std::string fLayerOutputName =
PyStringAsString(PyList_GetItem(fOutputs,0));
191 PyObject* fWeightNames = PyDict_GetItemString(fLayer,
"layerWeight");
195 std::unique_ptr<ROperator> op;
197 float attr_alpha = 1.0;
198 float attr_beta = 1.0;
199 int_t attr_transA = 0;
200 int_t attr_transB = 0;
204 op.reset(
new ROperator_Gemm<float>(attr_alpha, attr_beta, attr_transA, attr_transB, fLayerInputName, fKernelName, fBiasName, fLayerOutputName));
208 throw std::runtime_error(
"TMVA::SOFIE - Unsupported - Operator Gemm does not yet support input type " + fLayerDType);
223 PyObject* fAttributes=PyDict_GetItemString(fLayer,
"layerAttributes");
224 std::string fLayerActivation =
PyStringAsString(PyDict_GetItemString(fAttributes,
"activation"));
228 throw std::runtime_error(
"TMVA::SOFIE - Parsing Keras Activation layer " + fLayerActivation +
" is not yet supported");
230 return (findLayer->second)(fLayer);
244 PyObject* fInputs=PyDict_GetItemString(fLayer,
"layerInput");
245 PyObject* fOutputs=PyDict_GetItemString(fLayer,
"layerOutput");
247 std::string fLayerDType =
PyStringAsString(PyDict_GetItemString(fLayer,
"layerDType"));
249 std::string fLayerOutputName =
PyStringAsString(PyList_GetItem(fOutputs,0));
251 std::unique_ptr<ROperator> op;
257 throw std::runtime_error(
"TMVA::SOFIE - Unsupported - Operator Relu does not yet support input type " + fLayerDType);
272 PyObject* fInputs = PyDict_GetItemString(fLayer,
"layerInput");
273 PyObject* fOutputs = PyDict_GetItemString(fLayer,
"layerOutput");
275 std::string fLayerDType =
PyStringAsString(PyDict_GetItemString(fLayer,
"layerDType"));
277 std::string fLayerOutputName =
PyStringAsString(PyList_GetItem(fOutputs,0));
279 std::unique_ptr<ROperator> op;
285 throw std::runtime_error(
"TMVA::SOFIE - Unsupported - Operator Selu does not yet support input type " + fLayerDType);
300 PyObject* fInputs = PyDict_GetItemString(fLayer,
"layerInput");
301 PyObject* fOutputs = PyDict_GetItemString(fLayer,
"layerOutput");
303 std::string fLayerDType =
PyStringAsString(PyDict_GetItemString(fLayer,
"layerDType"));
305 std::string fLayerOutputName =
PyStringAsString(PyList_GetItem(fOutputs,0));
307 std::unique_ptr<ROperator> op;
313 throw std::runtime_error(
"TMVA::SOFIE - Unsupported - Operator Sigmoid does not yet support input type " + fLayerDType);
331 PyObject* fAttributes=PyDict_GetItemString(fLayer,
"layerAttributes");
332 PyObject* fInputs=PyDict_GetItemString(fLayer,
"layerInput");
333 PyObject* fOutputs=PyDict_GetItemString(fLayer,
"layerOutput");
335 std::string fLayerDType =
PyStringAsString(PyDict_GetItemString(fLayer,
"layerDType"));
337 std::string fLayerOutputName =
PyStringAsString(PyList_GetItem(fOutputs,0));
340 PyObject* fAttributePermute=PyDict_GetItemString(fAttributes,
"dims");
341 std::vector<int_t>fPermuteDims;
344 for(
Py_ssize_t tupleIter=0;tupleIter<PyTuple_Size(fAttributePermute);++tupleIter){
346 fPermuteDims.push_back((
int_t)PyLong_AsLong(PyTuple_GetItem(fAttributePermute,tupleIter)));
348 std::unique_ptr<ROperator> op;
353 if (!fPermuteDims.empty()){
362 throw std::runtime_error(
"TMVA::SOFIE - Unsupported - Operator Transpose does not yet support input type " + fLayerDType);
412 size_t isep = filename.rfind(sep, filename.length());
413 std::string filename_nodir = filename;
414 if (isep != std::string::npos){
415 filename_nodir = (filename.substr(isep+1, filename.length() - isep));
419 if(!std::ifstream(filename).good()){
420 throw std::runtime_error(
"Model file "+filename_nodir+
" not found!");
424 std::time_t ttime = std::time(0);
425 std::tm* gmt_time = std::gmtime(&ttime);
426 std::string parsetime (std::asctime(gmt_time));
428 RModel rmodel(filename_nodir, parsetime);
436 throw std::runtime_error(
"Can't init global namespace for Python");
439 throw std::runtime_error(
"Can't init local namespace for Python");
446 PyRunString(
"import tensorflow.keras as keras",fGlobalNS,fLocalNS);
447 PyRunString(
"from tensorflow.keras.models import load_model",fGlobalNS,fLocalNS);
448 PyRunString(
"print('Keras Version: '+ keras.__version__)",fGlobalNS,fLocalNS);
451 PyRunString(
"globals().update(locals())",fGlobalNS,fLocalNS);
453 PyRunString(
"for idx in range(len(model.layers)):\n"
454 " layer=model.get_layer(index=idx)\n"
455 " globals().update(locals())\n"
457 " layerData['layerType']=layer.__class__.__name__\n"
458 " layerData['layerAttributes']=layer.get_config()\n"
459 " layerData['layerInput']=[x.name for x in layer.input] if isinstance(layer.input,list) else [layer.input.name]\n"
460 " layerData['layerOutput']=[x.name for x in layer.output] if isinstance(layer.output,list) else [layer.output.name]\n"
461 " layerData['layerDType']=layer.dtype\n"
462 " layerData['layerWeight']=[x.name for x in layer.weights]\n"
463 " modelData.append(layerData)",fGlobalNS,fLocalNS);
466 PyObject* fPModel = PyDict_GetItemString(fLocalNS,
"modelData");
469 std::string fLayerType;
473 for(
Py_ssize_t fModelIterator=0;fModelIterator<fModelSize;++fModelIterator){
474 fLayer = PyList_GetItem(fPModel,fModelIterator);
478 if(fLayerType ==
"InputLayer")
483 else if(fLayerType ==
"Dense")
492 PyRunString(
"globals().update(locals())",fGlobalNS,fLocalNS);
494 PyRunString(
"for idx in range(len(model.get_weights())):\n"
496 " weightProp['name']=model.weights[idx].name\n"
497 " weightProp['dtype']=(model.get_weights())[idx].dtype.name\n"
498 " weightProp['value']=(model.get_weights())[idx]\n"
499 " weight.append(weightProp)",fGlobalNS,fLocalNS);
502 PyArrayObject *fWeightTensorValue;
503 std::string fWeightName;
505 fPWeight = PyDict_GetItemString(fLocalNS,
"weight");
506 std::vector<std::size_t> fWeightTensorShape;
507 std::size_t fWeightTensorSize;
510 for (
Py_ssize_t weightIter = 0; weightIter < PyList_Size(fPWeight); weightIter++){
511 fWeightTensor = PyList_GetItem(fPWeight, weightIter);
515 fWeightTensorValue = (PyArrayObject*)PyDict_GetItemString(fWeightTensor,
"value");
517 fWeightTensorShape.clear();
520 for(
int j=0; j<PyArray_NDIM(fWeightTensorValue); ++j){
521 fWeightTensorShape.push_back((std::size_t)(PyArray_DIM(fWeightTensorValue,j)));
522 fWeightTensorSize*=(std::size_t)(PyArray_DIM(fWeightTensorValue,j));
525 switch(fWeightDType){
527 float* fWeightArray = (
float*)PyArray_DATA(fWeightTensorValue);
528 std::shared_ptr<void> fData(
malloc(fWeightTensorSize *
sizeof(
float)),
free);
529 std::memcpy(fData.get(),fWeightArray, fWeightTensorSize *
sizeof(
float));
534 throw std::runtime_error(
"Type error: TMVA SOFIE does not yet weight data layer type"+
ConvertTypeToString(fWeightDType));
543 PyRunString(
"inputNames=model.input_names",fGlobalNS,fLocalNS);
544 PyRunString(
"inputShapes=model.input_shape",fGlobalNS,fLocalNS);
546 PyRunString(
"for idx in range(len(model.inputs)):\n"
547 " inputTypes.append(model.inputs[idx].dtype.__str__()[9:-2])",fGlobalNS,fLocalNS);
549 PyObject* fPInputs = PyDict_GetItemString(fLocalNS,
"inputNames");
550 PyObject* fPInputShapes = PyDict_GetItemString(fLocalNS,
"inputShapes");
551 PyObject* fPInputTypes = PyDict_GetItemString(fLocalNS,
"inputTypes");
553 std::string fInputName;
560 if(PyTuple_Check(fPInputShapes)){
569 std::vector<size_t>fInputShape = GetDataFromTuple(fPInputShapes);
570 if (
static_cast<int>(fInputShape[0]) <= 0){
572 std::cout <<
"Model has not a defined batch size, assume is 1 - input shape : "
580 throw std::runtime_error(
"Type error: TMVA SOFIE does not yet suppport data type"+
ConvertTypeToString(fInputDType));
588 for(
Py_ssize_t inputIter = 0; inputIter < PyList_Size(fPInputs);++inputIter){
595 PyObject* fInputShapeTuple=PyList_GetItem(fPInputShapes,inputIter);
597 std::vector<size_t>fInputShape = GetDataFromTuple(fInputShapeTuple);
598 if (
static_cast<int>(fInputShape[0]) <= 0){
600 std::cout <<
"Model has not a defined batch size, assume is 1 - input shape for tensor "
608 throw std::runtime_error(
"Type error: TMVA SOFIE does not yet suppport data type"+
ConvertTypeToString(fInputDType));
617 PyRunString(
"for layerName in model.output_names:\n"
618 " outputNames.append(model.get_layer(layerName).output.name)",fGlobalNS,fLocalNS);
619 PyObject* fPOutputs = PyDict_GetItemString(fLocalNS,
"outputNames");
620 std::vector<std::string> fOutputNames;
621 for(
Py_ssize_t outputIter = 0; outputIter < PyList_Size(fPOutputs);++outputIter){
622 fOutputNames.push_back(
PyStringAsString(PyList_GetItem(fPOutputs,outputIter)));
typedef void(GLAPIENTRYP _GLUfuncptr)(void)
void AddOutputTensorNameList(std::vector< std::string > outputtensornames)
void AddInputTensorInfo(std::string input_name, ETensorType type, std::vector< Dim > shape)
void AddInitializedTensor(std::string tensor_name, ETensorType type, std::vector< std::size_t > shape, std::shared_ptr< void > data)
void AddBlasRoutines(std::vector< std::string > routines)
void AddNeededStdLib(std::string libname)
void AddOperator(std::unique_ptr< ROperator > op, int order_execution=-1)
static std::vector< size_t > GetDataFromTuple(PyObject *tupleObject)
Utility function which retrieves and returns the values of the Tuple object as a vector of size_t.
static const char * PyStringAsString(PyObject *string)
Returns const char* from Python string in PyObject.
void PyRunString(TString code, TString errorMessage="Failed to run python code", int start=Py_single_input)
Execute Python code from string.
static TString Format(const char *fmt,...)
Static method which formats a string using a printf style format descriptor and return a TString.
std::unique_ptr< ROperator > MakeKerasPermute(PyObject *fLayer)
Prepares a ROperator object for Keras Permute layer.
std::unordered_map< std::string, std::unique_ptr< ROperator >(*)(PyObject *fLayer)> KerasMethodMap
void AddKerasLayer(RModel &rmodel, PyObject *fLayer)
Adds equivalent ROperator with respect to Keras model layer into the referenced RModel object.
std::unique_ptr< ROperator > MakeKerasDense(PyObject *fLayer)
Prepares a ROperator object for Keras Dense Layer.
std::unique_ptr< ROperator > MakeKerasReLU(PyObject *fLayer)
Prepares a ROperator object for Keras ReLU activation.
const KerasMethodMapWithActivation mapKerasLayerWithActivation
std::unordered_map< std::string, std::unique_ptr< ROperator >(*)(PyObject *fLayer)> KerasMethodMapWithActivation
std::unique_ptr< ROperator > MakeKerasSigmoid(PyObject *fLayer)
Prepares a ROperator object for Keras Sigmoid activation.
std::unique_ptr< ROperator > MakeKerasSelu(PyObject *fLayer)
Prepares a ROperator object for Keras Selu activation.
const KerasMethodMap mapKerasLayer
std::unique_ptr< ROperator > MakeKerasActivation(PyObject *fLayer)
Prepares a ROperator object for Keras activation layer.
static void(&) PyRunString(TString, PyObject *, PyObject *)
static const char *(&) PyStringAsString(PyObject *)
RModel Parse(std::string filename)
Parser function for translatng Keras .h5 model into a RModel object.
std::string ConvertShapeToString(std::vector< size_t > shape)
std::string ConvertTypeToString(ETensorType type)
ETensorType ConvertStringToType(std::string type)
create variable transformations