Ejemplo n.º 1
0
def _unstrip_tensor(tensor: onnx.TensorProto) -> None:
    meta_dict = {}
    meta_dict_idx = 0
    for i, external_data in enumerate(tensor.external_data):
        if external_data.key != "location":
            continue
        try:
            external_data_dict = json.loads(external_data.value)
            if external_data_dict.get("type", "") == "stripped":
                meta_dict = external_data_dict
                meta_dict_idx = i
                break
        except ValueError:
            continue
    if not meta_dict:
        return None
    ave = meta_dict.get("average", None)
    var = meta_dict.get("variance", None)
    if ave is None or var is None:
        return None

    np_dtype = onnx.mapping.TENSOR_TYPE_TO_NP_TYPE[tensor.data_type]
    dummy_array = numpy.random.normal(ave, math.sqrt(var),
                                      tensor.dims).astype(np_dtype)
    dummy_tensor = onnx.numpy_helper.from_array(dummy_array)
    tensor.data_location = onnx.TensorProto.DEFAULT
    tensor.raw_data = dummy_tensor.raw_data
    del tensor.external_data[meta_dict_idx]
Ejemplo n.º 2
0
def from_array(
        arr,
        name=None):  # type: (np.ndarray[Any], Optional[Text]) -> TensorProto
    """Converts a numpy array to a tensor def.

    Inputs:
        arr: a numpy array.
        name: (optional) the name of the tensor.
    Returns:
        tensor_def: the converted tensor def.
    """
    tensor = TensorProto()
    tensor.dims.extend(arr.shape)
    if name:
        tensor.name = name

    if arr.dtype == np.object:
        # Special care for strings.
        raise NotImplementedError("Need to properly implement string.")
    # For numerical types, directly use numpy raw bytes.
    try:
        dtype = mapping.NP_TYPE_TO_TENSOR_TYPE[arr.dtype]
    except KeyError:
        raise RuntimeError("Numpy data type not understood yet: {}".format(
            str(arr.dtype)))
    tensor.data_type = dtype
    tensor.raw_data = arr.tobytes()  # note: tobytes() is only after 1.9.

    return tensor
Ejemplo n.º 3
0
def to_array(tensor: TensorProto, base_dir: str = "") -> np.ndarray:
    """Converts a tensor def object to a numpy array.

    Inputs:
        tensor: a TensorProto object.
        base_dir: if external tensor exists, base_dir can help to find the path to it
    Returns:
        arr: the converted array.
    """
    if tensor.HasField("segment"):
        raise ValueError("Currently not supporting loading segments.")
    if tensor.data_type == TensorProto.UNDEFINED:
        raise TypeError("The element type in the input tensor is not defined.")

    tensor_dtype = tensor.data_type
    np_dtype = mapping.TENSOR_TYPE_TO_NP_TYPE[tensor_dtype]
    storage_type = mapping.TENSOR_TYPE_TO_STORAGE_TENSOR_TYPE[tensor_dtype]
    storage_np_dtype = mapping.TENSOR_TYPE_TO_NP_TYPE[storage_type]
    storage_field = mapping.STORAGE_TENSOR_TYPE_TO_FIELD[storage_type]
    dims = tensor.dims

    if tensor.data_type == TensorProto.STRING:
        utf8_strings = getattr(tensor, storage_field)
        ss = list(s.decode('utf-8') for s in utf8_strings)
        return np.asarray(ss).astype(np_dtype).reshape(dims)

    # Load raw data from external tensor if it exists
    if uses_external_data(tensor):
        load_external_data_for_tensor(tensor, base_dir)

    if tensor.HasField("raw_data"):
        # Raw_bytes support: using frombuffer.
        if sys.byteorder == 'big':
            # Convert endian from little to big
            convert_endian(tensor)

        # manually convert bf16 since there's no numpy support
        if tensor_dtype == TensorProto.BFLOAT16:
            data = np.frombuffer(tensor.raw_data, dtype=np.int16)
            return bfloat16_to_float32(data, dims)

        return np.frombuffer(tensor.raw_data, dtype=np_dtype).reshape(dims)
    else:
        # float16 is stored as int32 (uint16 type); Need view to get the original value
        if tensor_dtype == TensorProto.FLOAT16:
            return (np.asarray(tensor.int32_data,
                               dtype=np.uint16).reshape(dims).view(np.float16))

        # bfloat16 is stored as int32 (uint16 type); no numpy support for bf16
        if tensor_dtype == TensorProto.BFLOAT16:
            data = np.asarray(tensor.int32_data, dtype=np.int32)
            return bfloat16_to_float32(data, dims)

        data = getattr(tensor, storage_field)
        if (tensor_dtype == TensorProto.COMPLEX64
                or tensor_dtype == TensorProto.COMPLEX128):
            data = combine_pairs_to_complex(data)

        return (np.asarray(
            data, dtype=storage_np_dtype).astype(np_dtype).reshape(dims))
Ejemplo n.º 4
0
def fill_zeros_for_external_data(tensor: TensorProto):
    if tensor.HasField("raw_data"):  # already loaded
        return

    value = NumpyHelper.to_array(tensor, fill_zeros=True)
    zero_tensor = numpy_helper.from_array(value, name=tensor.name)
    tensor.raw_data = zero_tensor.raw_data
Ejemplo n.º 5
0
def from_array(arr, name=None):  # type: (np.ndarray[Any], Optional[Text]) -> TensorProto
    """Converts a numpy array to a tensor def.

    Inputs:
        arr: a numpy array.
        name: (optional) the name of the tensor.
    Returns:
        tensor_def: the converted tensor def.
    """
    tensor = TensorProto()
    tensor.dims.extend(arr.shape)
    if name:
        tensor.name = name

    if arr.dtype == np.object:
        # Special care for strings.
        raise NotImplementedError("Need to properly implement string.")
    # For numerical types, directly use numpy raw bytes.
    try:
        dtype = mapping.NP_TYPE_TO_TENSOR_TYPE[arr.dtype]
    except KeyError:
        raise RuntimeError(
            "Numpy data type not understood yet: {}".format(str(arr.dtype)))
    tensor.data_type = dtype
    tensor.raw_data = arr.tobytes()  # note: tobytes() is only after 1.9.

    return tensor
Ejemplo n.º 6
0
def from_bytes(b):
    """
    Retrieves an array from bytes then protobuf.

    @param      b       bytes
    @return             array

    .. exref::
        :title: Converts bytes into an array (serialization)

        Useful to deserialize.

        .. runpython::
            :showcode:

            import numpy
            from mlprodict.onnxrt.onnx2py_helper import to_bytes, from_bytes

            data = numpy.array([[0, 1], [2, 3], [4, 5]], dtype=numpy.float32)
            pb = to_bytes(data)
            data2 = from_bytes(pb)
            print(data2)
    """
    if isinstance(b, bytes):
        pb = TensorProto()
        pb.ParseFromString(b)
    else:
        pb = b
    return to_array(pb)
Ejemplo n.º 7
0
def make_tensor(
        name,  # type: Text
        data_type,  # type: int
        dims,  # type: Sequence[int]
        vals,  # type: Any
        raw=False  # type: bool
):  # type: (...) -> TensorProto
    '''
    Make a TensorProto with specified arguments.  If raw is False, this
    function will choose the corresponding proto field to store the
    values based on data_type. If raw is True, use "raw_data" proto
    field to store the values, and values should be of type bytes in
    this case.
    '''
    tensor = TensorProto()
    tensor.data_type = data_type
    tensor.name = name

    if data_type == TensorProto.STRING:
        assert not raw, "Can not use raw_data to store string type"

    if (data_type == TensorProto.COMPLEX64
            or data_type == TensorProto.COMPLEX128):
        vals = split_complex_to_pairs(vals)
    if raw:
        tensor.raw_data = vals
    else:
        field = mapping.STORAGE_TENSOR_TYPE_TO_FIELD[
            mapping.TENSOR_TYPE_TO_STORAGE_TENSOR_TYPE[data_type]]
        getattr(tensor, field).extend(vals)

    tensor.dims.extend(dims)
    return tensor
Ejemplo n.º 8
0
 def caffe2_op_to_onnx_node(cls, op_def, shapes):
     if C.support_onnx_export(op_def.type):
         shape_list = list(shapes.values())
         node_strs, tensor_strs = C.export_to_onnx(
             op_def.SerializeToString(), shapes)
         nodes = []
         for s in node_strs:
             node = NodeProto()
             node.ParseFromString(s)
             nodes.append(node)
         const_tensors = []
         for s in tensor_strs:
             tensor = TensorProto()
             tensor.ParseFromString(s)
             const_tensors.append(tensor)
         return nodes, const_tensors
     elif op_def.type in cls._special_operators:
         translator = getattr(cls, cls._special_operators[op_def.type])
     else:
         translator = cls._common_caffe2_op_to_onnx_node
     nodes = translator(op_def, shapes)
     const_tensors = []
     if isinstance(nodes, tuple):
         nodes, const_tensors = nodes
     if not isinstance(nodes, collections.Iterable):
         nodes = [nodes]
     return nodes, const_tensors
Ejemplo n.º 9
0
def load_data(folder):
    """
    Restores protobuf data stored in a folder.

    :param folder: folder
    :return: dictionary
    """
    res = OrderedDict()
    res['in'] = OrderedDict()
    res['out'] = OrderedDict()
    files = os.listdir(folder)
    for name in files:
        noext, ext = os.path.splitext(name)
        if ext == '.pb':
            data = TensorProto()
            with open(os.path.join(folder, name), 'rb') as f:
                data.ParseFromString(f.read())
            if noext.startswith('input'):
                res['in'][noext] = numpy_helper.to_array(data)
            elif noext.startswith('output'):
                res['out'][noext] = numpy_helper.to_array(data)
            else:
                raise ValueError(  # pragma: no cover
                    "Unable to guess anything about %r." % noext)

    return res
Ejemplo n.º 10
0
def from_array(value, name=None):
    """
    Converts an array into an ONNX tensor.

    :param value: numpy array
    :return: ONNX tensor
    """
    if isinstance(value, numpy.ndarray):
        try:
            pb = onnx_from_array(value, name=name)
        except NotImplementedError as e:  # pragma: no cover
            if value.dtype == numpy.dtype('O'):
                pb = TensorProto()
                pb.data_type = TensorProto.STRING  # pylint: disable=E1101
                if name is not None:
                    pb.name = name
                pb.dims.extend(value.shape)  # pylint: disable=E1101
                pb.string_data.extend(  # pylint: disable=E1101
                    list(map(lambda o: str(o).encode('utf-8'), value.ravel())))
            else:
                raise NotImplementedError(
                    "Unable to convert type %r (dtype=%r) into an ONNX tensor "
                    "due to %r." % (type(value), value.dtype, e)) from e
        return pb
    if isinstance(value, TensorProto):  # pragma: no cover
        return value
    raise NotImplementedError(  # pragma: no cover
        "Unable to convert type %r into an ONNX tensor." % type(value))
Ejemplo n.º 11
0
    def _add_constant_tensor(self, tensor: onnx.TensorProto):
        if not tensor.HasField("name"):
            raise ValueError("Got tensor without name")

        if not tensor.HasField("data_type"):
            raise ValueError("Initializer tensor '{}' has no type".format(
                tensor.name))

        name = clean_onnx_name(tensor.name)

        dtype = onnx_tensor_type_to_typeclass(tensor.data_type)

        if len(tensor.dims) == 0:
            # this is a scalar
            self.sdfg.add_scalar(name, dtype)
        else:
            dims = [d for d in tensor.dims]
            if name not in self.sdfg.arrays:
                self.sdfg.add_array(name, dims, dtype)
            else:
                existing_arr = self.sdfg.arrays[name]
                if existing_arr.dtype != dtype:
                    raise ValueError(
                        "Invalid ONNX model; found two values with name '{}', but different dtypes ({} and {})"
                        .format(name, existing_arr.dtype, dtype))
                if tuple(existing_arr.shape) != tuple(dims):
                    raise ValueError(
                        "Invalid ONNX model; found two values with name '{}', but different dimensions ({} and {})"
                        .format(name, existing_arr.shape, dims))

        self.weights[tensor.name] = numpy_helper.to_array(tensor)
Ejemplo n.º 12
0
def make_tensor(
        name,  # type: Text
        data_type,  # type: TensorProto.DataType
        dims,  # type: Sequence[int]
        vals,  # type: Any
        raw=False  # type: bool
):  # type: (...) -> TensorProto
    '''
    Make a TensorProto with specified arguments.  If raw is False, this
    function will choose the corresponding proto field to store the
    values based on data_type. If raw is True, use "raw_data" proto
    field to store the values, and values should be of type bytes in
    this case.
    '''
    tensor = TensorProto()
    tensor.data_type = data_type
    tensor.name = name

    if data_type == TensorProto.STRING:
        assert not raw, "Can not use raw_data to store string type"

    if (data_type == TensorProto.COMPLEX64 or
            data_type == TensorProto.COMPLEX128):
        vals = split_complex_to_pairs(vals)
    if raw:
        tensor.raw_data = vals
    else:
        field = mapping.STORAGE_TENSOR_TYPE_TO_FIELD[
            mapping.TENSOR_TYPE_TO_STORAGE_TENSOR_TYPE[data_type]]
        getattr(tensor, field).extend(vals)

    tensor.dims.extend(dims)
    return tensor
Ejemplo n.º 13
0
def make_tensor(
        name: Text,
        data_type: int,
        dims: Sequence[int],
        vals: Any,
        raw: bool = False
) -> TensorProto:
    '''
    Make a TensorProto with specified arguments.  If raw is False, this
    function will choose the corresponding proto field to store the
    values based on data_type. If raw is True, use "raw_data" proto
    field to store the values, and values should be of type bytes in
    this case.

    Arguments:
        name (string): tensor name
        data_type (int): a value such as onnx.TensorProto.FLOAT
        dims (List[int]): shape
        vals: values
        raw (bool): if True, vals contains the seralized content of the tensor,
            otherwise, vals should be a list of values of the type defined by *data_type*

    Returns:
        TensorProto
    '''
    tensor = TensorProto()
    tensor.data_type = data_type
    tensor.name = name

    if data_type == TensorProto.STRING:
        assert not raw, "Can not use raw_data to store string type"

    # Check number of vals specified equals tensor size
    expected_size = 1 if (not raw) else (mapping.TENSOR_TYPE_TO_NP_TYPE[data_type].itemsize)
    # Flatten a numpy array if its rank > 1
    if type(vals) is np.ndarray and len(vals.shape) > 1:
        vals = vals.flatten()
    for d in dims:
        expected_size = expected_size * d

    if len(vals) != expected_size:
        raise ValueError("Number of values does not match tensor's size. Expected {}, but it is {}. "
            .format(expected_size, len(vals)))

    if raw:
        tensor.raw_data = vals
    else:
        if (data_type == TensorProto.COMPLEX64
                or data_type == TensorProto.COMPLEX128):
            vals = split_complex_to_pairs(vals)
        # floa16/bfloat16 are stored as uint16
        elif (data_type == TensorProto.FLOAT16
                or data_type == TensorProto.BFLOAT16):
            vals = np.array(vals).astype(np.float16).view(dtype=np.uint16).flatten().tolist()
        field = mapping.STORAGE_TENSOR_TYPE_TO_FIELD[
            mapping.TENSOR_TYPE_TO_STORAGE_TENSOR_TYPE[data_type]]
        getattr(tensor, field).extend(vals)
    tensor.dims.extend(dims)
    return tensor
Ejemplo n.º 14
0
def make_external_tensor(name, data_type, dims, raw_data=None, **kwargs):
    tensor = TensorProto()
    tensor.data_type = data_type
    tensor.name = name
    tensor.dims.extend(dims)
    if raw_data is not None:
        tensor.raw_data = raw_data
    external_data_helper.set_external_data(tensor, **kwargs)
    order_repeated_field(tensor.external_data, 'key', kwargs.keys())
    return tensor
Ejemplo n.º 15
0
    def test_check_string_tensor(self):
        tensor = TensorProto()
        tensor.data_type = TensorProto.STRING
        tensor.dims.append(1)
        tensor.string_data.append('Test'.encode('utf-8'))
        checker.check_tensor(tensor)

        del tensor.string_data[:]
        tensor.raw_data = 'Test'.encode('utf-8')
        # string data should not be stored in raw_data field
        self.assertRaises(checker.ValidationError, checker.check_tensor, tensor)
Ejemplo n.º 16
0
    def test_check_string_tensor(self):  # type: () -> None
        tensor = TensorProto()
        tensor.data_type = TensorProto.STRING
        tensor.dims.append(1)
        tensor.string_data.append('Test'.encode('utf-8'))
        checker.check_tensor(tensor)

        del tensor.string_data[:]
        tensor.raw_data = 'Test'.encode('utf-8')
        # string data should not be stored in raw_data field
        self.assertRaises(checker.ValidationError, checker.check_tensor, tensor)
Ejemplo n.º 17
0
def create_onnx_components():
    """创建onnx的基本组件:node, graph, model,可以看到onnx是如何本onnx.proto文件对应的
    参考:https://github.com/onnx/onnx/blob/master/onnx/examples/Protobufs.ipynb
    """
    # ------ 创建int变量: 传入数值和描述即可 ------ 
    arg1 = helper.make_attribute("this is INT", 64)
    
    arg2 = helper.make_attribute("this is float/1", 3.14)
    
    arg3 = helper.make_attribute("this is STRING", "helloworld")
    
    arg4 = helper.make_attribute("this is INTS", [1,2,3,4])
    
    # ------ 创建TensorProto ------
    tensor0 = helper.make_tensor_value_info()   # ?
    
    array1 = np.array([[1,2,3],[4,5,6]])
    tensor1 = numpy_helper.from_array(array1)   # 从numpy获取tensorProto
    
    with open('ts.pb', 'wb') as f:
        f.write(tensor1.SerializeToString())     # 保存tensorProto
    tensor2 = TensorProto()
    with open('ts.pb', 'rb') as f:
        tensor2.ParseFromString(f.read())       # 读取tensorProto
    with
    
    
    # ------ 创建node ------ 
    node1 = helper.make_node("Relu", ["X"], ["Y"])  # op_type="Relu"
    
    node2 = helper.make_node("Conv", ["X", "W", "Y"], kernel=3, stride=1, pad=1)
    print(node2)
    print(helper.printable_node(node2))    # 这就是常看到的onnx形式:%Y = Conv[]
    
    # ------ 创建graph ------ 
    node_list = []
    arg_list = []
    graph1 = helper.make_graph(
    [
        helper.make_node("FC", ["X", "W1", "B1"], ["H1"]),
        helper.make_node("Relu", ["H1"], ["R1"]),
        helper.make_node("FC", ["R1", "W2", "B2"], ["Y"]),
    ],
    "MLP",
    [
        helper.make_tensor_value_info('X' , TensorProto.FLOAT, [1]),
        helper.make_tensor_value_info('W1', TensorProto.FLOAT, [1]),
        helper.make_tensor_value_info('B1', TensorProto.FLOAT, [1]),
        helper.make_tensor_value_info('W2', TensorProto.FLOAT, [1]),
        helper.make_tensor_value_info('B2', TensorProto.FLOAT, [1]),
    ],
    [
        helper.make_tensor_value_info('Y', TensorProto.FLOAT, [1]),
    ])
Ejemplo n.º 18
0
def load_checkpoint_to_model(path_to_checkpoint, model):
    """Loads the checkpoint to an onnx inference model."""

    # Load the parameters from the checkpoint
    parameters = _internal_load_checkpoint(path_to_checkpoint)

    parameters_dict = {}
    for param in parameters:
        param_proto = TensorProto()
        param_proto.ParseFromString(param)
        parameters_dict[param_proto.name] = param_proto

    for initializer in model.graph.initializer:
        initializer.CopyFrom(parameters_dict[initializer.name])
Ejemplo n.º 19
0
    def has_same_value(tensor1: TensorProto, tensor2: TensorProto) -> bool:
        """Returns True when two tensors have same value.
           Note that name can be different.

        Args:
            tensor1 (TensorProto): initializer 1
            tensor2 (TensorProto): initializer 2

        Returns:
            bool: True when two intializers has same value.
        """
        if tensor1.data_type != tensor2.data_type or tensor1.dims != tensor2.dims:
            return False
        if tensor1.HasField("raw_data") and tensor2.HasField("raw_data"):
            return tensor1.raw_data == tensor2.raw_data
        return numpy_helper.to_array(tensor1) == numpy_helper.to_array(tensor2)
Ejemplo n.º 20
0
def make_tensor(name: str, vals: np.ndarray) -> ITensorProto:
    """
    Make a TensorProto with specified arguments.  If raw is False, this
    function will choose the corresponding proto field to store the
    values based on data_type. If raw is True, use "raw_data" proto
    field to store the values, and values should be of type bytes in
    this case.
    """
    vals = vals.astype(np.float32)

    tensor = TensorProto()
    tensor.data_type = DataType.FLOAT
    tensor.name = name
    tensor.raw_data = vals.tobytes()
    tensor.dims.extend(vals.shape)
    return tensor
Ejemplo n.º 21
0
def _strip_raw_data(tensor: onnx.TensorProto) -> onnx.TensorProto:
    arr = onnx.numpy_helper.to_array(tensor)
    meta_dict = {}
    meta_dict['type'] = "stripped"
    meta_dict['average'] = float(arr.mean())  # type: ignore[assignment]
    meta_dict['variance'] = float(arr.var())  # type: ignore[assignment]
    if not tensor.HasField("raw_data"):
        tensor.raw_data = onnx.numpy_helper.from_array(arr,
                                                       tensor.name).raw_data
    onnx.external_data_helper.set_external_data(tensor,
                                                location=json.dumps(meta_dict),
                                                length=arr.nbytes)
    tensor.data_location = onnx.TensorProto.EXTERNAL
    tensor.ClearField('raw_data')
    tensor.ClearField('float_data')
    return tensor
Ejemplo n.º 22
0
def convert_endian(tensor: TensorProto) -> None:
    """
    call to convert endianess of raw data in tensor.
    @params
    TensorProto: TensorProto to be converted.
    """
    tensor_dtype = tensor.data_type
    np_dtype = mapping.TENSOR_TYPE_TO_NP_TYPE[tensor_dtype]
    tensor.raw_data = np.frombuffer(tensor.raw_data,
                                    dtype=np_dtype).byteswap().tobytes()
Ejemplo n.º 23
0
def post_processing(outputs_path, outputs_path_other):
    # Compare outputs with e.g. fp16 and fp32
    record = {}
    if_close = {}

    import glob
    for filename in glob.glob(os.path.join(outputs_path, '*.tensorproto')):
        filename_other = os.path.join(outputs_path_other, Path(filename).name)
        if not os.path.exists(filename_other):
            continue
        with open(filename, 'rb') as f:
            tensor = TensorProto()
            tensor.ParseFromString(f.read())
            array = numpy_helper.to_array(tensor)
            with open(filename_other, 'rb') as f:
                tensor_other = TensorProto()
                tensor_other.ParseFromString(f.read())
                array_other = numpy_helper.to_array(tensor_other)
                if array_other.size == 0:
                    continue
                diff = numpy.average(
                    numpy.abs(array_other - array) /
                    (numpy.abs(array_other) + 1e-6))
                if math.isnan(diff):
                    continue
                record[Path(filename).name.split(".")[0]] = diff
                if_close[Path(filename).name.split(".")[0]] = numpy.allclose(
                    array, array_other, rtol=1e-04, atol=1e-04)

    results = [f"Node\tDiff\tClose"]
    for k, v in sorted(record.items(), key=lambda x: x[1], reverse=True):
        results.append(f"{k}\t{v}\t{if_close[k]}")
    for line in results:
        print(line)
Ejemplo n.º 24
0
def get_test_files(name):
    """Extract tar file and returns model path and input, output data"""
    tar_name = download(URLS.get(name), dirname=CURR_PATH.__str__())
    # extract tar file
    tar_path = os.path.join(CURR_PATH, tar_name)
    tar = tarfile.open(tar_path.__str__(), "r:*")
    tar.extractall(path=CURR_PATH.__str__())
    tar.close()
    data_dir = os.path.join(CURR_PATH, name)
    model_path = os.path.join(data_dir, 'model.onnx')

    inputs = []
    outputs = []
    # get test files
    for test_file in os.listdir(data_dir):
        case_dir = os.path.join(data_dir, test_file)
        # skip the non-dir files
        if not os.path.isdir(case_dir):
            continue
        input_file = os.path.join(case_dir, 'input_0.pb')
        input_tensor = TensorProto()
        with open(input_file, 'rb') as proto_file:
            input_tensor.ParseFromString(proto_file.read())
        inputs.append(numpy_helper.to_array(input_tensor))

        output_tensor = TensorProto()
        output_file = os.path.join(case_dir, 'output_0.pb')
        with open(output_file, 'rb') as proto_file:
            output_tensor.ParseFromString(proto_file.read())
        outputs.append(numpy_helper.to_array(output_tensor))

    return model_path, inputs, outputs
Ejemplo n.º 25
0
    def _add_constant_tensor(self, tensor: onnx.TensorProto, parent_pt_model):
        if not tensor.HasField("name"):
            raise ValueError("Got tensor without name")

        if not tensor.HasField("data_type"):
            raise ValueError("Initializer tensor '{}' has no type".format(
                tensor.name))

        name = clean_onnx_name(tensor.name)

        dtype = onnx_tensor_type_to_typeclass(tensor.data_type)

        if len(tensor.dims) == 0:
            # this is a scalar
            self.sdfg.add_scalar(name, dtype)
        else:
            dims = [d for d in tensor.dims]
            if name not in self.sdfg.arrays:
                self.sdfg.add_array(name, dims, dtype)
            else:
                existing_arr = self.sdfg.arrays[name]
                if existing_arr.dtype != dtype:
                    raise ValueError(
                        "Invalid ONNX model; found two values with name '{}', but different dtypes ({} and {})"
                        .format(name, existing_arr.dtype, dtype))
                if tuple(existing_arr.shape) != tuple(dims):
                    raise ValueError(
                        "Invalid ONNX model; found two values with name '{}', but different dimensions ({} and {})"
                        .format(name, existing_arr.shape, dims))

        weight_arr = numpy_helper.to_array(tensor)

        if parent_pt_model is not None:
            parent_parameters = dict(parent_pt_model.named_parameters())

        if parent_pt_model is not None and tensor.name in parent_parameters:
            self.weights[tensor.name] = parent_parameters[tensor.name].data
        else:
            # we need to copy here because the weight_arr tensor is not writable
            self.weights[tensor.name] = torch.from_numpy(weight_arr.copy())
Ejemplo n.º 26
0
    def test_get_inputs(self):
        model = OnnxModel(model_proto=ModelProto(
            graph=GraphProto(initializer=[TensorProto(name='y')],
                             input=[
                                 ValueInfoProto(name='x'),
                                 ValueInfoProto(name='y'),
                                 ValueInfoProto(name='z')
                             ])),
                          input_data_formats=[None, None])

        self.assertEqual(model.get_inputs(),
                         [ValueInfoProto(name='x'),
                          ValueInfoProto(name='z')])
Ejemplo n.º 27
0
def from_array(
        arr,
        name=None):  # type: (np.ndarray[Any], Optional[Text]) -> TensorProto
    """Converts a numpy array to a tensor def.

    Inputs:
        arr: a numpy array.
        name: (optional) the name of the tensor.
    Returns:
        tensor_def: the converted tensor def.
    """
    tensor = TensorProto()
    tensor.dims.extend(arr.shape)
    if name:
        tensor.name = name

    if arr.dtype == object:
        # Special care for strings.
        tensor.data_type = mapping.NP_TYPE_TO_TENSOR_TYPE[arr.dtype]
        # TODO: Introduce full string support.
        # We flatten the array in case there are 2-D arrays are specified
        # We throw the error below if we have a 3-D array or some kind of other
        # object. If you want more complex shapes then follow the below instructions.
        # Unlike other types where the shape is automatically inferred from
        # nested arrays of values, the only reliable way now to feed strings
        # is to put them into a flat array then specify type astype(object)
        # (otherwise all strings may have different types depending on their length)
        # and then specify shape .reshape([x, y, z])
        flat_array = arr.flatten()
        for e in flat_array:
            if isinstance(e, text_type):
                tensor.string_data.append(e.encode('utf-8'))
            elif isinstance(e, np.ndarray):
                for s in e:
                    if isinstance(s, text_type):
                        tensor.string_data.append(s.encode('utf-8'))
                    elif isinstance(s, bytes):
                        tensor.string_data.append(s)
            elif isinstance(e, bytes):
                tensor.string_data.append(e)
            else:
                raise NotImplementedError(
                    "Unrecognized object in the object array, expect a string, or array of bytes: ",
                    str(type(e)))
        return tensor

    # For numerical types, directly use numpy raw bytes.
    try:
        dtype = mapping.NP_TYPE_TO_TENSOR_TYPE[arr.dtype]
    except KeyError:
        raise RuntimeError("Numpy data type not understood yet: {}".format(
            str(arr.dtype)))
    tensor.data_type = dtype
    tensor.raw_data = arr.tobytes()  # note: tobytes() is only after 1.9.
    if sys.byteorder == 'big':
        # Convert endian from big to little
        convert_endian(tensor)

    return tensor
Ejemplo n.º 28
0
def from_array(
        arr,
        name=None):  # type: (np.ndarray[Any], Optional[Text]) -> TensorProto
    """Converts a numpy array to a tensor def.

    Inputs:
        arr: a numpy array.
        name: (optional) the name of the tensor.
    Returns:
        tensor_def: the converted tensor def.
    """
    tensor = TensorProto()
    tensor.dims.extend(arr.shape)
    if name:
        tensor.name = name

    if arr.dtype == np.object:
        # Special care for strings.
        tensor.data_type = mapping.NP_TYPE_TO_TENSOR_TYPE[arr.dtype]
        for e in arr:
            if isinstance(e, text_type):
                tensor.string_data.append(e.encode('utf-8'))
            elif isinstance(e, np.ndarray):
                tensor.string_data.append(e.tobytes())
            else:
                raise NotImplementedError(
                    "Unrecognized object in the object array, expect a string, or array of bytes"
                )
        return tensor

    # For numerical types, directly use numpy raw bytes.
    try:
        dtype = mapping.NP_TYPE_TO_TENSOR_TYPE[arr.dtype]
    except KeyError:
        raise RuntimeError("Numpy data type not understood yet: {}".format(
            str(arr.dtype)))
    tensor.data_type = dtype
    tensor.raw_data = arr.tobytes()  # note: tobytes() is only after 1.9.

    return tensor
Ejemplo n.º 29
0
#!/usr/bin/env python

import os
import mxnet as mx
from mxnet.contrib import onnx as onnx_mxnet
import onnx
import numpy as np
from onnx import TensorProto
from onnx import numpy_helper

curr_dir = os.path.dirname(__file__)

sym, arg_params, aux_params = onnx_mxnet.import_model(curr_dir + "/model.onnx")

input_tensor = TensorProto()
with open(curr_dir + "/input_0.pb", 'rb') as proto_file:
    input_tensor.ParseFromString(proto_file.read())
input_array = numpy_helper.to_array(input_tensor)

x = mx.nd.array(input_array)

mod = mx.mod.Module(symbol=sym,
                    data_names=['0'],
                    context=mx.cpu(),
                    label_names=None)
mod.bind(for_training=False,
         data_shapes=[('0', (2, 4, 6, 6))],
         label_shapes=None)
mod.set_params(arg_params=arg_params, aux_params=aux_params)
mod.forward(mx.io.DataBatch([x]))
result = mod.get_outputs()[0].asnumpy()
Ejemplo n.º 30
0
def _write_tensor(onnx_tensor: onnx.TensorProto, out: Path) -> None:
    with open(out, "wb") as fp:
        fp.write(onnx_tensor.SerializeToString())
Ejemplo n.º 31
0
def add_onnx_graph(scope, operator, container, onx):
    """
    Adds a whole ONNX graph to an existing one following
    :epkg:`skl2onnx` API assuming this ONNX graph implements
    an `operator <http://onnx.ai/sklearn-onnx/api_summary.html?
    highlight=operator#skl2onnx.common._topology.Operator>`_.

    :param scope: scope (to get unique names)
    :param operator: operator
    :param container: container
    :param onx: ONNX graph
    """
    graph = onx.graph
    name_mapping = {}
    node_mapping = {}
    for node in graph.node:
        name = node.name
        if name is not None:
            node_mapping[node.name] = _clean_initializer_name(node.name, scope)
        for o in node.input:
            name_mapping[o] = _clean_variable_name(o, scope)
        for o in node.output:
            name_mapping[o] = _clean_variable_name(o, scope)
    for o in graph.initializer:
        name_mapping[o.name] = _clean_operator_name(o.name, scope)

    inputs = [_copy_inout(o, scope, name_mapping[o.name]) for o in graph.input]
    outputs = [
        _copy_inout(o, scope, name_mapping[o.name]) for o in graph.output
    ]

    for inp, to in zip(operator.inputs, inputs):
        n = helper.make_node('Identity', [inp.onnx_name], [to.name],
                             name=_clean_operator_name('Identity', scope))
        container.nodes.append(n)

    for inp, to in zip(outputs, operator.outputs):
        n = helper.make_node('Identity', [inp.name], [to.onnx_name],
                             name=_clean_operator_name('Identity', scope))
        container.nodes.append(n)

    for node in graph.node:
        n = helper.make_node(
            node.op_type, [name_mapping[o] for o in node.input],
            [name_mapping[o] for o in node.output],
            name=node_mapping[node.name] if node.name else None,
            domain=node.domain if node.domain else None)
        n.attribute.extend(node.attribute)  # pylint: disable=E1101
        container.nodes.append(n)

    for o in graph.initializer:
        as_str = o.SerializeToString()
        tensor = TensorProto()
        tensor.ParseFromString(as_str)
        tensor.name = name_mapping[o.name]
        container.initializers.append(tensor)

    # opset
    for oimp in onx.opset_import:
        container.node_domain_version_pair_sets.add(
            (oimp.domain, oimp.version))