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]
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
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))
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
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
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)
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
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
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
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))
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)
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
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
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
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)
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)
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]), ])
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])
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)
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
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
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()
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)
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
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())
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')])
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
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
#!/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()
def _write_tensor(onnx_tensor: onnx.TensorProto, out: Path) -> None: with open(out, "wb") as fp: fp.write(onnx_tensor.SerializeToString())
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))