def parse_sparkml_api_model(model, extra_config={}): """ Puts *Spark-ML* object into an abstract representation so that our framework can work seamlessly on models created with different machine learning tools. Args: model: A model object in Spark-ML format Returns: A `onnxconverter_common.topology.Topology` object representing the input model """ assert model is not None, "Cannot convert a mode of type None." raw_model_container = CommonSparkMLModelContainer(model) # Declare a computational graph. It will become a representation of # the input Spark-ML model after parsing. topology = Topology(raw_model_container) # Declare an object to provide variables' and operators' naming mechanism. # One global scope is enough for parsing Spark-ML models. scope = topology.declare_scope("__root__") # Declare input variables. inputs = _declare_input_variables(scope, raw_model_container, extra_config) # Parse the input Spark-ML model into its scope with the topology. # Get the outputs of the model. current_op_outputs, _ = _parse_sparkml_api(scope, model, inputs) # Declare output variables. _declare_output_variables(raw_model_container, extra_config, current_op_outputs) return topology
def parse_aad(model, initial_types=None, target_opset=None, custom_conversion_functions=None, custom_shape_calculators=None): raw_model_container = AadModelContainer(model) topology = Topology( raw_model_container, default_batch_size='None', initial_types=initial_types, target_opset=target_opset, custom_conversion_functions=custom_conversion_functions, custom_shape_calculators=custom_shape_calculators) scope = topology.declare_scope('__root__') inputs = [] for var_name, initial_type in initial_types: inputs.append(scope.declare_local_variable(var_name, initial_type)) for variable in inputs: raw_model_container.add_input(variable) outputs = _parse_aad(scope, model, inputs) for variable in outputs: raw_model_container.add_output(variable) return topology
def test_op_only(self): topo = Topology(_SimpleRawModelContainer(self.inputs, self.outputs)) scope = topo.declare_scope('__ROOT__') container = ModelComponentContainer(target_opset=7) with OnnxOperatorBuilder(container, scope).as_default('node_bn') as oopb: build_graph(oopb, self.inputs, self.outputs) self.assertEqual(len(container.nodes), GRAPH_NODES) self.assertEqual(len(container.initializers), 2) self.assertTrue(container.nodes[0].name.startswith('node_bn'))
def create_conversion_topology(input_names, output_names): GRAPH_OPERATOR_NAME = '__test_graph__' raw_model = _SimpleRawModelContainer(input_names, output_names) def on_conversion(scope, operator, container): with OnnxOperatorBuilder(container, scope).as_default('node_bn') as oopb: build_graph(oopb, container.inputs, container.outputs) register_converter(GRAPH_OPERATOR_NAME, on_conversion, overwrite=True) topo = Topology(raw_model) top_level = topo.declare_scope('__root__') top_level.declare_local_operator(GRAPH_OPERATOR_NAME) return topo
def parse_onnx_api_model(model): """ Puts *ONNX* object into an abstract representation so that our framework can work seamlessly on models created with different machine learning tools. Args: model: A model object in onnx format Returns: A `onnxconverter_common.topology.Topology` object representing the input model """ assert model is not None, "Cannot convert a mode of type None." raw_model_container = CommonONNXModelContainer(model) # We modify the ONNX model during translation model = deepcopy(model) # Declare a computational graph. It will become a representation of # the input ONNX model after parsing. topology = Topology(raw_model_container) # Declare an object to provide variables' and operators' naming mechanism. # One global scope is enough for parsing ONNX models. scope = topology.declare_scope("__root__") # Declare input variables. inputs = [] for i in model.graph.input: inputs.append(scope.declare_local_variable(i.name)) # The object raw_model_container is a part of the topology we're going to return. # We use it to store the inputs of the ONNX graph. for variable in inputs: raw_model_container.add_input(variable) # Parse the input ONNX model into its scope with the topology. _parse_onnx_api(scope, model, inputs) # The object raw_model_container is a part of the topology we're going to return. # We use it to store the output_names of the ONNX graph. for o in model.graph.output: raw_model_container.add_output(scope.declare_local_variable(o.name)) return topology
def parse_sklearn_api_model(model): """ Puts *scikit-learn* object into an abstract representation so that our framework can work seamlessly on models created with different machine learning tools. Args: model: A model object in scikit-learn format Returns: A `onnxconverter_common.topology.Topology` object representing the input model """ assert model is not None, "Cannot convert a mode of type None." raw_model_container = CommonSklearnModelContainer(model) # Declare a computational graph. It will become a representation of # the input scikit-learn model after parsing. topology = Topology(raw_model_container) # Declare an object to provide variables' and operators' naming mechanism. # One global scope is enough for parsing scikit-learn models. scope = topology.declare_scope("__root__") # Declare input variables. Sklearn always gets as input a single dataframe, # therefore by default we start with a single `input` variable inputs = [] inputs.append(scope.declare_local_variable("input")) # The object raw_model_container is a part of the topology we're going to return. # We use it to store the inputs of the scikit-learn's computational graph. for variable in inputs: raw_model_container.add_input(variable) # Parse the input scikit-learn model into its scope with the topology. # Get the outputs of the model. outputs = _parse_sklearn_api(scope, model, inputs) # The object raw_model_container is a part of the topology we're going to return. # We use it to store the outputs of the scikit-learn's computational graph. for variable in outputs: raw_model_container.add_output(variable) return topology
class Topology: def __init__(self, input_container): self.onnxconverter_topology = ONNXTopology(input_container) # Declare an object to provide variables' and operators' naming mechanism. # One global scope is enough for parsing Hummingbird's supported input models. self.scope = self.onnxconverter_topology.declare_scope("__root__") @property def input_container(self): """ Returns the input container wrapping the original input model. """ return self.onnxconverter_topology.raw_model @property def variables(self): """ Returns all the logical variables of the topology. """ return self.scope.variables def declare_logical_variable(self, original_input_name, type=None): """ This function creates a new logical variable within the topology. If original_input_name has been used to create other variables, the new variable will hide all other variables created using original_input_name. """ return self.scope.declare_local_variable(original_input_name, type=type) def declare_logical_operator(self, alias, model=None): """ This function is used to declare new logical operator. """ return self.scope.declare_local_operator(alias, model) def topological_operator_iterator(self): """ This is an iterator of all operators in the Topology object. Operators are returned in a topological order. """ return self.onnxconverter_topology.topological_operator_iterator()
def __init__(self, input_container): self.onnxconverter_topology = ONNXTopology(input_container) # Declare an object to provide variables' and operators' naming mechanism. # One global scope is enough for parsing Hummingbird's supported input models. self.scope = self.onnxconverter_topology.declare_scope("__root__")
def parse_sklearn_api_model(model, extra_config={}): """ Puts *scikit-learn* object into an abstract representation so that our framework can work seamlessly on models created with different machine learning tools. Args: model: A model object in scikit-learn format Returns: A `onnxconverter_common.topology.Topology` object representing the input model """ assert model is not None, "Cannot convert a mode of type None." raw_model_container = CommonSklearnModelContainer(model) # Declare a computational graph. It will become a representation of # the input scikit-learn model after parsing. topology = Topology(raw_model_container) # Declare an object to provide variables' and operators' naming mechanism. # One global scope is enough for parsing scikit-learn models. scope = topology.declare_scope("__root__") # Declare input variables. inputs = [] n_inputs = extra_config[ constants.N_INPUTS] if constants.N_INPUTS in extra_config else 1 if constants.INPUT_NAMES in extra_config: assert n_inputs == len(extra_config[constants.INPUT_NAMES]) if constants.TEST_INPUT in extra_config: from onnxconverter_common.data_types import FloatTensorType, DoubleTensorType, Int32TensorType, Int64TensorType test_input = extra_config[constants.TEST_INPUT] if n_inputs > 1 else [ extra_config[constants.TEST_INPUT] ] for i in range(n_inputs): input = test_input[i] input_name = (extra_config[constants.INPUT_NAMES][i] if constants.INPUT_NAMES in extra_config else "input_{}".format(i)) if input.dtype == np.float32: input_type = FloatTensorType(input.shape) elif input.dtype == np.float64: input_type = DoubleTensorType(input.shape) elif input.dtype == np.int32: input_type = Int32TensorType(input.shape) elif input.dtype == np.int64: input_type = Int64TensorType(input.shape) else: raise RuntimeError( "Type {} not supported. Please fill an issue on https://github.com/microsoft/hummingbird/." .format(type(input.dtype))) inputs.append( scope.declare_local_variable(input_name, type=input_type)) else: # We have no information on the input. Sklearn always gets as input a single dataframe, # therefore by default we start with a single `input` variable input_name = extra_config[constants.INPUT_NAMES][ 0] if constants.TEST_INPUT in extra_config else "input" inputs.append(scope.declare_local_variable(input_name)) # The object raw_model_container is a part of the topology we're going to return. # We use it to store the inputs of the scikit-learn's computational graph. for variable in inputs: raw_model_container.add_input(variable) # Parse the input scikit-learn model into its scope with the topology. # Get the outputs of the model. outputs = _parse_sklearn_api(scope, model, inputs) # Use the output names specified by the user, if any if constants.OUTPUT_NAMES in extra_config: assert len(extra_config[constants.OUTPUT_NAMES]) == len(outputs) for i in range(len(outputs)): outputs[i].raw_name = extra_config[constants.OUTPUT_NAMES][i] # The object raw_model_container is a part of the topology we're going to return. # We use it to store the outputs of the scikit-learn's computational graph. for variable in outputs: raw_model_container.add_output(variable) return topology