Пример #1
0
def _parse_onnx_api(topology, model, inputs):
    """
    This function handles all input ONNX models.

    Args:
        topology: The ``onnxconverter_common.topology.Topology`` where the model will be added
        model: A ONNX model object
        inputs: A list of `onnxconverter_common.topology.Variable`s

    Returns:
        A list of output `onnxconverter_common.topology.Variable` which will be passed to next stage
    """
    if isinstance(model, str):
        raise RuntimeError("Parameter model must be an object not a " "string '{0}'.".format(model))

    # Parse an ONNX-ML model into our internal data structure (i.e., LinkedNode)
    graph = model.graph
    inputs_names = [in_.raw_name for in_ in inputs]
    output_names = [] if graph.output is None else [o_.name for o_ in graph.output]
    initializers = [] if graph.initializer is None else [in_ for in_ in graph.initializer]
    node_list = LinkedNode.build_from_onnx(graph.node, [], inputs_names + [in_.name for in_ in initializers], output_names)

    # This a new node list but with some node been removed plus eventual variable renaming.
    new_node_list = _remove_zipmap(node_list)

    # Add each operator in the LinkedNode data structure to the topology.
    for node in new_node_list:
        _parse_onnx_single_operator(topology, node)
Пример #2
0
def _convert_onnxml(model, test_input=None, extra_config={}):
    """
    This function converts the specified [ONNX-ML] model into its [ONNX] counterpart.
    The supported operators can be found at `hummingbird.ml.supported`.
    The ONNX-ML converter requires either a test_input of a the initial types set through the exta_config parameter.
    [ONNX-ML]: https://github.com/onnx/onnx/blob/master/docs/Operators-ml.md
    [ONNX]: https://github.com/onnx/onnx/blob/master/docs/Operators.md

    Args:
        model: A model containing ONNX-ML operators
        test_input: Some input data used to trace the model execution.
                    For the ONNX backend the test_input size is supposed to be as large as the expected batch size.
        extra_config: Extra configurations to be used by the individual operator converters.
                      The set of supported extra configurations can be found at `hummingbird.ml.supported`

    Examples:
        extra_config = {}
        extra_config[constans.ONNX_INITIAL_TYPES] =[('input', FloatTensorType([1, 20])]
        >>> onnx_model = _convert_onnxml(onnx_ml_model, None, extra_config)

    Returns:
        A model containing only *ONNX* operators. The mode is equivalent to the input *ONNX-ML* model
    """
    assert model is not None
    assert torch_installed(), "To use Hummingbird you need to install torch."
    assert (
        onnx_runtime_installed()
    ), "To use the onnxml converter you need to install onnxruntime (or `pip install hummingbird-ml[onnx]`)."

    output_model_name = initial_types = input_names = output_names = None
    target_opset = 9

    # Set optional configuration options if any.
    if constants.ONNX_OUTPUT_MODEL_NAME in extra_config:
        output_model_name = extra_config[constants.ONNX_OUTPUT_MODEL_NAME]
    if constants.ONNX_INITIAL_TYPES in extra_config:
        initial_types = extra_config[constants.ONNX_INITIAL_TYPES]
    if constants.ONNX_INPUT_NAMES in extra_config:
        input_names = extra_config[constants.ONNX_INPUT_NAMES]
    if constants.ONNX_OUTPUT_NAMES in extra_config:
        output_names = extra_config[constants.ONNX_OUTPUT_NAMES]
    if constants.ONNX_TARGET_OPSET in extra_config:
        target_opset = extra_config[constants.ONNX_TARGET_OPSET]

    assert (
        test_input is not None and len(test_input) > 0
    ) or initial_types is not None, "Cannot generate test input data. Either pass some input data or the initial_types"

    from .ir_converters.linked_node import convert as linked_node_converter

    # We modify the model during translation.
    model = deepcopy(model)

    # Parse an ONNX-ML model into our internal data structure (i.e., LinkedNode)
    graph = model.graph
    input_names = input_names if input_names is not None else [in_.name for in_ in graph.input]
    inputs = [in_ for in_ in graph.input if in_.name in input_names]

    assert len(inputs) > 0, "Provided input name does not match with any model's input."
    assert len(inputs) == 1, "Hummingbird currently do not support models with more than 1 input."
    assert initial_types is None or len(initial_types) == 1, "len(initial_types) {} differs from len(inputs) {}.".format(
        len(initial_types), len(inputs)
    )

    if output_names is None:
        output_names = [] if graph.output is None else [o_.name for o_ in graph.output]

    if test_input is None:
        assert (
            not initial_types[0][1].shape is None
        ), "Cannot generate test input data. Initial_types do not contain shape information."
        assert len(initial_types[0][1].shape) == 2, "Hummingbird currently support only inputs with len(shape) == 2."

        from onnxconverter_common.data_types import FloatTensorType, Int32TensorType

        test_input = np.random.rand(initial_types[0][1].shape[0], initial_types[0][1].shape[1])
        extra_config[constants.N_FEATURES] = initial_types[0][1].shape[1]
        if type(initial_types[0][1]) is FloatTensorType:
            test_input = np.array(test_input, dtype=np.float32)
        elif type(initial_types[0][1]) is Int32TensorType:
            test_input = np.array(test_input, dtype=np.int32)
        else:
            raise RuntimeError(
                "Type {} not supported. Please fill an issue on https://github.com/microsoft/hummingbird/.".format(
                    type(initial_types[0][1])
                )
            )

    initializers = [] if graph.initializer is None else [in_ for in_ in graph.initializer]
    onnx_ir = LinkedNode.build_from_onnx(
        graph.node, [], [in_.name for in_ in inputs] + [in_.name for in_ in initializers], output_names
    )

    # Convert the input onnx_ir object into ONNX. The outcome is a model containing only ONNX operators.
    onnx_model = linked_node_converter(
        onnx_ir, inputs, initializers, output_names, test_input, output_model_name, target_opset, extra_config
    )
    return onnx_model