Example #1
0
def get_all_backend_handlers(opset_dict):
    """ Get a dict of all backend handler classes.
  e.g. {'domain': {'Abs': Abs handler class}, ...}, }.

  :param opset_dict: A dict of opset. e.g. {'domain': version, ...}
  :return: Dict.
  """
    handlers = {}
    for handler in BackendHandler.__subclasses__():
        handler.check_cls()

        domain = handler.DOMAIN
        version = opset_dict[domain]
        handler.VERSION = version

        since_version = 1
        if defs.has(handler.ONNX_OP, domain=handler.DOMAIN):
            try:
                since_version = defs.get_schema(
                    handler.ONNX_OP,
                    domain=handler.DOMAIN,
                    max_inclusive_version=version).since_version
            except RuntimeError:
                warnings.warn(
                    "Fail to get since_version of {} in domain `{}` "
                    "with max_inclusive_version={}. Set to 1.".format(
                        handler.ONNX_OP, handler.DOMAIN, version))
        else:
            warnings.warn("Unknown op {} in domain `{}`.".format(
                handler.ONNX_OP, handler.DOMAIN or "ai.onnx"))
        handler.SINCE_VERSION = since_version
        handlers.setdefault(domain, {})[handler.ONNX_OP] = handler
    return handlers
def get_all_backend_handlers(opset_dict):
    """ Get a dict of all backend handler classes.
    e.g. {'domain': {'Abs': Abs handler class}, ...}, }.

    :param opset_dict: A dict of opset. e.g. {'domain': version, ...}
    :return: Dict.
    """
    handlers = {}
    for handler in BackendHandler.__subclasses__():
        handler.check_cls()

        domain = handler.DOMAIN
        version = opset_dict[domain] if domain in opset_dict else 1
        handler.VERSION = version

        since_version = 1
        if defs.has(handler.ONNX_OP, domain=handler.DOMAIN):
            try:
                since_version = defs.get_schema(  # @IgnoreException
                    handler.ONNX_OP,
                    domain=handler.DOMAIN,
                    max_inclusive_version=version).since_version
            except RuntimeError:
                common.logger.debug("Fail to get since_version of %s in domain `%s` "
                                    "with max_inclusive_version=%s. Set to 1.",
                                    handler.ONNX_OP, handler.DOMAIN, version)
        else:
            common.logger.debug("Unknown op %s in domain `%s`.",
                                handler.ONNX_OP, handler.DOMAIN or "ai.onnx")
        handler.SINCE_VERSION = since_version
        handlers.setdefault(domain, {})[handler.ONNX_OP] = handler
    return handlers
Example #3
0
def get_all_backend_handlers(opset_dict):
    """Get a dict of all backend handler classes.
    e.g. {'domain': {'Abs': Abs handler class}, ...}, }.

    :param opset_dict: A dict of opset. e.g. {'domain': version, ...}
    :return: Dict.
    """
    handlers = {}
    for handler in BackendHandler.__subclasses__():
        handler.check_cls()

        domain = handler.DOMAIN
        version = opset_dict[domain] if domain in opset_dict else 1
        handler.VERSION = version

        since_version = 1
        if defs.has(handler.ONNX_OP, domain=handler.DOMAIN):
            try:
                since_version = defs.get_schema(
                    handler.ONNX_OP,
                    domain=handler.DOMAIN,
                    max_inclusive_version=version,
                ).since_version
            except:
                logger.warning(
                    f"Fail to get since_version of {handler.ONNX_OP} "
                    f"in domain `{handler.DOMAIN}` "
                    f"with max_inclusive_version={version}. Set to 1.")
        else:
            logger.warning(
                f"Unknown op {handler.ONNX_OP} in domain `{handler.DOMAIN}`.")
        handler.SINCE_VERSION = since_version
        handlers.setdefault(domain, {})[handler.ONNX_OP] = handler

    return handlers
Example #4
0
def check_node(node):
    """Checks if a node is legal.

    Inputs:
        node: a NodeProto object.
    Returns:
        None
    An exception is thrown if it does not pass the test.
    """
    # General checks.
    if not isinstance(node, NodeProto):
        raise RuntimeError('You cannot pass an object that is not NodeProto.')
    if not node.op_type:
        raise NameError('NodeProto does not have a proper op_type set.')
    if not node.input and not node.output:
        raise ValueError('NodeProto has zero input and zero output.')
    if not defs.has(node.op_type):
        raise NameError('Node op_type {} not recognized by onnx.'.format(
            node.op_type))
    if not defs.get_schema(node.op_type).verify(node.SerializeToString()):
        raise ValueError(
            'NodeProto of type {} did not pass defs schema check.'.format(
                str(node.op_type)))
    for attr in node.attribute:
        if attr.HasField('t'):
            check_tensor(attr.t)
        elif attr.HasField('tensors'):
            for tensor in attr.tensors:
                check_tensor(tensor)
Example #5
0
def get_all_backend_handlers(opset_dict):
    """ Get a dict of all backend handler classes.
  e.g. {'domain': {'Abs': Abs handler class}, ...}, }.

  :param opset_dict: A dict of opset. e.g. {'domain': version, ...}
  :return: Dict.
  """
    handlers = {}
    for handler in BackendHandler.__subclasses__():
        handler.check_cls()

        domain = handler.DOMAIN
        version = opset_dict[domain] if domain in opset_dict else 1
        handler.VERSION = version

        since_version = 1
        if defs.has(handler.ONNX_OP, domain=handler.DOMAIN):
            try:
                since_version = defs.get_schema(
                    handler.ONNX_OP,
                    domain=handler.DOMAIN,
                    max_inclusive_version=version).since_version
            except RuntimeError:
                # ONNX throws RuntimeError up to 1.8
                common_logging(handler, version)
            except defs.SchemaError:
                # ONNX changed to defs.SchemaError since 1.9
                common_logging(handler, version)
        else:
            common.logger.debug("Unknown op {} in domain `{}`.".format(
                handler.ONNX_OP, handler.DOMAIN or "ai.onnx"))
        handler.SINCE_VERSION = since_version
        handlers.setdefault(domain, {})[handler.ONNX_OP] = handler
    return handlers
Example #6
0
def get_all_frontend_handlers(opset_dict):
    """ Get a dict of all frontend handler classes.
  e.g. {'domain': {'Abs': Abs handler class}, ...}, }.

  :param opset_dict: A dict of opset. e.g. {'domain': version, ...}
  :return: Dict.
  """
    handlers = {}
    for handler in FrontendHandler.__subclasses__():
        handler.check_cls()

        domain = handler.DOMAIN
        version = opset_dict[domain]
        handler.VERSION = version

        since_version = 1
        if handler.ONNX_OP and defs.has(handler.ONNX_OP,
                                        domain=handler.DOMAIN):
            since_version = defs.get_schema(
                handler.ONNX_OP,
                domain=handler.DOMAIN,
                max_inclusive_version=version).since_version
        else:
            warnings.warn("Unknown op {} in domain `{}`. "
                          "Can't check specification by ONNX. "
                          "Please set should_check flag to False "
                          "when call make_node method in handler.".format(
                              handler.ONNX_OP or "Undefined", handler.DOMAIN
                              or "ai.onnx"))
        handler.SINCE_VERSION = since_version

        for tf_op in handler.TF_OP:
            handlers.setdefault(domain, {})[tf_op] = handler
    return handlers
Example #7
0
def get_all_backend_handlers(opset_dict):

    handlers = {}
    for handler in BackendHandler.__subclasses__():
        handler.check_cls()

        domain = handler.DOMAIN
        version = opset_dict[domain]
        handler.VERSION = version

        since_version = 1
        if defs.has(handler.ONNX_OP, domain=handler.DOMAIN):
            try:
                since_version = defs.get_schema(
                    handler.ONNX_OP,
                    domain=handler.DOMAIN,
                    max_inclusive_version=version,
                ).since_version
            except RuntimeError:
                print(
                    "Fail to get since_version of {} in domain `{}` "
                    "with max_inclusive_version={}. Set to 1.".format(
                        handler.ONNX_OP, handler.DOMAIN, version
                    )
                )
        else:
            print(
                "Unknown op {} in domain `{}`.".format(
                    handler.ONNX_OP, handler.DOMAIN or "ai.onnx"
                )
            )
        handler.SINCE_VERSION = since_version
        handlers.setdefault(domain, {})[handler.ONNX_OP] = handler
    return handlers
Example #8
0
    def add(self, node):
        assert self.op_type in [None, node.op_type]

        if self.op_type is None:
            self.op_type = node.op_type
            self.schema = defs.get_schema(self.op_type)

        for attr in node.attribute:
            self.attr_coverages[attr.name].add(attr)
Example #9
0
    def add(self, node):  # type: (onnx.NodeProto) -> None
        assert self.op_type in [None, node.op_type]

        if self.op_type is None:
            self.op_type = node.op_type
            assert self.op_type is not None
            self.schema = defs.get_schema(self.op_type)

        for attr in node.attribute:
            self.attr_coverages[attr.name].add(attr)
Example #10
0
    def add(self, node):  # type: (onnx.NodeProto) -> None
        assert self.op_type in [None, node.op_type]

        if self.op_type is None:
            self.op_type = node.op_type
            assert self.op_type is not None
            self.schema = defs.get_schema(self.op_type)

        for attr in node.attribute:
            self.attr_coverages[attr.name].add(attr)
Example #11
0
    def _annotate_consumed(cls, graph_def):
        for node in graph_def.node:
            schema = defs.get_schema(node.op_type)
            consumes = []
            for i, _input_name in enumerate(node.input):
                consume_type, output_idx = schema.consumed(i)
                if consume_type == defs.OpSchema.UseType.CONSUME_ENFORCED:
                    consumes.append(1)
                else:
                    consumes.append(0)

            if any(consumes):
                node.attribute.extend([helper.make_attribute(
                    'consumed_inputs',
                    consumes,
                )])
Example #12
0
    def _annotate_consumed(cls, graph_def):
        for node in graph_def.node:
            schema = defs.get_schema(node.op_type)
            consumes = []
            for i, input_name in enumerate(node.input):
                consume_type, output_idx = schema.consumed(i)
                if consume_type == defs.OpSchema.UseType.CONSUME_ENFORCED:
                    consumes.append(1)
                else:
                    consumes.append(0)

            if any(consumes):
                consumes_attr = AttributeProto()
                consumes_attr.name = "consumed_inputs"
                consumes_attr.ints.extend(consumes)
                node.attribute.extend([consumes_attr])
Example #13
0
    def test_typecheck(self):
        schema = defs.get_schema("Conv")

        # kernels should be [int]
        node_def = helper.make_node(op_type="Conv",
                                    inputs=["X", "w"],
                                    outputs=["Y"],
                                    name="test",
                                    kernel_shape=["a"])
        self.assertFalse(defs.verify(schema, node_def))

        node_def = helper.make_node(op_type="Conv",
                                    inputs=["X", "w"],
                                    outputs=["Y"],
                                    name="test",
                                    kernel_shape=[1, 2])
        self.assertTrue(defs.verify(schema, node_def))
Example #14
0
 def test_get_schema(self) -> None:
     defs.get_schema("Relu")
Example #15
0
 def test_attr_default_value(self) -> None:
     v = defs.get_schema(
         "BatchNormalization").attributes['epsilon'].default_value
     self.assertEqual(type(v), AttributeProto)
     self.assertEqual(v.type, AttributeProto.FLOAT)
Example #16
0
 def test_typecheck(self) -> None:
     defs.get_schema("Conv")
Example #17
0
 def test_verify(self):
     schema = defs.get_schema("Relu")
     node_def = helper.make_node("Relu", ["X"], ["Y"], name="test")
     self.assertTrue(defs.verify(schema, node_def))
Example #18
0
def generate_onnx_node(node, graph):
    """
    Convert an MDF node into an ONNX node.
    Takes an MDF node, MDF graph and returns the ONNX node, any inputs to the node coming from  outside the graph,
    any outputs from the node going outside the graph, and an initializer for constants
    """

    onnx_graph_inputs = []
    onnx_graph_outputs = []
    onnx_initializer = []

    sender_port_name = {}  # Names of ports that send values to this node

    # Go over all parameters
    # Assumption: there may be multiple parameters but there will only be one function.
    # If there are multiple functions, the code should change so that each function should become its own node.
    for param in node.parameters:
        # If this is a constant
        if param.value:
            # Create a constant onnx node
            name = node.id + "_" + param.id
            constant = helper.make_tensor(name,
                                          data_type=TensorProto.FLOAT,
                                          dims=[],
                                          vals=[param.value])
            onnx_initializer.append(constant)
            # The following will be the sender port from the constant onnx node for this parameter
            sender_port_name[param.id] = name
        elif param.function:
            # This is a function and will be part of an onnx node corresponding to this MDF node
            function_name = param.function

            onnx_function_prefix = "onnx::"
            pattern = re.compile(onnx_function_prefix)
            if re.match(pattern, function_name):
                # This is an onnx function
                function_name = function_name[len(onnx_function_prefix):]
                # Get the arguments that this onnx function expects
                schema = get_schema(function_name)
                # The MDF description would have specified all the expected arguments of ths function
                function_input_names = [
                    param.args[arg.name] for arg in schema.inputs
                ]
            else:
                # Error
                raise "Cannot generate onnx function for the unknown function: {} specfied in the MDF node {}".format(
                    function_name,
                    node.id,
                )

    # Find the inputs to the new ONNX node. These are the senders of the in edges to this node
    node_in_edges = [edge for edge in graph.edges if edge.receiver == node.id]
    for in_edge in node_in_edges:
        sender_port_name[in_edge.receiver_port] = (in_edge.sender + "_" +
                                                   in_edge.sender_port)

    onnx_node_input_names = [
        sender_port_name[function_input_name]
        if function_input_name in sender_port_name else function_input_name
        for function_input_name in function_input_names
    ]

    # No parameters. Constants became their own nodes earlier
    onnx_node_parameters = {}

    # Find the outputs of the new ONNX node. These are the output ports of the node
    onnx_node_output_names = [
        node.id + "_" + port.id for port in node.output_ports
    ]

    # print(node.id, node_in_edges,node_out_edges)
    # print(function_name, onnx_node_input_names, onnx_node_output_names)

    # Create an ONNX node
    onnx_node = helper.make_node(
        function_name,
        onnx_node_input_names,
        onnx_node_output_names,
        name=node.id,
        **onnx_node_parameters,
    )

    # Check if any of the node's inputs are the inputs to the ONNX graph itself.
    # These are the node's inputs that don't have an incoming edge.
    input_ports_with_edge = [
        in_edge.receiver_port for in_edge in node_in_edges
    ]
    input_ports_without_edge = [
        input_port for input_port in node.input_ports
        if input_port.id not in input_ports_with_edge
    ]
    if input_ports_without_edge:
        # Create ONNX graph input ports
        for input_port in input_ports_without_edge:
            shape = literal_eval(input_port.shape)
            value_info = helper.make_tensor_value_info(input_port.id,
                                                       TensorProto.FLOAT,
                                                       shape)
            onnx_graph_inputs.append(value_info)

    # Check if any of the node's outputs are the outputs of the ONNX graph.
    # These are the node's outputs that don't have an outgoing edge
    node_out_edges = [edge for edge in graph.edges if edge.sender == node.id]

    output_ports_with_edge = [
        out_edge.sender_port for out_edge in node_out_edges
    ]
    output_ports_without_edge = [
        output_port for output_port in node.output_ports
        if output_port.id not in output_ports_with_edge
    ]
    if output_ports_without_edge:
        # Create ONNX graph output ports
        for output_port in output_ports_without_edge:
            # No need to create output shapes because they are inferred by ONNX
            value_info = helper.make_empty_tensor_value_info(node.id + "_" +
                                                             output_port.id)
            onnx_graph_outputs.append(value_info)
    # print("Graph ip op", input_ports_without_edge, output_ports_without_edge)

    return onnx_node, onnx_graph_inputs, onnx_graph_outputs, onnx_initializer
Example #19
0
 def test_get_schema(self):  # type: () -> None
     defs.get_schema("Relu")
Example #20
0
 def test_get_schema(self):
     defs.get_schema("Relu")
Example #21
0
def onnx_node_to_mdf(node: typing.Union[onnx.NodeProto, onnx.ValueInfoProto],
                     onnx_initializer: typing.Dict[str, typing.Dict[str, typing.Any]]) -> Node:
    """
    Construct an MDF node (and function) from an ONNX NodeProto or ValueInfoProto

    Args:
        node: The ONNX node to use to form the MDF node. Can be a node from the model or
            a ValueInfoProto specifying an input or output.
        onnx_initializer: A specification of values in the graph that ONNX has
            marked as initializer's. This dict is keyed on the name of the parameter,
            the value is another dict with two entries:
                - 'shape': The shape of the parameter
                - 'type': The data type of the parameter
                - 'value': The actual value if present.

    Returns:
        The equivalent MDF node for the ONNX node passed in as argument.
    """

    # If this is a ONNX Node,
    if type(node) == onnx.NodeProto:

        # Create and MDF node with parameters
        # FIXME: We need to preserve type info somewhere
        params_dict = {a.name: get_onnx_attribute(a) for a in node.attribute}

        # For any attributes that are sub-graphs, we need to recurse
        for aname, val in params_dict.items():
            if type(val) == GraphProto:
                params_dict[aname] = onnx_to_mdf(val, onnx_initializer=onnx_initializer)

        # If we have we have value constants that feed into this node. Make them parameters
        # instead of input ports
        non_constant_inputs = []
        for inp_i, inp in enumerate(node.input):
            if inp in onnx_initializer and 'value' in onnx_initializer[inp]:

                # Get the name of the formal argument that corresponds to this input.
                # We need to go to the schema for this.
                # FIXME: We need to make sure we are going the correct schema here ... yuck!
                arg_name = get_schema(node.op_type).inputs[inp_i].name

                params_dict[arg_name] = onnx_initializer[inp]['value']
            else:
                non_constant_inputs.append(inp)

        # FIXME: parameters must be set or we get JSON serialization error later
        mdf_node = Node(id=node.name, parameters=params_dict) if bool(params_dict) else Node(id=node.name)

        # Add the function
        # FIXME: There is probably more stuff we need to preserve for ONNX Ops
        func = Function(id=node.name, function=node.op_type)
        mdf_node.functions.append(func)

        # Recreate inputs and outputs of ONNX node as InputPorts and OutputPorts
        for inp in non_constant_inputs:
            param_info = onnx_initializer.get(inp, None)
            shape = param_info['shape'] if param_info else ""
            ip = InputPort(id=inp, shape=shape)
            mdf_node.input_ports.append(ip)

        for out in node.output:
            op = OutputPort(id=out, value=func.get_id())
            mdf_node.output_ports.append(op)

    elif type(node) == onnx.ValueInfoProto:
        raise NotImplementedError()
        # # Lets start with an MDF node that uses the ONNX node name as its id. No parameters
        # mdf_node = Node(id=node.name)
        #
        # # This is an input or output node. No Op\Function or parameters. This is just
        # # a simple pass through node with an input and output port with the correct
        # # shape.
        # # FIXME: Should this be necessary? ONNX treats input and output nodes as simple named values.
        # ip1 = InputPort(id=f"in_port",
        #                 shape=str(get_shape_params(node.type.tensor_type.shape))) # FIXME: Why string?
        # mdf_node.input_ports.append(ip1)
        # op1 = OutputPort(id=node.name)
        # op1.value = f"in_port"
        # mdf_node.output_ports.append(op1)

    return mdf_node
Example #22
0
 def test_typecheck(self):  # type: () -> None
     defs.get_schema("Conv")
Example #23
0
 def test_typecheck(self):  # type: () -> None
     defs.get_schema("Conv")
Example #24
0
 def test_attr_default_value(self):  # type: () -> None
     v = defs.get_schema(
         "BatchNormalization").attributes['epsilon'].default_value
     self.assertEqual(type(v), AttributeProto)
     self.assertEqual(v.type, AttributeProto.FLOAT)
Example #25
0
 def test_get_schema(self):  # type: () -> None
     defs.get_schema("Relu")