Example #1
0
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
Example #2
0
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
Example #3
0
    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'))
Example #4
0
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
Example #5
0
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
Example #6
0
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
Example #7
0
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()
Example #8
0
    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__")
Example #9
0
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