def test_unsupported_op_attribute_provide_functions(self): # type: () -> None def convert_flatten(builder, node, graph, err): params = NeuralNetwork_pb2.CustomLayerParams() params.className = node.op_type params.description = "Custom layer that corresponds to the ONNX op {}".format(node.op_type, ) params.parameters["axis"].intValue = node.attrs['axis'] builder.add_custom( name=node.name, input_names=node.inputs, output_names=node.outputs, custom_proto_spec=params ) def test_conversion(onnx_model, add_custom_layers=False): coreml_model = convert(onnx_model, add_custom_layers=add_custom_layers, custom_conversion_functions={'Flatten': convert_flatten}) spec = coreml_model.get_spec() layers = spec.neuralNetwork.layers self.assertIsNotNone(layers[0].custom) self.assertEqual('Flatten', layers[0].custom.className) self.assertEqual(3, layers[0].custom.parameters['axis'].intValue) onnx_model = _make_model_flatten_axis3() # Test with add_custom_layers True convert(onnx_model, add_custom_layers=True, custom_conversion_functions={'Flatten': convert_flatten}) # Test with add_custom_layers False convert(onnx_model, add_custom_layers=False, custom_conversion_functions={'Flatten': convert_flatten})
def convert_to_ml(): model = onnx.load(inception_onnx_name) mlmodel = convert(model, image_input_names=[inception_in_name], target_ios=target_ios_verion) mlmodel.save(inception_ml_name) model = onnx.load(compress_onnx_name) mlmodel = convert(model, target_ios=target_ios_verion) mlmodel.save(compress_ml_name)
def _test_torch_model_single_io(torch_model, torch_input_shape, coreml_input_shape): # run torch model torch_input = torch.rand(*torch_input_shape) torch_out = torch_model(torch_input).detach().numpy() # convert to onnx model model_dir = tempfile.mkdtemp() onnx_file = os.path.join(model_dir, 'torch_model.onnx') torch.onnx.export(torch_model, torch_input, onnx_file) onnx_model = onnx.load(onnx_file) # convert to coreml and run coreml_model = convert(onnx_model) output_name = [o.name for o in onnx_model.graph.output][0] initializer_names = {t.name for t in onnx_model.graph.initializer} input_name = [ i.name for i in onnx_model.graph.input if i.name not in initializer_names ][0] input_numpy = torch_input.detach().numpy() input_dict = { input_name: np.reshape(input_numpy, coreml_input_shape) } # type: ignore coreml_out = coreml_model.predict(input_dict, useCPUOnly=True)[output_name] # compare _assert_outputs([torch_out], [coreml_out], decimal=4) # type: ignore # delete onnx model if os.path.exists(model_dir): shutil.rmtree(model_dir)
def convert_to_coreml(self, fn_mlmodel, sample_input): torch_output = self.gen_torch_output(sample_input) # clipwise = torch_output[0] # for idx in torch.topk(torch.from_numpy(clipwise[0,:]), k=5).indices.squeeze(0).tolist(): # print( '%s: %0.3f' % ( idx, clipwise[0,idx] ) ) # first convert to ONNX filename_onnx = '/tmp/PANN_model.onnx' self.convert_to_onnx(filename_onnx, sample_input) onnx_outputs = self.gen_onnx_outputs(filename_onnx, sample_input) # set up for Core ML export convert_params = dict( predicted_feature_name=[], minimum_ios_deployment_target='13', custom_conversion_functions={'Pad': _convert_pad}, ) mlmodel = onnx_coreml.convert( model=filename_onnx, **convert_params, ) # print(mlmodel._spec.description) # assert mlmodel != None, 'CoreML Conversion failed' mlmodel.save(fn_mlmodel) return torch_output """
def convert_to_coreml( self, fn_mlmodel, sample_input ): # first convert to ONNX filename_onnx = '/tmp/PANN_model.onnx' self.convert_to_onnx( filename_onnx, sample_input ) # onnx_outputs = self.gen_onnx_outputs( filename_onnx, sample_input ) # set up for Core ML export convert_params = dict( predicted_feature_name = [], minimum_ios_deployment_target='13', custom_conversion_functions={'Pad':_convert_pad}, ) mlmodel = onnx_coreml.convert( model=filename_onnx, **convert_params, ) # print(mlmodel._spec.description) # assert mlmodel != None, 'CoreML Conversion failed' mlmodel.save( fn_mlmodel ) torch_output = self.gen_torch_output( sample_input ) return torch_output """
def test_convert_onnx_to_coreml(): onnx_model = onnx.load(vgg_onnx_filename) onnx.checker.check_model(onnx_model) labels = load_class_names( os.path.join( os.environ['HOME'], 'workspace/ya-yolo/src/datasets/imagenet1000_clsidx_to_labels.txt') ) from onnx_coreml import convert coreml_model = convert(onnx_model, minimum_ios_deployment_target="13", image_input_names=['image'], preprocessing_args={ "image_scale": 1 / 255.0, "red_bias": 0, "green_bias": 0, "blue_bias": 0 }) vgg_model = coremltools.models.MLModel(coreml_model.get_spec()) vgg_model._spec.neuralNetworkClassifier.stringClassLabels.vector.extend( labels) vgg_model.save(vgg_coreml_filename)
def convert_onnx_to_coreml(onnx_model, model_name, torch_model, input_data): model_coreml = convert(onnx_model, minimum_ios_deployment_target="13") coreml_filename = model_name + ".mlmodel" model_coreml.save(coreml_filename) if platform.system() == "Darwin": check_coreml_model(coreml_filename, torch_model, input_data) return model_coreml
def export_to_core_ml(model): model.eval() device = model.fc.weight.device dummy_input = torch.randn(16, 1, 28, 28, requires_grad=True).to(device) torch.onnx.export(model, dummy_input, 'model.onnx', export_params=True) core_ml_model = convert('model.onnx') core_ml_model.save('model.mlmodel')
def main(args): device_name = 'cpu' if args.gpu is None else 'cuda:' + str(args.gpu) device = torch.device(device_name) n_joints = 14 model = LPM(3, 32, n_joints + 1, device, T=args.t) if args.checkpoint_name is not None: print('Loading checkpoint...') path = os.path.join(args.model_dir, args.checkpoint_name) checkpoint = torch.load(path) model.load_state_dict(checkpoint['state_dict']) model = model.to(device) print('Exporting ONNX...') dummy_images = torch.zeros( (3, args.resolution, args.resolution)).to(device) dummy_centers = torch.zeros( (1, args.resolution, args.resolution)).to(device) torch.onnx.export(model, (dummy_images, dummy_images, dummy_images, dummy_images, dummy_images, dummy_centers), args.onnx_name) print('Exporting CoreML...') model_file = open(args.onnx_name, 'rb') model_proto = onnx_pb.ModelProto() model_proto.ParseFromString(model_file.read()) mlmodel = onnx_coreml.convert(model_proto, mode='regressor', image_input_names=['0']) mlmodel.save(args.core_ml_name) print('Done!')
def _test_torch_model_single_io(torch_model, torch_input_shape, coreml_input_shape, minimum_ios_deployment_target='12', decimal=4, opset_version=9): # run torch model torch_input = torch.rand(*torch_input_shape) torch_out_raw = torch_model(torch_input) if isinstance(torch_out_raw, tuple): torch_out = torch_out_raw[0].detach().numpy() else: torch_out = torch_out_raw.detach().numpy() # convert to onnx model model_dir = tempfile.mkdtemp() if DEBUG: model_dir = '/tmp' onnx_file = os.path.join(model_dir, 'torch_model.onnx') torch.onnx.export(torch_model, torch_input, onnx_file, opset_version=opset_version) onnx_model = onnx.load(onnx_file) # convert to coreml and run coreml_model = convert( onnx_model, minimum_ios_deployment_target=minimum_ios_deployment_target) output_name = [o.name for o in onnx_model.graph.output][0] initializer_names = {t.name for t in onnx_model.graph.initializer} input_name = [ i.name for i in onnx_model.graph.input if i.name not in initializer_names ][0] input_numpy = torch_input.detach().numpy() if SupportedVersion.is_nd_array_supported(minimum_ios_deployment_target): input_dict = {input_name: input_numpy} # type: ignore else: input_dict = { input_name: np.reshape(input_numpy, coreml_input_shape) } # type: ignore coreml_out = coreml_model.predict(input_dict, useCPUOnly=True)[output_name] if DEBUG: coreml_model.save(model_dir + '/torch_model.mlmodel') print('coreml_out') print(np.squeeze(coreml_out)) print('torch_out') print(np.squeeze(torch_out)) print('coreml out shape ', coreml_out.shape) print('torch out shape: ', torch_out.shape) # compare _assert_outputs([torch_out], [coreml_out], decimal=decimal) # type: ignore # delete onnx model if not DEBUG: if os.path.exists(model_dir): shutil.rmtree(model_dir)
def exportCoreML(self, output_coreml_file=None): if not self.conf.coreml_model_dir: return if output_coreml_file is None: output_coreml_file = self.conf.coreml_model_dir try: from onnx_coreml import convert except: LOG.logE("You must install onnx-coreml, coremltools package if you want to convert PyTorch to CoreML model. E.g. pip install --upgrade onnx-coreml coremltools") input_names = ["deepvac_in"] output_names = ["deepvac_out"] if not self.conf.onnx_model_dir: f = tempfile.NamedTemporaryFile() self.conf.onnx_model_dir = f.name #to onnx torch.onnx.export(model, self.sample, self.conf.onnx_model_dir, verbose=True, input_names=input_names, output_names=output_names) #onnx2coreml model_coreml = convert(model=self.conf.onnx_model_dir, preprocessing_args= self.conf.coreml_preprocessing_args, mode=self.conf.coreml_mode, image_input_names=['deepvac_in'], class_labels=self.conf.coreml_class_labels, predicted_feature_name='deepvac_out', minimum_ios_deployment_target=self.conf.minimum_ios_deployment_target) # Save the CoreML model coreml_model.save(output_coreml_file)
def convert_to_coreml( fn_mlmodel, filename_onnx, sample_input ): ''' torch_output = self.gen_torch_output( sample_input ) # print( 'torch_output: shape %s\nsample %s ' % ( torch_output.shape, torch_output[:, :, :3, :3] ) ) print( 'torch_output: shape ', ( torch_output.shape ) ) # (1, 1, 28, 64) # first convert to ONNX filename_onnx = '/tmp/wave__melspec_model.onnx' model.convert_to_onnx( filename_onnx, sample_input ) onnx_output = self.gen_onnx_output( filename_onnx, sample_input ) ''' # set up for Core ML export convert_params = dict( predicted_feature_name = [], minimum_ios_deployment_target='13', ) mlmodel = onnx_coreml.convert( model=filename_onnx, **convert_params, ) # print(mlmodel._spec.description) # assert mlmodel != None, 'CoreML Conversion failed' mlmodel.save( fn_mlmodel )
def test_multiple_image_scaler(self): # type : () -> None inputs = [('input_color', (1,3,10,10)), ('input_gray', (1,1,10,10))] outputs = [('out', (1,4,10,10), TensorProto.FLOAT)] im_scaler1 = helper.make_node("ImageScaler", inputs = ['input_color'], outputs = ['scaler_out_1'], bias = [10,-6,20], scale=3.0) im_scaler2 = helper.make_node("ImageScaler", inputs = ['input_gray'], outputs = ['scaler_out_2'], bias = [-13], scale=5.0) concat = helper.make_node("Concat", inputs=['scaler_out_1', 'scaler_out_2'], outputs=['out'], axis = 1) onnx_model = _onnx_create_model([im_scaler1, im_scaler2, concat], inputs, outputs) spec = convert(onnx_model).get_spec() self.assertEqual(len(spec.neuralNetwork.layers), 1) self.assertEqual(len(spec.neuralNetwork.preprocessing), 2) self.assertEqual(spec.neuralNetwork.preprocessing[0].scaler.channelScale, 3.0) self.assertEqual(spec.neuralNetwork.preprocessing[0].scaler.blueBias, 20.0) self.assertEqual(spec.neuralNetwork.preprocessing[0].scaler.greenBias, -6.0) self.assertEqual(spec.neuralNetwork.preprocessing[0].scaler.redBias, 10.0) self.assertEqual(spec.neuralNetwork.preprocessing[1].scaler.channelScale, 5.0) self.assertEqual(spec.neuralNetwork.preprocessing[1].scaler.grayBias, -13.0)
def _coreml_forward_onnx_model(model, # type: ModelProto input_dict, # type: Dict[Text, np._ArrayLike[Any]] ): # type: (...) -> np.ndarray[Any] coreml_model = convert(model) output_names = [o.name for o in model.graph.output] return _coreml_forward_model(coreml_model, input_dict, output_names)
def convert_onnx2coreml(path, img_path=None, macos=False): # Step 1 ONNX to CoreML model = convert(model=path, minimum_ios_deployment_target="13") coreml_path = path.replace("onnx", "mlmodel") model.save(coreml_path) # Step 2 Display CoreML model specifications model = coremltools.models.MLModel(coreml_path) # Display its specifications print(model.visualize_spec) print_info("Convert the ONNX model into an CoreML model... Pass!") # Step 3 Test CoreML model on one image if macos: if img_path is not None: image = Image.open(img_path) image = image.resize((128, 127)) image = np.array(image) image = image.astype(np.float32) image = image / 255. image = image.transpose(2, 0, 1) else: image = torch.rand(1, 3, 127, 128) pred = model.predict({'my_input': image}) pred = pred['my_output'] pred = pred.squeeze() idx = pred.argmax() print('Predicted class : %d (%s)' % (idx, classes[idx]))
def test_image_scaler_remover(self): # type: () -> None inputs = [('input', (1, 3, 50, 50))] outputs = [('out', (1, 3, 50, 50), TensorProto.FLOAT)] im_scaler = helper.make_node("ImageScaler", inputs=['input'], outputs=['scaler_out'], bias=[10, -6, 20], scale=3.0) exp = helper.make_node("Exp", inputs=["scaler_out"], outputs=['out']) onnx_model = _onnx_create_model([im_scaler, exp], inputs, outputs) graph = Graph.from_onnx(onnx_model.graph) new_graph = graph.transformed([ImageScalerRemover()]) self.assertEqual(len(graph.nodes), 2) self.assertEqual(len(new_graph.nodes), 1) self.assertEqual(new_graph.nodes[0].inputs[0], 'input') self.assertEqual(new_graph.nodes[0].outputs[0], 'out') coreml_model = convert(onnx_model) spec = coreml_model.get_spec() self.assertEqual( spec.neuralNetwork.preprocessing[0].scaler.channelScale, 3.0) self.assertEqual(spec.neuralNetwork.preprocessing[0].scaler.blueBias, 20.0) self.assertEqual(spec.neuralNetwork.preprocessing[0].scaler.greenBias, -6.0) self.assertEqual(spec.neuralNetwork.preprocessing[0].scaler.redBias, 10.0)
def test_unsupported_ops_provide_functions(self): # type: () -> None def convert_acos(node): params = NeuralNetwork_pb2.CustomLayerParams() params.className = node.op_type params.description = "Custom layer that corresponds to the ONNX op {}".format( node.op_type, ) return params def convert_topk(node): params = NeuralNetwork_pb2.CustomLayerParams() params.className = node.op_type params.description = "Custom layer that corresponds to the ONNX op {}".format( node.op_type, ) params.parameters["axis"].intValue = node.attrs.get('axis', -1) params.parameters["k"].intValue = node.attrs['k'] return params onnx_model = _make_model_clip_exp_topk() coreml_model = convert(model=onnx_model, add_custom_layers=True, custom_conversion_functions={ 'Acos': convert_acos, 'TopK': convert_topk }) spec = coreml_model.get_spec() layers = spec.neuralNetwork.layers self.assertIsNotNone(layers[0].custom) self.assertIsNotNone(layers[2].custom) self.assertEqual('Acos', layers[0].custom.className) self.assertEqual('TopK', layers[2].custom.className) self.assertEqual(0, layers[2].custom.parameters['axis'].intValue) self.assertEqual(3, layers[2].custom.parameters['k'].intValue)
def test_convert_image_input(self): # type: () -> None coreml_model = convert( self.onnx_model, image_input_names=self.input_names ) spec = coreml_model.get_spec() for input_ in spec.description.input: self.assertEqual(input_.type.WhichOneof('Type'), 'imageType')
def test_unsupported_op_attribute(self): # type: () -> None onnx_model = _make_model_flatten_axis3() coreml_model = convert(onnx_model, add_custom_layers=True) spec = coreml_model.get_spec() layers = spec.neuralNetwork.layers self.assertIsNotNone(layers[0].custom) self.assertEqual('Flatten', layers[0].custom.className)
def test_convert_image_output(self): coreml_model = convert( self.onnx_model, image_output_names=self.output_names ) spec = coreml_model.get_spec() for output in spec.description.output: self.assertEqual(output.type.WhichOneof('Type'), 'imageType')
def _coreml_forward_onnx_model(model, # type: ModelProto input_dict, # type: Dict[Text, np._ArrayLike[Any]] onnx_coreml_input_shape_map = {}, # type: Dict[Text, List[int,...]] target_ios='12' ): # type: (...) -> np.ndarray[Any] coreml_model = convert(model, onnx_coreml_input_shape_map=onnx_coreml_input_shape_map, target_ios=target_ios) output_names = [o.name for o in model.graph.output] return _coreml_forward_model(coreml_model, input_dict, output_names, target_ios=target_ios)
def convert_to_coreml(self, fn_mlmodel, sample_input, plot_specs=True): import onnx import onnx_coreml torch_spectrogram = self.gen_torch_output(sample_input) print('torch_spectrogram: shape %s\nsample %s ' % (torch_spectrogram.shape, torch_spectrogram[:, :, :3, :3])) # first convert to ONNX filename_onnx = '/tmp/wave__spectrogram_model.onnx' model.convert_to_onnx(filename_onnx, sample_input) onnx_spectrogram = self.gen_onnx_spectrogram(filename_onnx, sample_input) # set up for Core ML export convert_params = dict( predicted_feature_name=[], minimum_ios_deployment_target='13', ) mlmodel = onnx_coreml.convert( model=filename_onnx, **convert_params, ) ''' output = spec.description.output[0] import coremltools.proto.FeatureTypes_pb2 as ft output.type.imageType.colorSpace = ft.ImageFeatureType.GRAYSCALE output.type.imageType.height = 300 output.type.imageType.width = 150 ''' assert mlmodel != None, 'CoreML Conversion failed' mlmodel.save(fn_mlmodel) model_inputs = {self.input_name: sample_input} # do forward pass mlmodel_outputs = mlmodel.predict(model_inputs, useCPUOnly=True) # fetch the spectrogram from output dictionary mlmodel_spectrogram = mlmodel_outputs[self.output_name] print('mlmodel_output: shape %s sample %s ' % (mlmodel_spectrogram.shape, mlmodel_spectrogram[:, :, :3, :3])) assert torch_spectrogram.shape == mlmodel_spectrogram.shape assert np.allclose(torch_spectrogram, mlmodel_spectrogram) print('Successful MLModel conversion to %s!' % fn_mlmodel) if plot_specs: plot_spectrograms(torch_spectrogram, onnx_spectrogram, mlmodel_spectrogram) return mlmodel_spectrogram
def test_conversion(onnx_model, add_custom_layers=False): coreml_model = convert(onnx_model, add_custom_layers=add_custom_layers, custom_conversion_functions={'Flatten': convert_flatten}) spec = coreml_model.get_spec() layers = spec.neuralNetwork.layers self.assertIsNotNone(layers[0].custom) self.assertEqual('Flatten', layers[0].custom.className) self.assertEqual(3, layers[0].custom.parameters['axis'].intValue)
def convert_onnx2coreml_new(path): model = convert(model=path, mode='classifier', image_input_names=['my_input'], preprocessing_args={'image_scale': 1. / 255.}, minimum_ios_deployment_target='13') print(model.visualize_spec) coreml_path = path.replace(".onnx", "_RGB.mlmodel") # Save the CoreML model model.save(coreml_path)
def test_convert_image_output_bgr(self): # type: () -> None coreml_model = convert(self.onnx_model, image_input_names=self.input_names, image_output_names=self.output_names, deprocessing_args={'is_bgr': True}) output = coreml_model.predict({self.input_names[0]: self.img})[self.output_names[0]] output = np.array(output)[:, :, :3].transpose((2, 0, 1)) expected_output = self.img_arr[:, :, ::-1].transpose((2, 0, 1)) npt.assert_equal(output, expected_output)
def prepare(cls, model, # type: ModelProto device='CPU', # type: Text **kwargs # type: Any ): # type: (...) -> CoreMLRep super(CoreMLBackend, cls).prepare(model, device, **kwargs) coreml_model = convert(model) onnx_outputs = _get_onnx_outputs(model) return CoreMLRep(coreml_model, onnx_outputs, device == 'CPU')
def test_node_name_type_custom_functions(self): # type: () -> None def convert_acos(builder, node, graph, err): params = NeuralNetwork_pb2.CustomLayerParams() params.className = node.op_type params.description = "Custom layer that corresponds to the ONNX op {}".format(node.op_type, ) builder.add_custom( name=node.name, input_names=node.inputs, output_names=node.outputs, custom_proto_spec=params ) def convert_topk_generic(builder, node, graph, err): params = NeuralNetwork_pb2.CustomLayerParams() params.className = node.op_type params.description = "Custom layer that corresponds to the ONNX op {}".format(node.op_type, ) params.parameters["axis"].intValue = node.attrs.get('axis', -1) params.parameters["k"].intValue = node.attrs['k'] builder.add_custom( name=node.name, input_names=node.inputs, output_names=node.outputs, custom_proto_spec=params ) def convert_topk_node_specific(builder, node, graph, err): params = NeuralNetwork_pb2.CustomLayerParams() params.className = node.op_type params.description = "Custom layer that corresponds to the ONNX op {}".format(node.op_type, ) params.parameters["axis"].intValue = node.attrs.get('axis', -1) builder.add_custom( name=node.name, input_names=node.inputs, output_names=node.outputs, custom_proto_spec=params ) onnx_model = _make_model_acos_exp_topk() onnx.save_model(onnx_model, 'acos.onnx') coreml_model = convert(model=onnx_model, add_custom_layers=True, custom_conversion_functions={'Acos':convert_acos, 'TopK':convert_topk_generic, 'output_values_output_indices':convert_topk_node_specific}) spec = coreml_model.get_spec() layers = spec.neuralNetwork.layers self.assertIsNotNone(layers[0].custom) self.assertIsNotNone(layers[2].custom) self.assertEqual('Acos', layers[0].custom.className) self.assertEqual('TopK', layers[2].custom.className) self.assertEqual(0, layers[2].custom.parameters['axis'].intValue)
def test_unsupported_ops(self): # type: () -> None onnx_model = _make_model_acos_exp_topk() coreml_model = convert(onnx_model, add_custom_layers=True) spec = coreml_model.get_spec() layers = spec.neuralNetwork.layers self.assertIsNotNone(layers[0].custom) self.assertIsNotNone(layers[2].custom) self.assertEqual('Acos', layers[0].custom.className) self.assertEqual('TopK', layers[2].custom.className)
def tomodel(): class_labels = [ 'air plane', 'automobile', 'bird', 'cat', 'deer', 'dog', 'frog', 'horse', 'ship', 'truck' ] model = convert(model=PATH + '.onnx', minimum_ios_deployment_target='13', image_input_names=['image'], mode='classifier', predicted_feature_name='classLabel', class_labels=class_labels) model.save(PATH + '.mlmodel')
def convert_onnx2coreml_classlabels(path): model = convert(model=path, mode='classifier', image_input_names=['my_input'], preprocessing_args={'image_scale': 1. / 255.}, class_labels=classes, predicted_feature_name='classLabel', minimum_ios_deployment_target='13') print(model.visualize_spec) coreml_path = path.replace(".onnx", "_RGB_classlabels.mlmodel") # Save the CoreML model model.save(coreml_path)