24#define NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION
25#include <numpy/arrayobject.h>
29namespace Experimental{
145 if(fLayerType ==
"Reshape"){
149 std::vector<size_t>fTargetShape = GetDataFromTuple(fPTargetShape);
150 std::shared_ptr<void> fData(
malloc(fTargetShape.size() *
sizeof(int64_t)),
free);
151 std::copy(fTargetShape.begin(),fTargetShape.end(),(int64_t*)fData.get());
170 std::string fLayerActivation =
PyStringAsString(PyObject_GetAttrString(fPActivation,
"__name__"));
172 if(fLayerActivation ==
"selu" || fLayerActivation ==
"sigmoid")
177 if(fLayerActivation !=
"linear"){
180 std::string fActivationLayerOutput =
PyStringAsString(PyList_GetItem(fOutputs,0));
182 if(fLayerType ==
"Conv2D"){
183 std::unique_ptr<ROperator> op_pre_transpose;
187 PyList_SetItem(fInputs,0,PyUnicode_FromString((fLayerName+
"PreTrans").c_str()));
188 PyDict_SetItemString(fLayer,
"layerInput",fInputs);
192 PyList_SetItem(fOutputs,0,PyUnicode_FromString((fLayerName+fLayerType).c_str()));
193 PyDict_SetItemString(fLayer,
"layerOutput",fOutputs);
196 std::string fActivationLayerInput = fLayerName+fLayerType;
197 if(fLayerType ==
"Conv2D"){
198 std::unique_ptr<ROperator> op_post_transpose;
201 fActivationLayerInput = fLayerName+
"PostTrans";
204 PyList_SetItem(fInputs,0,PyUnicode_FromString(fActivationLayerInput.c_str()));
205 PyList_SetItem(fOutputs,0,PyUnicode_FromString(fActivationLayerOutput.c_str()));
206 PyDict_SetItemString(fLayer,
"layerInput",fInputs);
207 PyDict_SetItemString(fLayer,
"layerOutput",fOutputs);
209 auto findActivationLayer =
mapKerasLayer.find(fLayerActivation);
211 throw std::runtime_error(
"TMVA::SOFIE - Parsing Keras Activation layer " + fLayerActivation +
" is not yet supported");
213 rmodel.
AddOperator((findActivationLayer->second)(fLayer));
223 throw std::runtime_error(
"TMVA::SOFIE - Parsing Keras layer " + fLayerType +
" is not yet supported");
243 std::string fLayerOutputName =
PyStringAsString(PyList_GetItem(fOutputs,0));
252 std::unique_ptr<ROperator> op;
254 float attr_alpha = 1.0;
255 float attr_beta = 1.0;
256 int_t attr_transA = 0;
257 int_t attr_transB = 0;
261 op.reset(
new ROperator_Gemm<float>(attr_alpha, attr_beta, attr_transA, attr_transB, fLayerInputName, fKernelName, fBiasName, fLayerOutputName));
265 throw std::runtime_error(
"TMVA::SOFIE - Unsupported - Operator Gemm does not yet support input type " + fLayerDType);
289 std::string fLayerOutputName =
PyStringAsString(PyList_GetItem(fOutputs,0));
305 std::vector<size_t> fAttrDilations = GetDataFromTuple(fDilations);
308 size_t fAttrGroup = PyLong_AsLong(fGroup);
309 std::vector<size_t> fAttrKernelShape = GetDataFromTuple(fKernelShape);
310 std::vector<size_t> fAttrStrides = GetDataFromTuple(fStrides);
311 std::string fAttrAutopad;
312 std::vector<size_t>fAttrPads;
316 if(fKerasPadding ==
"valid"){
317 fAttrAutopad =
"VALID";
319 else if(fKerasPadding ==
"same"){
320 fAttrAutopad=
"NOTSET";
322 long inputHeight = PyLong_AsLong(PyTuple_GetItem(fInputShape,1));
323 long inputWidth = PyLong_AsLong(PyTuple_GetItem(fInputShape,2));
325 long outputHeight = std::ceil(
float(inputHeight) /
float(fAttrStrides[0]));
326 long outputWidth = std::ceil(
float(inputWidth) /
float(fAttrStrides[1]));
328 long padding_height = std::max(
long((outputHeight - 1) * fAttrStrides[0] + fAttrKernelShape[0] - inputHeight),0L);
329 long padding_width = std::max(
long((outputWidth - 1) * fAttrStrides[1] + fAttrKernelShape[1] - inputWidth),0L);
331 size_t padding_top = std::floor(padding_height/2);
332 size_t padding_bottom = padding_height - padding_top;
333 size_t padding_left = std::floor(padding_width/2);
334 size_t padding_right = padding_width - padding_left;
335 fAttrPads = {padding_top,padding_bottom,padding_left,padding_right};
338 throw std::runtime_error(
"TMVA::SOFIE - RModel Keras Parser doesn't yet supports Convolution layer with padding " + fKerasPadding);
341 std::unique_ptr<ROperator> op;
345 op.reset(
new ROperator_Conv<float>(fAttrAutopad, fAttrDilations, fAttrGroup, fAttrKernelShape, fAttrPads, fAttrStrides, fLayerInputName, fKernelName, fBiasName, fLayerOutputName));
349 throw std::runtime_error(
"TMVA::SOFIE - Unsupported - Operator Conv does not yet support input type " + fLayerDType);
366 std::string fLayerActivation =
PyStringAsString(PyObject_GetAttrString(fPActivation,
"__name__"));
370 throw std::runtime_error(
"TMVA::SOFIE - Parsing Keras Activation layer " + fLayerActivation +
" is not yet supported");
372 return (findLayer->second)(fLayer);
391 std::string fLayerOutputName =
PyStringAsString(PyList_GetItem(fOutputs,0));
393 std::unique_ptr<ROperator> op;
399 throw std::runtime_error(
"TMVA::SOFIE - Unsupported - Operator Relu does not yet support input type " + fLayerDType);
419 std::string fLayerOutputName =
PyStringAsString(PyList_GetItem(fOutputs,0));
421 std::unique_ptr<ROperator> op;
427 throw std::runtime_error(
"TMVA::SOFIE - Unsupported - Operator Selu does not yet support input type " + fLayerDType);
447 std::string fLayerOutputName =
PyStringAsString(PyList_GetItem(fOutputs,0));
449 std::unique_ptr<ROperator> op;
455 throw std::runtime_error(
"TMVA::SOFIE - Unsupported - Operator Sigmoid does not yet support input type " + fLayerDType);
474 std::string fLayerOutputName =
PyStringAsString(PyList_GetItem(fOutputs,0));
476 std::unique_ptr<ROperator> op;
482 throw std::runtime_error(
"TMVA::SOFIE - Unsupported - Operator Sigmoid does not yet support input type " + fLayerDType);
503 std::string fLayerOutputName =
PyStringAsString(PyList_GetItem(fOutputs,0));
504 float fAlpha = (float)PyFloat_AsDouble(
GetValueFromDict(fAttributes,
"alpha"));
505 std::unique_ptr<ROperator> op;
511 throw std::runtime_error(
"TMVA::SOFIE - Unsupported - Operator Sigmoid does not yet support input type " + fLayerDType);
530 std::string fLayerOutputName =
PyStringAsString(PyList_GetItem(fOutputs,0));
532 std::unique_ptr<ROperator> op;
538 throw std::runtime_error(
"TMVA::SOFIE - Unsupported - Operator Tanh does not yet support input type " + fLayerDType);
557 std::string fLayerOutputName =
PyStringAsString(PyList_GetItem(fOutputs,0));
559 std::unique_ptr<ROperator> op;
565 throw std::runtime_error(
"TMVA::SOFIE - Unsupported - Operator Swish does not yet support input type " + fLayerDType);
588 std::string fLayerOutputName =
PyStringAsString(PyList_GetItem(fOutputs,0));
592 std::vector<int_t>fPermuteDims;
595 for(
Py_ssize_t tupleIter=0;tupleIter<PyTuple_Size(fAttributePermute);++tupleIter){
597 fPermuteDims.push_back((
int_t)PyLong_AsLong(PyTuple_GetItem(fAttributePermute,tupleIter)));
599 std::unique_ptr<ROperator> op;
604 if (!fPermuteDims.empty()){
613 throw std::runtime_error(
"TMVA::SOFIE - Unsupported - Operator Transpose does not yet support input type " + fLayerDType);
637 std::string fNScale =
PyStringAsString(PyObject_GetAttrString(fGamma,
"name"));
639 std::string fNMean =
PyStringAsString(PyObject_GetAttrString(fMoving_Mean,
"name"));
640 std::string fNVar =
PyStringAsString(PyObject_GetAttrString(fMoving_Var,
"name"));
641 float fEpsilon = (float)PyFloat_AsDouble(
GetValueFromDict(fAttributes,
"epsilon"));
642 float fMomentum = (float)PyFloat_AsDouble(
GetValueFromDict(fAttributes,
"momentum"));
644 std::unique_ptr<ROperator> op;
667 std::string fNameShape = fLayerName +
"ReshapeAxes";
668 std::unique_ptr<ROperator> op;
684 std::vector<std::string> inputs;
685 for(
Py_ssize_t i=0; i<PyList_Size(fInputs); ++i){
691 std::unique_ptr<ROperator> op;
716 std::unique_ptr<ROperator> op;
719 if(fLayerType ==
"Add")
721 else if(fLayerType ==
"Subtract")
728 throw std::runtime_error(
"TMVA::SOFIE - Unsupported - Operator Sigmoid does not yet support input type " + fLayerDType);
748 std::string fLayerOutputName =
PyStringAsString(PyList_GetItem(fOutputs,0));
750 std::unique_ptr<ROperator> op;
756 throw std::runtime_error(
"TMVA::SOFIE - Unsupported - Operator Identity does not yet support input type " + fLayerDType);
807 std::string filename_nodir =
filename;
808 if (isep != std::string::npos){
813 if(!std::ifstream(
filename).good()){
814 throw std::runtime_error(
"Model file "+filename_nodir+
" not found!");
818 std::time_t ttime = std::time(0);
819 std::tm* gmt_time = std::gmtime(&ttime);
820 std::string parsetime (std::asctime(gmt_time));
822 RModel rmodel(filename_nodir, parsetime);
830 throw std::runtime_error(
"Can't init global namespace for Python");
833 throw std::runtime_error(
"Can't init local namespace for Python");
840 PyRunString(
"import tensorflow",fGlobalNS,fLocalNS);
841 PyRunString(
"import tensorflow.keras as keras",fGlobalNS,fLocalNS);
842 PyRunString(
"from tensorflow.keras.models import load_model",fGlobalNS,fLocalNS);
843 PyRunString(
"print('TF/Keras Version: '+ tensorflow.__version__)",fGlobalNS,fLocalNS);
846 PyRunString(
"globals().update(locals())",fGlobalNS,fLocalNS);
848 PyRunString(
"for idx in range(len(model.layers)):\n"
849 " layer=model.get_layer(index=idx)\n"
851 " layerData['layerType']=layer.__class__.__name__\n"
852 " layerData['layerAttributes']=layer.__dict__\n"
853 " layerData['layerInput']=[x.name for x in layer.input] if isinstance(layer.input,list) else [layer.input.name]\n"
854 " layerData['layerOutput']=[x.name for x in layer.output] if isinstance(layer.output,list) else [layer.output.name]\n"
855 " layerData['layerDType']=layer.dtype\n"
856 " layerData['layerWeight']=[x.name for x in layer.weights]\n"
857 " modelData.append(layerData)",fGlobalNS,fLocalNS);
863 std::string fLayerType;
867 for(
Py_ssize_t fModelIterator=0;fModelIterator<fModelSize;++fModelIterator){
868 fLayer = PyList_GetItem(fPModel,fModelIterator);
872 if(fLayerType ==
"InputLayer")
877 else if(fLayerType ==
"Dense")
879 else if (fLayerType ==
"BatchNormalization")
881 else if(fLayerType ==
"Conv1D" || fLayerType ==
"Conv2D" || fLayerType ==
"Conv3D")
892 PyRunString(
"for idx in range(len(model.get_weights())):\n"
894 " weightProp['name']=model.weights[idx].name\n"
895 " weightProp['dtype']=(model.get_weights())[idx].dtype.name\n"
896 " weightProp['value']=(model.get_weights())[idx].transpose((3,2,0,1)).copy() if ('conv' in model.weights[idx].name and model.weights[idx].shape.ndims == 4) else (model.get_weights())[idx]\n"
897 " weight.append(weightProp)",fGlobalNS,fLocalNS);
900 PyArrayObject *fWeightTensorValue;
901 std::string fWeightName;
904 std::vector<std::size_t> fWeightTensorShape;
905 std::size_t fWeightTensorSize;
908 for (
Py_ssize_t weightIter = 0; weightIter < PyList_Size(fPWeight); weightIter++){
909 fWeightTensor = PyList_GetItem(fPWeight, weightIter);
913 fWeightTensorValue = (PyArrayObject*)
GetValueFromDict(fWeightTensor,
"value");
915 fWeightTensorShape.clear();
918 for(
int j=0; j<PyArray_NDIM(fWeightTensorValue); ++j){
919 fWeightTensorShape.push_back((std::size_t)(PyArray_DIM(fWeightTensorValue,j)));
920 fWeightTensorSize*=(std::size_t)(PyArray_DIM(fWeightTensorValue,j));
923 switch(fWeightDType){
925 float* fWeightArray = (
float*)PyArray_DATA(fWeightTensorValue);
926 std::shared_ptr<void> fData(
malloc(fWeightTensorSize *
sizeof(
float)),
free);
927 std::memcpy(fData.get(),fWeightArray, fWeightTensorSize *
sizeof(
float));
932 throw std::runtime_error(
"Type error: TMVA SOFIE does not yet weight data layer type"+
ConvertTypeToString(fWeightDType));
941 PyRunString(
"inputNames=model.input_names",fGlobalNS,fLocalNS);
942 PyRunString(
"inputShapes=model.input_shape if type(model.input_shape)==list else [model.input_shape]",fGlobalNS,fLocalNS);
944 PyRunString(
"for idx in range(len(model.inputs)):\n"
945 " inputTypes.append(model.inputs[idx].dtype.__str__()[9:-2])",fGlobalNS,fLocalNS);
951 std::string fInputName;
958 if(PyTuple_Check(fPInputShapes)){
967 std::vector<size_t>fInputShape = GetDataFromTuple(fPInputShapes);
968 if (
static_cast<int>(fInputShape[0]) <= 0){
970 std::cout <<
"Model has not a defined batch size, assume is 1 - input shape : "
979 throw std::runtime_error(
"Type error: TMVA SOFIE does not yet support data type"+
ConvertTypeToString(fInputDType));
987 for(
Py_ssize_t inputIter = 0; inputIter < PyList_Size(fPInputs);++inputIter){
994 PyObject* fInputShapeTuple=PyList_GetItem(fPInputShapes,inputIter);
996 std::vector<size_t>fInputShape = GetDataFromTuple(fInputShapeTuple);
997 if (
static_cast<int>(fInputShape[0]) <= 0){
999 std::cout <<
"Model has not a defined batch size, assume is 1 - input shape for tensor "
1008 throw std::runtime_error(
"Type error: TMVA SOFIE does not yet support data type"+
ConvertTypeToString(fInputDType));
1018 PyRunString(
"for layerName in model.output_names:\n"
1019 " outputNames.append(model.get_layer(layerName).output.name)",fGlobalNS,fLocalNS);
1021 std::vector<std::string> fOutputNames;
1022 for(
Py_ssize_t outputIter = 0; outputIter < PyList_Size(fPOutputs);++outputIter){
1023 fOutputNames.push_back(
PyStringAsString(PyList_GetItem(fPOutputs,outputIter)));
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 filename
void AddBlasRoutines(std::vector< std::string > routines)
void AddNeededStdLib(std::string libname)
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 AddInputTensorName(std::string name)
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.
static PyObject * GetValueFromDict(PyObject *dict, const char *key)
Utility function which checks if a given key is present in a Python dictionary object and returns the...
void PyRunString(TString code, TString errorMessage="Failed to run python code", int start=256)
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 > MakeKerasConv(PyObject *fLayer)
Prepares a ROperator object for Keras Conv Layer.
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
std::unique_ptr< ROperator > MakeKerasBatchNorm(PyObject *fLayer)
Prepares a ROperator object for Keras BatchNorm layer.
std::unique_ptr< ROperator > MakeKerasSwish(PyObject *fLayer)
Prepares a ROperator object for Keras Swish activation.
void AddKerasLayer(RModel &rmodel, PyObject *fLayer)
Adds equivalent ROperator with respect to Keras model layer into the referenced RModel object.
std::unique_ptr< ROperator > MakeKerasConcat(PyObject *fLayer)
Prepares a ROperator object for Keras Concat layer.
std::unique_ptr< ROperator > MakeKerasLeakyRelu(PyObject *fLayer)
Prepares a ROperator object for Keras Leaky Relu activation.
std::unique_ptr< ROperator > MakeKerasDense(PyObject *fLayer)
Prepares a ROperator object for Keras Dense Layer.
std::unique_ptr< ROperator > MakeKerasBinary(PyObject *fLayer)
Prepares a ROperator object for Keras binary operations like Add, subtract, and multiply.
std::unique_ptr< ROperator > MakeKerasTanh(PyObject *fLayer)
Prepares a ROperator object for Keras Tanh activation.
std::unique_ptr< ROperator > MakeKerasSoftmax(PyObject *fLayer)
Prepares a ROperator object for Keras Softmax activation.
std::unique_ptr< ROperator > MakeKerasReshape(PyObject *fLayer)
Prepares a ROperator object for Keras Reshape 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 > MakeKerasIdentity(PyObject *fLayer)
Prepares a ROperator object for Keras Identity and Dropout Layer.
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 PyObject *(&) GetValueFromDict(PyObject *, const char *)
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