def test_nn_set_training_input(self):
        builder = self.create_base_builder()

        builder.set_mean_squared_error_loss(name="mse",
                                            input_feature=("output",
                                                           datatypes.Array(3)))

        builder.set_adam_optimizer(
            AdamParams(lr=1e-2, batch=10, beta1=0.9, beta2=0.999, eps=1e-8))
        builder.set_epochs(20, allowed_set=[10, 20, 30])

        model_path = os.path.join(self.model_dir, "updatable_creation.mlmodel")
        print(model_path)
        save_spec(builder.spec, model_path)

        mlmodel = MLModel(model_path)
        self.assertTrue(mlmodel is not None)
        spec = mlmodel.get_spec()
        self.assertEqual(spec.description.trainingInput[0].name, "input")
        self.assertEqual(
            spec.description.trainingInput[0].type.WhichOneof("Type"),
            "multiArrayType")
        self.assertEqual(spec.description.trainingInput[1].name, "output_true")
        self.assertEqual(
            spec.description.trainingInput[1].type.WhichOneof("Type"),
            "multiArrayType")
Beispiel #2
0
    def test_downgrade_specification_version(self):
        # manually set a invalid specification version
        self.spec.specificationVersion = -1
        model = MLModel(self.spec)
        assert model.get_spec().specificationVersion == 1

        # manually set a high specification version
        self.spec.specificationVersion = 4
        filename = tempfile.mktemp(suffix='.mlmodel')
        save_spec(self.spec, filename, auto_set_specification_version=True)
        model = MLModel(filename)
        assert model.get_spec().specificationVersion == 1

        # simple neural network with only spec 1 layer
        input_features = [('data', datatypes.Array(3))]
        output_features = [('out', datatypes.Array(3))]
        builder = NeuralNetworkBuilder(input_features, output_features)
        builder.add_activation('relu', 'RELU', 'data', 'out')
        # set a high specification version
        builder.spec.specificationVersion = 3
        model = MLModel(builder.spec)
        filename = tempfile.mktemp(suffix='.mlmodel')
        model.save(filename)
        # load the model back
        model = MLModel(filename)
        assert model.get_spec().specificationVersion == 1

        # test save without automatic set specification version
        self.spec.specificationVersion = 3
        filename = tempfile.mktemp(suffix='.mlmodel')
        save_spec(self.spec, filename, auto_set_specification_version=False)
        model = MLModel(filename)
        # the specification version should be original
        assert model.get_spec().specificationVersion == 3
Beispiel #3
0
    def test_nn_set_training_input(self):

        builder = self.create_base_builder()

        builder.set_mean_squared_error_loss(name='mse',
                                            input='output',
                                            target='target')

        builder.set_adam_optimizer(
            AdamParams(lr=1e-2, batch=10, beta1=0.9, beta2=0.999, eps=1e-8))
        builder.set_epochs(20, allowed_set=[10, 20, 30])

        builder.set_training_input([('input', datatypes.Array(3)),
                                    ('target', 'Double')])

        model_path = os.path.join(self.model_dir, 'updatable_creation.mlmodel')
        print(model_path)
        save_spec(builder.spec, model_path)

        mlmodel = MLModel(model_path)
        self.assertTrue(mlmodel is not None)
        spec = mlmodel.get_spec()
        self.assertEqual(spec.description.trainingInput[0].name, 'input')
        self.assertEqual(
            spec.description.trainingInput[0].type.WhichOneof('Type'),
            'multiArrayType')
        self.assertEqual(spec.description.trainingInput[1].name, 'target')
        self.assertEqual(
            spec.description.trainingInput[1].type.WhichOneof('Type'),
            'doubleType')
Beispiel #4
0
    def test_nn_builder_with_training_features(self):

        input_features = [('input', datatypes.Array(3))]
        output_features = [('output', None)]
        training_features = [('input', datatypes.Array(3)),
                             ('target', datatypes.Double)]

        builder = NeuralNetworkBuilder(input_features,
                                       output_features,
                                       disable_rank5_shape_mapping=True,
                                       training_features=training_features)

        W1 = _np.random.uniform(-0.5, 0.5, (3, 3))
        W2 = _np.random.uniform(-0.5, 0.5, (3, 3))
        builder.add_inner_product(name='ip1',
                                  W=W1,
                                  b=None,
                                  input_channels=3,
                                  output_channels=3,
                                  has_bias=False,
                                  input_name='input',
                                  output_name='hidden')
        builder.add_inner_product(name='ip2',
                                  W=W2,
                                  b=None,
                                  input_channels=3,
                                  output_channels=3,
                                  has_bias=False,
                                  input_name='hidden',
                                  output_name='output')

        builder.make_updatable(['ip1', 'ip2'])  # or a dict for weightParams

        builder.set_mean_squared_error_loss(name='mse',
                                            input='output',
                                            target='target')

        builder.set_adam_optimizer(
            AdamParams(lr=1e-2, batch=10, beta1=0.9, beta2=0.999, eps=1e-8))
        builder.set_epochs(20, allowed_set=[10, 20, 30])

        builder.set_training_input([('input', datatypes.Array(3)),
                                    ('target', 'Double')])

        model_path = os.path.join(self.model_dir, 'updatable_creation.mlmodel')
        print(model_path)
        save_spec(builder.spec, model_path)

        mlmodel = MLModel(model_path)
        self.assertTrue(mlmodel is not None)
        spec = mlmodel.get_spec()
        self.assertEqual(spec.description.trainingInput[0].name, 'input')
        self.assertEqual(
            spec.description.trainingInput[0].type.WhichOneof('Type'),
            'multiArrayType')
        self.assertEqual(spec.description.trainingInput[1].name, 'target')
        self.assertEqual(
            spec.description.trainingInput[1].type.WhichOneof('Type'),
            'doubleType')
Beispiel #5
0
    def test_model_creation(self):
        model = MLModel(self.spec)
        self.assertIsNotNone(model)

        filename = tempfile.mktemp(suffix='.mlmodel')
        save_spec(self.spec, filename)
        model = MLModel(filename)
        self.assertIsNotNone(model)
    def test_nn_partial_fp16_make_updatable_fail(self):
        nn_builder = self.create_base_builder()
        model_path = os.path.join(self.model_dir, "updatable_creation.mlmodel")
        print(model_path)
        save_spec(nn_builder.spec, model_path)
        mlmodel = MLModel(model_path)

        # fails since updatable models cannot get quantized to FP16
        with self.assertRaises(Exception):
            quantization_utils.quantize_weights(mlmodel, 16, "linear")
    def test_nn_builder_with_training_features(self):
        input_features = [("input", datatypes.Array(3))]
        output_features = [("output", datatypes.Array(3))]
        builder = NeuralNetworkBuilder(input_features, output_features)

        W1 = _np.random.uniform(-0.5, 0.5, (3, 3))
        W2 = _np.random.uniform(-0.5, 0.5, (3, 3))
        builder.add_inner_product(
            name="ip1",
            W=W1,
            b=None,
            input_channels=3,
            output_channels=3,
            has_bias=False,
            input_name="input",
            output_name="hidden",
        )
        builder.add_inner_product(
            name="ip2",
            W=W2,
            b=None,
            input_channels=3,
            output_channels=3,
            has_bias=False,
            input_name="hidden",
            output_name="output",
        )

        builder.make_updatable(["ip1", "ip2"])  # or a dict for weightParams

        builder.set_mean_squared_error_loss(name="mse",
                                            input_feature=("output",
                                                           datatypes.Array(3)))

        builder.set_adam_optimizer(
            AdamParams(lr=1e-2, batch=10, beta1=0.9, beta2=0.999, eps=1e-8))
        builder.set_epochs(20, allowed_set=[10, 20, 30])

        model_path = os.path.join(self.model_dir, "updatable_creation.mlmodel")
        print(model_path)
        save_spec(builder.spec, model_path)

        mlmodel = MLModel(model_path)
        self.assertTrue(mlmodel is not None)
        spec = mlmodel.get_spec()
        self.assertEqual(spec.description.trainingInput[0].name, "input")
        self.assertEqual(
            spec.description.trainingInput[0].type.WhichOneof("Type"),
            "multiArrayType")
        self.assertEqual(spec.description.trainingInput[1].name, "output_true")
        self.assertEqual(
            spec.description.trainingInput[1].type.WhichOneof("Type"),
            "multiArrayType")
    def test_model_creation(self):
        model = MLModel(self.spec)
        self.assertIsNotNone(model)

        package = tempfile.TemporaryDirectory(suffix=".mlpackage")
        package.cleanup()

        save_spec(self.spec, package.name)
        model = MLModel(package.name)
        self.assertIsNotNone(model)

        # cleanup
        MLModelTest._remove_path(package.name)
Beispiel #9
0
    def test_model_save_no_extension(self):
        model = MLModel(self.spec)
        self.assertIsNotNone(model)

        filename = tempfile.mktemp(suffix="")
        save_spec(self.spec, filename) # appends .mlmodel extension when it is not provided
        self.assertFalse(os.path.exists(filename))

        filename = filename + ".mlmodel"
        self.assertTrue(os.path.exists(filename))

        model = MLModel(filename)
        self.assertIsNotNone(model)
        os.remove(filename)
    def test_nn_fp16_make_updatable_fail(self):
        nn_builder = self.create_base_builder(is_updatable=False)
        model_path = os.path.join(self.model_dir, "updatable_creation.mlmodel")
        print(model_path)
        save_spec(nn_builder.spec, model_path)
        mlmodel = MLModel(model_path)

        quantized_model = quantization_utils.quantize_weights(
            mlmodel, 16, "linear")

        q_nn_builder = NeuralNetworkBuilder(spec=quantized_model._spec)

        # fails since an FP16 model cannot be marked updatable
        with self.assertRaises(ValueError):
            q_nn_builder.make_updatable(["ip1", "ip2"])
Beispiel #11
0
 def test_future_version(self):
     self.spec.specificationVersion = 10000
     filename = tempfile.mktemp(suffix='.mlmodel')
     save_spec(self.spec, filename, auto_set_specification_version=False)
     model = MLModel(filename)
     # this model should exist, but throw an exception when we try to use
     # predict because the engine doesn't support this model version
     self.assertIsNotNone(model)
     with self.assertRaises(Exception):
         try:
             model.predict({})
         except Exception as e:
             assert 'Core ML model specification version' in str(e)
             raise
     self.spec.specificationVersion = 1
    def test_nn_partial_fp16_make_updatable_quantized_layer_fail(self):
        nn_builder = self.create_base_builder(is_updatable=False)
        model_path = os.path.join(self.model_dir, "updatable_creation.mlmodel")
        print(model_path)
        save_spec(nn_builder.spec, model_path)
        mlmodel = MLModel(model_path)

        selector = LayerSelector(layer_name='ip2')
        quantized_model = quantization_utils.quantize_weights(
            mlmodel, 16, "linear", selector=selector)

        q_nn_builder = NeuralNetworkBuilder(spec=quantized_model._spec)

        # fails since model has a layer with FP16 bias
        with self.assertRaises(ValueError):
            q_nn_builder.make_updatable(["ip2"])
Beispiel #13
0
def onnx_to_coreml(onnx_filename, core_ml_filename):
    onnx_model = onnx.load(onnx_filename)
    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
                           })
    builder = coremltools.models.neural_network.NeuralNetworkBuilder(
        spec=coreml_model.get_spec())

    save_spec(builder.spec, core_ml_filename)

    coremltools.models.neural_network.printer.print_network_spec(builder.spec)
Beispiel #14
0
    def test_downgrade_specification_version(self):
        # manually set a invalid specification version
        self.spec.specificationVersion = -1
        model = MLModel(self.spec)
        if model.get_spec().specificationVersion != 1:
            raise AssertionError

        # manually set a high specification version
        self.spec.specificationVersion = 4
        filename = tempfile.mktemp(suffix=".mlmodel")
        save_spec(self.spec, filename, auto_set_specification_version=True)
        model = MLModel(filename)
        if model.get_spec().specificationVersion != 1:
            raise AssertionError

        # simple neural network with only spec 1 layer
        input_features = [("data", datatypes.Array(3))]
        output_features = [("out", datatypes.Array(3))]
        builder = NeuralNetworkBuilder(input_features, output_features)
        builder.add_activation("relu", "RELU", "data", "out")
        # set a high specification version
        builder.spec.specificationVersion = 3
        model = MLModel(builder.spec)
        filename = tempfile.mktemp(suffix=".mlmodel")
        model.save(filename)
        # load the model back
        model = MLModel(filename)
        if model.get_spec().specificationVersion != 1:
            raise AssertionError

        # test save without automatic set specification version
        self.spec.specificationVersion = 3
        filename = tempfile.mktemp(suffix=".mlmodel")
        save_spec(self.spec, filename, auto_set_specification_version=False)
        model = MLModel(filename)
        # the specification version should be original
        if model.get_spec().specificationVersion != 3:
            raise AssertionError
    def test_updatable_model_creation_ce_sgd(self):
        builder = self.create_base_builder()

        builder.add_softmax(name="softmax",
                            input_name="output",
                            output_name="softmax_output")

        builder.set_categorical_cross_entropy_loss(name="cross_entropy",
                                                   input="softmax_output")

        builder.set_sgd_optimizer(SgdParams(lr=1e-2, batch=10, momentum=0.0))
        builder.set_epochs(20, allowed_set=[10, 20, 30, 40])

        model_path = os.path.join(self.model_dir, "updatable_creation.mlmodel")
        print(model_path)
        save_spec(builder.spec, model_path)

        mlmodel = MLModel(model_path)
        self.assertTrue(mlmodel is not None)

        spec = mlmodel.get_spec()
        self.assertTrue(spec.isUpdatable)
        self.assertTrue(spec.neuralNetwork.layers[0].isUpdatable)
        self.assertTrue(
            spec.neuralNetwork.layers[0].innerProduct.weights.isUpdatable)
        self.assertTrue(spec.neuralNetwork.layers[1].isUpdatable)
        self.assertTrue(
            spec.neuralNetwork.layers[1].innerProduct.weights.isUpdatable)

        self.assertTrue(spec.neuralNetwork.updateParams.lossLayers[0].
                        categoricalCrossEntropyLossLayer is not None)
        self.assertTrue(
            spec.neuralNetwork.updateParams.optimizer.sgdOptimizer is not None)

        self.assertTrue(
            _np.isclose(
                spec.neuralNetwork.updateParams.optimizer.sgdOptimizer.
                learningRate.defaultValue,
                1e-2,
                atol=1e-4,
            ))
        self.assertTrue(
            _np.isclose(
                spec.neuralNetwork.updateParams.optimizer.sgdOptimizer.
                miniBatchSize.defaultValue,
                10,
                atol=1e-4,
            ))
        self.assertTrue(
            _np.isclose(
                spec.neuralNetwork.updateParams.optimizer.sgdOptimizer.
                momentum.defaultValue,
                0,
                atol=1e-8,
            ))

        self.assertTrue(
            _np.isclose(spec.neuralNetwork.updateParams.epochs.defaultValue,
                        20,
                        atol=1e-4))

        self.assertTrue(spec.neuralNetwork.updateParams.optimizer.sgdOptimizer.
                        learningRate.range.minValue == 0)
        self.assertTrue(spec.neuralNetwork.updateParams.optimizer.sgdOptimizer.
                        learningRate.range.maxValue == 1)

        self.assertTrue(spec.neuralNetwork.updateParams.optimizer.sgdOptimizer.
                        miniBatchSize.set.values == [10])

        self.assertTrue(spec.neuralNetwork.updateParams.optimizer.sgdOptimizer.
                        momentum.range.minValue == 0)
        self.assertTrue(spec.neuralNetwork.updateParams.optimizer.sgdOptimizer.
                        momentum.range.maxValue == 1)
                        output_name='position_ids_expanded_to_rank5',
                        axes=(1, 2, 3, 4))
builder.add_embedding(
    name='token_embeddings',
    input_name='input_ids_expanded_to_rank5',
    output_name='token_embeddings',
    W=wte,
    b=None,
    input_dim=50257,
    output_channels=768,
    has_bias=False,
)
builder.add_embedding(
    name='positional_embeddings',
    input_name='position_ids_expanded_to_rank5',
    output_name='positional_embeddings',
    W=wpe,
    b=None,
    input_dim=1024,
    output_channels=768,
    has_bias=False,
)
builder.add_add_broadcastable(
    name='embeddings_addition',
    input_names=['token_embeddings', 'positional_embeddings'],
    output_name='output_logits')

# compile spec to model
## model = coremltools.models.MLModel(builder.spec)
save_spec(builder.spec, 'gpt2.mlmodel')
Beispiel #17
0
def export_models(config, mask_rcnn_model, classifier_model, mask_model,
                  export_main_path, export_mask_path, export_anchors_path):
    license = "MIT"
    author = "Édouard Lavery-Plante"

    def convert_proposal(layer):
        params = NeuralNetwork_pb2.CustomLayerParams()
        params.className = "ProposalLayer"
        params.description = "Proposes regions of interests and performs NMS."
        params.parameters["bboxStdDev_count"].intValue = len(
            layer.bounding_box_std_dev)
        for idx, value in enumerate(layer.bounding_box_std_dev):
            params.parameters["bboxStdDev_" + str(idx)].doubleValue = value
        params.parameters[
            "preNMSMaxProposals"].intValue = layer.pre_nms_max_proposals
        params.parameters["maxProposals"].intValue = layer.max_proposals
        params.parameters["nmsIOUThreshold"].doubleValue = layer.nms_threshold
        return params

    def convert_pyramid(layer):
        params = NeuralNetwork_pb2.CustomLayerParams()
        params.className = "PyramidROIAlignLayer"
        params.parameters["poolSize"].intValue = layer.pool_shape[0]
        params.parameters["imageWidth"].intValue = layer.image_shape[0]
        params.parameters["imageHeight"].intValue = layer.image_shape[1]
        params.description = "Extracts feature maps based on the regions of interest."
        return params

    def convert_time_distributed_classifier(layer):
        params = NeuralNetwork_pb2.CustomLayerParams()
        params.className = "TimeDistributedClassifierLayer"
        return params

    def convert_time_distributed(layer):
        params = NeuralNetwork_pb2.CustomLayerParams()
        params.className = "TimeDistributedMaskLayer"
        params.description = "Applies the Mask graph to each detections along the time dimension."
        return params

    def convert_detection(layer):
        params = NeuralNetwork_pb2.CustomLayerParams()
        params.className = "DetectionLayer"
        params.parameters["bboxStdDev_count"].intValue = len(
            layer.bounding_box_std_dev)
        for idx, value in enumerate(layer.bounding_box_std_dev):
            params.parameters["bboxStdDev_" + str(idx)].doubleValue = value
        params.parameters["maxDetections"].intValue = layer.max_detections
        params.parameters[
            "scoreThreshold"].doubleValue = layer.detection_min_confidence
        params.parameters[
            "nmsIOUThreshold"].doubleValue = layer.detection_nms_threshold
        params.description = "Outputs detections based on confidence and performs NMS."
        return params

    mask_rcnn_model = convert_keras_to_coreml(
        mask_rcnn_model,
        input_names=["image"],
        image_input_names=['image'],
        output_names=["detections", "mask"],
        red_bias=-123.7,
        green_bias=-116.8,
        blue_bias=-103.9,
        add_custom_layers=True,
        custom_conversion_functions={
            "ProposalLayer": convert_proposal,
            "PyramidROIAlign": convert_pyramid,
            "TimeDistributedClassifier": convert_time_distributed_classifier,
            "TimeDistributedMask": convert_time_distributed,
            "DetectionLayer": convert_detection
        })

    mask_rcnn_model.author = author
    mask_rcnn_model.license = license
    mask_rcnn_model.short_description = "Mask-RCNN"
    mask_rcnn_model.input_description["image"] = "Input image"
    mask_rcnn_model.output_description[
        "detections"] = "Detections (y1,x1,y2,x2,classId,score)"
    mask_rcnn_model.output_description["mask"] = "Masks for the detections"
    half_model = convert_neural_network_weights_to_fp16(mask_rcnn_model)
    half_spec = half_model.get_spec()
    save_spec(half_spec, export_main_path)

    mask_model_coreml = convert_keras_to_coreml(mask_model,
                                                input_names=["feature_map"],
                                                output_names=["masks"])
    mask_model_coreml.author = author
    mask_model_coreml.license = license
    mask_model_coreml.short_description = "Generates a mask for each class for a given feature map"
    mask_model_coreml.input_description[
        "feature_map"] = "Fully processed feature map, ready for mask generation."
    mask_model_coreml.output_description[
        "masks"] = "Masks corresponding to each class"
    half_mask_model = convert_neural_network_weights_to_fp16(mask_model_coreml)
    half_mask_spec = half_mask_model.get_spec()
    save_spec(half_mask_spec, export_mask_path)

    classifier_model_coreml = convert_keras_to_coreml(
        classifier_model,
        input_names=["feature_map"],
        output_names=["probabilities", "bounding_boxes"])

    classifier_model_coreml.author = author
    classifier_model_coreml.license = license
    classifier_model_coreml.short_description = ""
    classifier_model_coreml.input_description[
        "feature_map"] = "Fully processed feature map, ready for classification."
    half_classifier_model = convert_neural_network_weights_to_fp16(
        classifier_model_coreml)
    half_classifier_spec = half_classifier_model.get_spec()
    save_spec(half_classifier_spec, "products/Classifier.mlmodel")
    def test_updatable_model_creation_mse_adam(self):
        builder = self.create_base_builder()

        builder.set_mean_squared_error_loss(name="mse",
                                            input_feature=("output",
                                                           datatypes.Array(3)))

        builder.set_adam_optimizer(
            AdamParams(lr=1e-2, batch=10, beta1=0.9, beta2=0.999, eps=1e-8))
        builder.set_epochs(20, allowed_set=[10, 20, 30])

        model_path = os.path.join(self.model_dir, "updatable_creation.mlmodel")
        print(model_path)
        save_spec(builder.spec, model_path)

        mlmodel = MLModel(model_path)
        self.assertTrue(mlmodel is not None)
        spec = mlmodel.get_spec()
        self.assertTrue(spec.isUpdatable)
        self.assertTrue(spec.neuralNetwork.layers[0].isUpdatable)
        self.assertTrue(
            spec.neuralNetwork.layers[0].innerProduct.weights.isUpdatable)
        self.assertTrue(spec.neuralNetwork.layers[1].isUpdatable)
        self.assertTrue(
            spec.neuralNetwork.layers[1].innerProduct.weights.isUpdatable)

        self.assertTrue(spec.neuralNetwork.updateParams.lossLayers[0].
                        categoricalCrossEntropyLossLayer is not None)
        self.assertTrue(spec.neuralNetwork.updateParams.optimizer.adamOptimizer
                        is not None)

        self.assertTrue(
            _np.isclose(
                spec.neuralNetwork.updateParams.optimizer.adamOptimizer.
                learningRate.defaultValue,
                1e-2,
                atol=1e-4,
            ))
        self.assertTrue(
            _np.isclose(
                spec.neuralNetwork.updateParams.optimizer.adamOptimizer.
                miniBatchSize.defaultValue,
                10,
                atol=1e-4,
            ))
        self.assertTrue(
            _np.isclose(
                spec.neuralNetwork.updateParams.optimizer.adamOptimizer.beta1.
                defaultValue,
                0.9,
                atol=1e-4,
            ))
        self.assertTrue(
            _np.isclose(
                spec.neuralNetwork.updateParams.optimizer.adamOptimizer.beta2.
                defaultValue,
                0.999,
                atol=1e-4,
            ))
        self.assertTrue(
            _np.isclose(
                spec.neuralNetwork.updateParams.optimizer.adamOptimizer.eps.
                defaultValue,
                1e-8,
                atol=1e-8,
            ))
        self.assertTrue(
            _np.isclose(spec.neuralNetwork.updateParams.epochs.defaultValue,
                        20,
                        atol=1e-4))

        self.assertTrue(spec.neuralNetwork.updateParams.optimizer.
                        adamOptimizer.learningRate.range.minValue == 0)
        self.assertTrue(spec.neuralNetwork.updateParams.optimizer.
                        adamOptimizer.learningRate.range.maxValue == 1)

        self.assertTrue(spec.neuralNetwork.updateParams.optimizer.
                        adamOptimizer.miniBatchSize.set.values == [10])

        self.assertTrue(spec.neuralNetwork.updateParams.optimizer.
                        adamOptimizer.beta1.range.minValue == 0)
        self.assertTrue(spec.neuralNetwork.updateParams.optimizer.
                        adamOptimizer.beta1.range.maxValue == 1)

        self.assertTrue(spec.neuralNetwork.updateParams.optimizer.
                        adamOptimizer.beta2.range.minValue == 0)
        self.assertTrue(spec.neuralNetwork.updateParams.optimizer.
                        adamOptimizer.beta2.range.maxValue == 1)

        self.assertTrue(spec.neuralNetwork.updateParams.optimizer.
                        adamOptimizer.eps.range.minValue == 0)
        self.assertTrue(spec.neuralNetwork.updateParams.optimizer.
                        adamOptimizer.eps.range.maxValue == 1)

        self.assertTrue(
            spec.neuralNetwork.updateParams.epochs.set.values == [10, 20, 30])
Beispiel #19
0
    def test_updatable_model_creation_mse_sgd(self):

        builder = self.create_base_builder()

        builder.set_mean_squared_error_loss(name='mse',
                                            input='output',
                                            target='target')

        builder.set_sgd_optimizer(SgdParams(lr=1e-2, batch=10, momentum=0.0))

        builder.set_epochs(20)

        model_path = os.path.join(self.model_dir, 'updatable_creation.mlmodel')
        print(model_path)
        save_spec(builder.spec, model_path)

        mlmodel = MLModel(model_path)
        self.assertTrue(mlmodel is not None)
        spec = mlmodel.get_spec()
        self.assertTrue(spec.isUpdatable)
        self.assertTrue(spec.neuralNetwork.layers[0].isUpdatable)
        self.assertTrue(
            spec.neuralNetwork.layers[0].innerProduct.weights.isUpdatable)
        self.assertTrue(spec.neuralNetwork.layers[1].isUpdatable)
        self.assertTrue(
            spec.neuralNetwork.layers[1].innerProduct.weights.isUpdatable)

        self.assertTrue(spec.neuralNetwork.updateParams.lossLayers[0].
                        categoricalCrossEntropyLossLayer is not None)
        self.assertTrue(
            spec.neuralNetwork.updateParams.optimizer.sgdOptimizer is not None)

        self.assertTrue(
            _np.isclose(spec.neuralNetwork.updateParams.optimizer.sgdOptimizer.
                        learningRate.defaultValue,
                        1e-2,
                        atol=1e-4))
        self.assertTrue(
            _np.isclose(spec.neuralNetwork.updateParams.optimizer.sgdOptimizer.
                        miniBatchSize.defaultValue,
                        10,
                        atol=1e-4))
        self.assertTrue(
            _np.isclose(spec.neuralNetwork.updateParams.optimizer.sgdOptimizer.
                        momentum.defaultValue,
                        0,
                        atol=1e-8))
        self.assertTrue(
            _np.isclose(spec.neuralNetwork.updateParams.epochs.defaultValue,
                        20,
                        atol=1e-4))

        self.assertTrue(spec.neuralNetwork.updateParams.optimizer.sgdOptimizer.
                        learningRate.range.minValue == 0)
        self.assertTrue(spec.neuralNetwork.updateParams.optimizer.sgdOptimizer.
                        learningRate.range.maxValue == 1)

        self.assertTrue(spec.neuralNetwork.updateParams.optimizer.sgdOptimizer.
                        miniBatchSize.set.values == [10])

        self.assertTrue(spec.neuralNetwork.updateParams.optimizer.sgdOptimizer.
                        momentum.range.minValue == 0)
        self.assertTrue(spec.neuralNetwork.updateParams.optimizer.sgdOptimizer.
                        momentum.range.maxValue == 1)
input_features = [('data', datatypes.Array(*input_dim))]
output_features = [('result', datatypes.Array(*output_dim))]

weights = np.random.rand(1, input_max_size)
bias = np.random.rand(1)

builder = NeuralNetworkBuilder(input_features, output_features)
builder.add_inner_product(name='ip_layer',
                          W=weights,
                          b=bias,
                          input_channels=input_max_size,
                          output_channels=1,
                          has_bias=True,
                          input_name='data',
                          output_name='result')
builder.make_updatable(['ip_layer'])

builder.set_mean_squared_error_loss(name='lossLayer',
                                    input_feature=output_features[0])

optimizerParams = SgdParams(lr=0.01, batch=1)
optimizerParams.set_batch(1, allowed_set=[1, 2, 4, 8, 16, 32])
builder.set_sgd_optimizer(optimizerParams)

builder.set_epochs(16, allowed_set=[2, 4, 8, 16, 32, 64, 128, 256])

#builder.spec = convert_neural_network_spec_weights_to_fp16(builder.spec)

save_spec(builder.spec, '../core/LinearRegressionModel.mlmodel')
lm_head_weights = lm_head_model.lm_head.weight.data.numpy().reshape(
    (1, 50257, 768, 1, 1))

builder.add_inner_product(name="lm_head",
                          input_name="ln_f_scaled",
                          output_name="output_logits",
                          input_channels=768,
                          output_channels=50257,
                          W=lm_head_weights,
                          b=None,
                          has_bias=False)

# compile spec to model
mlmodel = coremltools.models.MLModel(builder.spec)

save_spec(builder.spec, f'../Resources/{model_name}-{sequence_length}.mlmodel')
# model = coremltools.models.MLModel('gpt2.mlmodel')

input_ids = np.zeros(sequence_length)
position_ids = np.arange(sequence_length).astype(np.float)

input_data = {
    'input_ids': input_ids,
    'position_ids': position_ids,
}

# predictions = mlmodel.predict(input_data)["output_logits"]
# equal = np.amax(predictions - mlp_conv_proj.detach().numpy())

print(predictions)
Beispiel #22
0
    def gen_mlmodel2(self, filepattern, out_file):
        reader = tf.train.NewCheckpointReader(filepattern)

        img_shape = self._img_ph.shape.as_list()  # b, h, w, c
        input = [
            ("img", datatypes.Array(img_shape[3], img_shape[1], img_shape[2])),
            ("len_pixel", datatypes.Array(1)),
            ("len_cm", datatypes.Array(1)),
        ]
        output = [
            ("label", datatypes.Array(self._num_classes)),
        ]
        builder = neural_network.NeuralNetworkBuilder(input, output)

        # CoreML has a bug:
        # https://github.com/apple/coremltools/pull/45
        #builder.add_elementwise(name="div_255", input_names=["img"], output_name="div_255", mode="MULTIPLY", alpha=1.0 / 255)
        spec_layer = builder.nn_spec.layers.add()
        spec_layer.name = "div_255"
        spec_layer.input.append("img")
        spec_layer.output.append("div_255")
        spec_layer.multiply.MergeFromString("")
        spec_layer.multiply.alpha = 1.0 / 255

        output_channels = (16, 32, 64, 32)
        kernel_shape = (3, 3, 3, 3)
        rate = (1, 2, 4, 8)
        hidden = {"name": "div_255", "channels": img_shape[3]}
        for i in range(len(output_channels)):
            conv_name = "agent/process_img/conv_2d_{}".format(i)
            if i == 0:
                conv_name = "agent/process_img/conv_2d"
            builder.add_convolution(name=conv_name,
                                    input_name=hidden["name"],
                                    output_name=conv_name,
                                    is_deconv=False,
                                    kernel_channels=hidden["channels"],
                                    output_channels=output_channels[i],
                                    height=kernel_shape[i],
                                    width=kernel_shape[i],
                                    dilation_factors=(rate[i], rate[i]),
                                    has_bias=True,
                                    W=reader.get_tensor(conv_name + "/w"),
                                    b=reader.get_tensor(conv_name + "/b"),
                                    groups=1,
                                    border_mode="same",
                                    stride_height=1,
                                    stride_width=1)
            hidden["name"] = conv_name
            hidden["channels"] = output_channels[i]

            tanh_name = "agent/process_img/tanh_{}".format(i)
            builder.add_activation(name=tanh_name,
                                   non_linearity="TANH",
                                   input_name=hidden["name"],
                                   output_name=tanh_name)
            hidden["name"] = tanh_name

        reduce_name = "reduce_wh"
        builder.add_reduce(name=reduce_name,
                           input_name=hidden["name"],
                           output_name=reduce_name,
                           axis="HW",
                           mode="max")
        hidden["name"] = reduce_name

        embedding_name = "embedding"
        builder.add_elementwise(
            name=embedding_name,
            input_names=[hidden["name"], "len_pixel", "len_cm"],
            output_name=embedding_name,
            mode="CONCAT")
        hidden["name"] = embedding_name
        hidden["channels"] += 2

        output_size = (32, )
        linear_idx = -1
        for opsz in output_size:
            linear_idx += 1
            linear_name = "agent/linear_{}".format(linear_idx)
            if linear_idx == 0:
                linear_name = "agent/linear"
            # CoreML's linear product expects the weights to be of shape
            # (output_size, input_size), but Tensorflow gives (input_size, output_size)
            builder.add_inner_product(
                name=linear_name,
                has_bias=True,
                input_name=hidden["name"],
                input_channels=hidden["channels"],
                output_name=linear_name,
                output_channels=opsz,
                W=np.swapaxes(reader.get_tensor(linear_name + "/w"), 0, 1),
                b=reader.get_tensor(linear_name + "/b"))
            hidden["name"] = linear_name
            hidden["channels"] = opsz

            tanh_name = "agent/tanh_{}".format(i)
            builder.add_activation(name=tanh_name,
                                   non_linearity="TANH",
                                   input_name=hidden["name"],
                                   output_name=tanh_name)
            hidden["name"] = tanh_name

        linear_idx += 1
        linear_name = "agent/linear_{}".format(linear_idx)
        if linear_idx == 0:
            linear_name = "agent/linear"
        builder.add_inner_product(name=linear_name,
                                  has_bias=True,
                                  input_name=hidden["name"],
                                  input_channels=hidden["channels"],
                                  output_name=linear_name,
                                  output_channels=self._num_classes,
                                  W=np.swapaxes(
                                      reader.get_tensor(linear_name + "/w"), 0,
                                      1),
                                  b=reader.get_tensor(linear_name + "/b"))
        hidden["name"] = linear_name
        hidden["channels"] = opsz

        builder.add_softmax(name="softmax",
                            input_name=hidden["name"],
                            output_name="label")

        utils.save_spec(builder.spec, out_file)
from coremltools.models.neural_network.flexible_shape_utils import *
from coremltools.models.utils import load_spec, save_spec

base_path = "../DistractedDriverCreateML/DistractedDriverCreateML/Models/"
spec = load_spec(base_path + "DistractedDriverClassifier_1000_it.mlmodel")

print("Description before adding new sizes")
print(spec.description)

image_sizes = [NeuralNetworkImageSize(480, 640)]
add_enumerated_image_sizes(spec, feature_name='image', sizes=image_sizes)

# img_size_ranges = NeuralNetworkImageSizeRange()
# img_size_ranges.add_height_range((299,480))
# img_size_ranges.add_width_range((299,640))
#update_image_size_range(spec, feature_name='image', size_range=img_size_ranges)

print("Description after adding new sizes")
print(spec.description)
save_spec(spec, base_path + "DistractedDriverClassifier_1000_it_spec.mlmodel")

# Does not work properly with Create ML model with 299... x 299... flexibility
Beispiel #24
0
def _convert_pb_to_mlmodel(
        tf_model_path,
        mlmodel_path,
        output_feature_names,
        input_name_shape_dict={},
        image_input_names=None,
        is_bgr=False,
        red_bias=0.0,
        green_bias=0.0,
        blue_bias=0.0,
        gray_bias=0.0,
        image_scale=1.0,
        class_labels=None,
        predicted_feature_name=None,
        predicted_probabilities_output='',
        add_custom_layers=False,  # type: bool
        custom_conversion_functions={},  # type: Dict[Text, Any]
):

    # Load the TF graph
    with open(tf_model_path, 'rb') as f:
        serialized = f.read()

    tf.reset_default_graph()
    gdef = tf.GraphDef()
    gdef.ParseFromString(serialized)

    with tf.Graph().as_default() as g:
        tf.import_graph_def(gdef, name='')

    sess = tf.Session(graph=g)
    OPS = g.get_operations()

    if 'DecodeJpeg' in [op.type for op in OPS]:
        raise NotImplementedError(
            "Unsupported Op of type: DecodeJpeg. "
            "Kindly refer to the \"examples/inception_v3.ipynb\" notebook, "
            "on the tfcoreml github page, to see how to strip input "
            "pre-processing from the TF graph before conversion to CoreML.")

    # Sort the ops in topological order and check whether the graph has cycles, if yes, error out
    OPS = _topological_sort_ops(OPS)

    SHAPE_DICT = {}  #Tensor name --> shape ({str: list})
    CONSTS = {}  #Const Tensor name --> value
    BLOB_GRAPH = {}  #Blob name to list of ops it feeds into

    # Make Dictionary of Input blob to the list of ops it feeds into
    for op in OPS:
        for inp in op.inputs:
            if inp.name in BLOB_GRAPH:
                BLOB_GRAPH[inp.name].append(op)
        for out in op.outputs:
            if out.name not in BLOB_GRAPH:
                BLOB_GRAPH[out.name] = []

    # Fill in input information
    input_features = []
    output_features = []
    input_feed_dict = dict()  #Input tensors' values
    input_feed_dict2 = dict()  # used later to find skippable ops

    # run through all placeholders
    for op in OPS:
        output_names = set([compat.as_str_any(x.name) for x in op.outputs])
        if op.type == 'Placeholder':
            # Handle placeholders -- all placeholders are inputs
            assert not any(filter(output_names.__contains__, output_feature_names)), \
                ('Output feature cannot be a placeholder')
            input_name = compat.as_str_any(op.outputs[0].name)
            shape = op.outputs[0].get_shape()
            if not (shape.is_fully_defined()
                    or input_name in input_name_shape_dict):
                assert False, ("%s is a placeholder with incomplete shape %s" %
                               (input_name, str(shape)))
            if shape.is_fully_defined():
                shape = shape.as_list()
            else:
                shape = input_name_shape_dict[input_name]

            if len(shape) == 0:  # scalar - use a 1
                input_feed_dict[op.outputs[0]] = 1
                input_feed_dict2[op.outputs[0]] = 1
            else:
                input_feed_dict[op.outputs[0]] = np.random.rand(*shape)
                input_feed_dict2[op.outputs[0]] = 255 * np.random.rand(*shape)

            SHAPE_DICT[input_name] = shape

    # Populate SHAPE_DICT: Dictionary for all tensor blobs in the graph and their shapes
    shapes_wanted = []  # list of output names
    for op in OPS:
        for out in op.outputs:
            shape = out.get_shape()
            if not shape.is_fully_defined():
                shapes_wanted.append((compat.as_str_any(out.name), out))
            else:
                SHAPE_DICT[compat.as_str_any(out.name)] = shape.as_list()

    if len(shapes_wanted) > 0:
        print("Shapes not found for %d tensors. "
              "Executing graph to determine shapes. " % (len(shapes_wanted)))
        tensor_names, tensors = zip(*shapes_wanted)
        tensors_evaluated = sess.run(tensors, feed_dict=input_feed_dict)
        for i in range(len(tensor_names)):
            SHAPE_DICT[tensor_names[i]] = list(tensors_evaluated[i].shape)

    # Fill in output information and CONSTS dictionary
    for op in OPS:
        output_names = set([compat.as_str_any(x.name) for x in op.outputs])
        if any(filter(output_names.__contains__, output_feature_names)):
            # retrieve model outputs
            for output in [
                    x for x in op.outputs if x.name in output_feature_names
            ]:
                #infer shape for Core ML
                tf_shape = SHAPE_DICT[compat.as_str_any(output.name)]
                shape = _infer_coreml_output_shape(tf_shape)
                out_name = output.name
                if shape is None:
                    output_features.append((compat.as_str_any(out_name), None))
                else:
                    output_features.append(
                        (compat.as_str_any(out_name), datatypes.Array(*shape)))
        elif op.type == 'Const':
            # retrieve all consts and store them in dictionary
            const = op.outputs[0]
            CONSTS[compat.as_str_any(const.name)] = sess.run(
                const, feed_dict=input_feed_dict)

    if len(output_features) != len(output_feature_names):
        all_out_names_in_graph = [out_[0] for out_ in output_features]
        for given_out_name in output_feature_names:
            if given_out_name not in all_out_names_in_graph:
                raise ValueError(
                    "output name: {}, was provided, but the Tensorflow graph does not contain a tensor with this name."
                    .format(given_out_name))

    # Find "effectively_constant_ops": ops whose output(s) do not change with different valued Graph level inputs
    # Find "unused_ops" : ops that are not connected to the output(s)
    unused_ops, effectively_constant_ops = _find_unused_ops(
        OPS, sess, output_feature_names, input_feed_dict,
        input_feed_dict2)  # return type: List[str], List[str]
    if not add_custom_layers:
        _check_unsupported_ops(OPS, output_feature_names,
                               effectively_constant_ops + unused_ops)

    # Load all the dictionaries in the object of the class "context"
    context = Context(CONSTS, SHAPE_DICT, OPS, BLOB_GRAPH, output_features)

    # Interpret Input shapes and fill in input information for Core ML
    # (now that SHAPE_DICT and CONSTS are complete)
    sequence_inputs = dict()
    for input_tensor in input_feed_dict:
        input_name = compat.as_str_any(input_tensor.name)
        shape = SHAPE_DICT[input_name]

        if context.use_dfs_shape_infer:
            status = interpret_shape(input_name, context)
        else:
            status = False
        if status:
            print('Automatic shape interpretation succeeded for input blob %s' \
                %(input_name))
            shape = context.shape_dict_rank_4[input_name]

        if len(shape) == 4 and shape[0] != 1:
            sequence_inputs[input_name] = shape[0]

        # if the consumer of input_tensor is an one-hot encoding op,
        # treat it as a sequence.
        consumer_op = input_tensor.consumers()[0]
        if consumer_op.type == 'OneHot':
            shape = [
                1,
            ]
            sequence_inputs[input_name] = -1
        else:
            shape = _infer_coreml_input_shape(shape)
        input_features.append(
            (compat.as_str_any(input_name), datatypes.Array(*shape)))

    # Set classifier flag
    is_classifier = class_labels is not None
    mode = 'classifier' if is_classifier else None

    # Convert the TF graph with builder
    input_features = list(input_features)
    output_features = list(output_features)
    builder = NeuralNetworkBuilder(input_features, output_features, mode=mode)
    context.builder = builder
    context.session = sess
    context.input_feed_dict = input_feed_dict
    context.unused_ops = unused_ops
    context.effectively_constant_ops = effectively_constant_ops
    context.add_custom_layers = add_custom_layers
    context.custom_conversion_functions = custom_conversion_functions
    convert_ops_to_layers(context)
    sess.close()

    #optimizations on the nn spec
    optimize_nn_spec(spec=builder.spec)

    #Add a description for inputs that are sequences
    for i, inputs in enumerate(builder.spec.description.input):
        if inputs.name in sequence_inputs:
            seq_length = sequence_inputs[inputs.name]
            if seq_length == -1:
                builder.spec.description.input[i].shortDescription = \
                  'This input is a sequence'
            else:
                builder.spec.description.input[i].shortDescription = \
                  'This input is a sequence of length ' + str(seq_length)

    # Add image input identifier
    if image_input_names is not None and isinstance(image_input_names,
                                                    _string_types):
        image_input_names = [image_input_names]

    # Replace all input/output blob names with ":" to "__" for compatible
    # auto-generated Objective C / Swift code
    interface_blob_names = []
    for idx, in_blob in enumerate(builder.spec.description.input):
        interface_blob_names.append(in_blob.name)
        builder.spec.description.input[idx].name = in_blob.name.replace(
            ':', '__').replace('/', '__')
    for idx, out_blob in enumerate(builder.spec.description.output):
        interface_blob_names.append(out_blob.name)
        builder.spec.description.output[idx].name = out_blob.name.replace(
            ':', '__').replace('/', '__')

    nn_spec = builder.nn_spec
    for i, spec_layer in enumerate(nn_spec.layers):
        for j, blob in enumerate(spec_layer.input):
            name = spec_layer.input[j]
            if name in interface_blob_names:
                spec_layer.input[j] = name.replace(':',
                                                   '__').replace('/', '__')
        for j, blob in enumerate(spec_layer.output):
            name = spec_layer.output[j]
            if name in interface_blob_names:
                spec_layer.output[j] = name.replace(':',
                                                    '__').replace('/', '__')

    if image_input_names is not None:
        for i, img in enumerate(image_input_names):
            image_input_names[i] = img.replace(':', '__').replace('/', '__')

    # Add classifier classes (if applicable)
    if is_classifier:
        classes_in = class_labels
        if isinstance(classes_in, _string_types):
            import os
            if not os.path.isfile(classes_in):
                raise ValueError("Path to class labels (%s) does not exist." % \
                    classes_in)
            with open(classes_in, 'r') as f:
                classes = f.read()
            classes = classes.splitlines()
        elif type(classes_in) is list:  # list[int or str]
            classes = classes_in
        else:
            raise ValueError('Class labels must be a list of integers / strings,'\
                ' or a file path')

        if predicted_feature_name is not None:
            builder.set_class_labels(
                classes,
                predicted_feature_name=predicted_feature_name,
                prediction_blob=predicted_probabilities_output)
        else:
            builder.set_class_labels(classes)

    # Set pre-processing parameters
    builder.set_pre_processing_parameters(image_input_names=image_input_names,
                                          is_bgr=is_bgr,
                                          red_bias=red_bias,
                                          green_bias=green_bias,
                                          blue_bias=blue_bias,
                                          gray_bias=gray_bias,
                                          image_scale=image_scale)

    utils.save_spec(builder.spec, mlmodel_path)
    print("\n Core ML model generated. Saved at location: %s \n" %
          (mlmodel_path))
    print('Core ML input(s): \n', builder.spec.description.input)
    print('Core ML output(s): \n', builder.spec.description.output)

    # print information about all ops for which custom layers have been added
    if len(context.ops_converted_to_custom_layers) > 0:
        print('\n')
        print("Custom layers have been added to the CoreML model "
              "corresponding to the following ops in the TF graph: ")
        for i, op in enumerate(context.ops_converted_to_custom_layers):
            input_info = []
            for input_ in op.inputs:
                input_info.append(
                    (str(input_.name),
                     context.shape_dict.get(input_.name,
                                            str("Shape not available"))))
            output_info = []
            for output_ in op.outputs:
                output_info.append(
                    (str(output_.name),
                     context.shape_dict.get(output_.name,
                                            str("Shape not available"))))
            print(
                "{}/{}: op type: {}, op input names and shapes: {}, op output names and shapes: {}"
                .format(i + 1, len(context.ops_converted_to_custom_layers),
                        op.type, str(input_info), str(output_info)))

    # Return the protobuf spec
    spec = builder.spec
    return MLModel(spec)
		name=f"{i}_output_ln",
		input_name=f"{i}_block_mlp_conv_proj",
		output_name=f"{i}_output_ln",
		across_channels=True,
		normalize_variance=True,
		epsilon=layer.output_layer_norm.eps
	)
	builder.add_scale(
		name=f"{i}_output_ln_scaled",
		input_name=f"{i}_output_ln",
		output_name=f"{i}_output_ln_scaled",
		W=layer.output_layer_norm.weight.data.numpy().reshape((1, 1, 768, 1, 1)),
		b=layer.output_layer_norm.bias.data.numpy().reshape((1, 1, 768, 1, 1)),
		has_bias=True,
		shape_scale=[768],
		shape_bias=[768]
	)



# compile spec to model
# mlmodel = coremltools.models.MLModel(builder.spec)
# input_data = {
# 	'input_ids': np.array([ 7592, 1010, 2026, 3899, 2003, 10140 ])
# }
# predictions = mlmodel.predict(input_data)["output_logits"]
# print(predictions)


save_spec(builder.spec, f'../Resources/distilbert-{sequence_length}-{steps}.mlmodel')
Beispiel #26
0
builder.add_inner_product(
    name="lm_head",
    input_name="ln_f_scaled",
    output_name="output_logits",
    input_channels=768,
    output_channels=num_tokens,
    W=lm_head_weights,
    b=None,
    has_bias=False,
)

# compile spec to model
mlmodel = coremltools.models.MLModel(builder.spec)

# save_spec(builder.spec, f'../Resources/{model_name}-{sequence_length}-{steps}-2.mlmodel')
save_spec(builder.spec, args.output)
# model = coremltools.models.MLModel('gpt2.mlmodel')

# input_ids = np.zeros(sequence_length)
# position_ids = np.arange(sequence_length).astype(np.float)

# input_data = {
# 	'input_ids': input_ids,
# 	'position_ids': position_ids,
# }

# predictions = mlmodel.predict(input_data)["output_logits"]
# equal = np.amax(predictions - mlp_conv_proj.detach().numpy())

# print(predictions)
def _convert_pb_to_mlmodel(tf_model_path,
                           mlmodel_path,
                           output_feature_names,
                           input_name_shape_dict=None,
                           image_input_names=None,
                           is_bgr=False,
                           red_bias=0.0,
                           green_bias=0.0,
                           blue_bias=0.0,
                           gray_bias=0.0,
                           image_scale=1.0,
                           class_labels=None,
                           predicted_feature_name=None,
                           predicted_probabilities_output=''):
    if input_name_shape_dict is None:
        input_name_shape_dict = {}
    # Load the TF graph
    with open(tf_model_path, 'rb') as f:
        serialized = f.read()

    tf.reset_default_graph()
    gdef = tf.GraphDef()
    gdef.ParseFromString(serialized)

    with tf.Graph().as_default() as g:
        tf.import_graph_def(gdef, name='')

    sess = tf.Session(graph=g)
    OPS = g.get_operations()
    OPS = _topological_sort_ops(OPS)
    _check_unsupported_ops(OPS, output_feature_names)

    SHAPE_DICT = {}  #Tensor name --> shape ({str: list})
    CONSTS = {}  #Const Tensor name --> value
    BLOB_GRAPH = {}  #Blob name to list of ops it feeds into

    # Make Dictionary of Input blob to the list of ops it feeds into
    for op in OPS:
        for inp in op.inputs:
            if inp.name in BLOB_GRAPH:
                BLOB_GRAPH[inp.name].append(op)
        for out in op.outputs:
            if out.name not in BLOB_GRAPH:
                BLOB_GRAPH[out.name] = []

    # Fill in input information
    input_features = []
    output_features = []
    input_feed_dict = dict()  #Input tensors' values

    # run through all placeholders
    for op in OPS:
        output_names = set([compat.as_bytes(x.name) for x in op.outputs])
        if op.type == 'Placeholder':
            # Handle placeholders -- all placeholders are inputs
            assert not filter(output_names.__contains__, output_feature_names), \
                ('Output feature cannot be a placeholder')
            input_name = compat.as_bytes(op.outputs[0].name)
            shape = op.outputs[0].get_shape()
            if not (shape.is_fully_defined()
                    or input_name in input_name_shape_dict):
                assert False, ("%s is a placehoder with incomplete shape %s" %
                               (input_name, str(shape)))
            if shape.is_fully_defined():
                shape = shape.as_list()
            else:
                shape = input_name_shape_dict[input_name]

            if len(shape) == 0:  # scalar - use a 1
                input_feed_dict[op.outputs[0]] = 1
            else:
                input_feed_dict[op.outputs[0]] = np.random.rand(*shape)

            SHAPE_DICT[input_name] = shape

    # Populate SHAPE_DICT:
    # Dictionary for all tensor blobs in the graph and their shapes
    shapes_wanted = []
    for op in OPS:
        for out in op.outputs:
            shape = out.get_shape()
            if not shape.is_fully_defined():
                shapes_wanted.append((compat.as_bytes(out.name), out))
            else:
                SHAPE_DICT[compat.as_bytes(out.name)] = shape.as_list()

    if len(shapes_wanted) > 0:
        print("Shapes not found for %d tensors. "
              "Executing graph to determine shapes. " % (len(shapes_wanted)))
        tensor_names, tensors = zip(*shapes_wanted)
        tensors_evaluated = sess.run(tensors, feed_dict=input_feed_dict)
        for i in range(len(tensor_names)):
            SHAPE_DICT[tensor_names[i]] = list(tensors_evaluated[i].shape)

    # Fill in output information and CONSTS dictionary
    for op in OPS:
        output_names = set([compat.as_bytes(x.name) for x in op.outputs])
        if filter(output_names.__contains__, output_feature_names):
            # retrieve model outputs
            for output in [
                    x for x in op.outputs if x.name in output_feature_names
            ]:
                #infer shape for Core ML
                tf_shape = SHAPE_DICT[compat.as_bytes(output.name)]
                shape = _infer_coreml_output_shape(tf_shape)
                out_name = output.name
                if shape is None:
                    output_features.append((compat.as_bytes(out_name), None))
                else:
                    output_features.append(
                        (compat.as_bytes(out_name), datatypes.Array(*shape)))
        elif op.type == 'Const':
            # retrieve all consts and store them in dictionary
            const = op.outputs[0]
            CONSTS[compat.as_bytes(const.name)] = sess.run(
                const, feed_dict=input_feed_dict)

    assert len(output_features) == len(output_feature_names), (
        'Tensorflow Graph does not contain all the provided Output name(s)')

    # Load all the dictionaries in the object of class context
    context = Context(CONSTS, SHAPE_DICT, OPS, BLOB_GRAPH, output_features)

    # Interpret Input shapes and fill in input information for Core ML
    # (now that SHAPE_DICT and CONSTS are complete)
    sequence_inputs = dict()
    for input_tensor in input_feed_dict:
        input_name = compat.as_bytes(input_tensor.name)
        shape = SHAPE_DICT[input_name]

        if context.use_dfs_shape_infer:
            status = interpret_shape(input_name, context)
        else:
            status = False
        if status:
            print('Automatic shape interpretation succeeded for input blob %s' \
                %(input_name))
            shape = context.shape_dict_rank_4[input_name]

        if len(shape) == 4 and shape[0] != 1:
            sequence_inputs[input_name] = shape[0]

        # if the consumer of input_tensor is an one-hot encoding op,
        # treat it as a sequence.
        consumer_op = input_tensor.consumers()[0]
        if consumer_op.type == 'OneHot':
            shape = [
                1,
            ]
            sequence_inputs[input_name] = -1
        else:
            shape = _infer_coreml_input_shape(shape)
        input_features.append(
            (compat.as_bytes(input_name), datatypes.Array(*shape)))

    # Set classifier flag
    is_classifier = class_labels is not None
    mode = 'classifier' if is_classifier else None

    # Convert the TF graph with builder
    input_features = list(input_features)
    output_features = list(output_features)
    builder = NeuralNetworkBuilder(input_features, output_features, mode=mode)
    context.builder = builder
    context.session = sess
    context.input_feed_dict = input_feed_dict
    convert_ops_to_layers(context)
    sess.close()

    #optimizations on the nn spec
    optimize_nn_spec(builder=builder)

    #Add a description for inputs that are sequences
    for i, inputs in enumerate(builder.spec.description.input):
        if inputs.name in sequence_inputs:
            seq_length = sequence_inputs[inputs.name]
            if seq_length == -1:
                builder.spec.description.input[i].shortDescription = \
                  'This input is a sequence'
            else:
                builder.spec.description.input[i].shortDescription = \
                  'This input is a sequence of length ' + str(seq_length)

    # Add image input identifier
    if image_input_names is not None and isinstance(image_input_names,
                                                    _string_types):
        image_input_names = [image_input_names]

    # Replace all input/output blob names with ":" to "__" for compatible
    # auto-generated Objective C / Swift code
    interface_blob_names = []
    for idx, in_blob in enumerate(builder.spec.description.input):
        interface_blob_names.append(in_blob.name)
        builder.spec.description.input[idx].name = in_blob.name.replace(
            ':', '__').replace('/', '__')
    for idx, out_blob in enumerate(builder.spec.description.output):
        interface_blob_names.append(out_blob.name)
        builder.spec.description.output[idx].name = out_blob.name.replace(
            ':', '__').replace('/', '__')

    nn_spec = builder.nn_spec
    for i, spec_layer in enumerate(nn_spec.layers):
        for j, blob in enumerate(spec_layer.input):
            name = spec_layer.input[j]
            if name in interface_blob_names:
                spec_layer.input[j] = name.replace(':',
                                                   '__').replace('/', '__')
        for j, blob in enumerate(spec_layer.output):
            name = spec_layer.output[j]
            if name in interface_blob_names:
                spec_layer.output[j] = name.replace(':',
                                                    '__').replace('/', '__')

    if image_input_names is not None:
        for i, img in enumerate(image_input_names):
            image_input_names[i] = img.replace(':', '__').replace('/', '__')

    # Add classifier classes (if applicable)
    if is_classifier:
        classes_in = class_labels
        if isinstance(classes_in, _string_types):
            import os
            if not os.path.isfile(classes_in):
                raise ValueError("Path to class labels (%s) does not exist." % \
                    classes_in)
            with open(classes_in, 'r') as f:
                classes = f.read()
            classes = classes.splitlines()
        elif type(classes_in) is list:  # list[int or str]
            classes = classes_in
        else:
            raise ValueError('Class labels must be a list of integers / strings,'\
                ' or a file path')

        if predicted_feature_name is not None:
            builder.set_class_labels(
                classes,
                predicted_feature_name=predicted_feature_name,
                prediction_blob=predicted_probabilities_output)
        else:
            builder.set_class_labels(classes)

    # Set pre-processing paramsters
    builder.set_pre_processing_parameters(image_input_names=image_input_names,
                                          is_bgr=is_bgr,
                                          red_bias=red_bias,
                                          green_bias=green_bias,
                                          blue_bias=blue_bias,
                                          gray_bias=gray_bias,
                                          image_scale=image_scale)

    utils.save_spec(builder.spec, mlmodel_path)
    print("\n Core ML model generated. Saved at location: %s \n" %
          (mlmodel_path))
    print('Core ML input(s): \n', builder.spec.description.input)
    print('Core ML output(s): \n', builder.spec.description.output)

    # Return the protobuf spec
    spec = builder.spec
    return MLModel(spec)
Beispiel #28
0
    def test_updatable_model_creation_ce_adam(self):

        builder = self.create_base_builder()

        builder.add_softmax(name='softmax',
                            input_name='output',
                            output_name='softmax_output')

        builder.set_categorical_cross_entropy_loss(name='cross_entropy',
                                                   input='softmax_output',
                                                   target='target')

        adam_params = AdamParams()
        adam_params.set_batch(value=10, allowed_set=[10, 20])
        builder.set_adam_optimizer(adam_params)
        builder.set_epochs(20)

        model_path = os.path.join(self.model_dir, 'updatable_creation.mlmodel')
        print(model_path)
        save_spec(builder.spec, model_path)

        mlmodel = MLModel(model_path)
        self.assertTrue(mlmodel is not None)
        spec = mlmodel.get_spec()
        self.assertTrue(spec.isUpdatable)
        self.assertTrue(spec.neuralNetwork.layers[0].isUpdatable)
        self.assertTrue(
            spec.neuralNetwork.layers[0].innerProduct.weights.isUpdatable)
        self.assertTrue(spec.neuralNetwork.layers[1].isUpdatable)
        self.assertTrue(
            spec.neuralNetwork.layers[1].innerProduct.weights.isUpdatable)

        self.assertTrue(spec.neuralNetwork.updateParams.lossLayers[0].
                        categoricalCrossEntropyLossLayer is not None)
        self.assertTrue(spec.neuralNetwork.updateParams.optimizer.adamOptimizer
                        is not None)

        self.assertTrue(
            _np.isclose(spec.neuralNetwork.updateParams.optimizer.
                        adamOptimizer.learningRate.defaultValue,
                        1e-2,
                        atol=1e-4))
        self.assertTrue(
            _np.isclose(spec.neuralNetwork.updateParams.optimizer.
                        adamOptimizer.miniBatchSize.defaultValue,
                        10,
                        atol=1e-4))
        self.assertTrue(
            _np.isclose(spec.neuralNetwork.updateParams.optimizer.
                        adamOptimizer.beta1.defaultValue,
                        0.9,
                        atol=1e-4))
        self.assertTrue(
            _np.isclose(spec.neuralNetwork.updateParams.optimizer.
                        adamOptimizer.beta2.defaultValue,
                        0.999,
                        atol=1e-4))
        self.assertTrue(
            _np.isclose(spec.neuralNetwork.updateParams.optimizer.
                        adamOptimizer.eps.defaultValue,
                        1e-8,
                        atol=1e-8))

        self.assertTrue(
            _np.isclose(spec.neuralNetwork.updateParams.epochs.defaultValue,
                        20,
                        atol=1e-4))

        self.assertTrue(spec.neuralNetwork.updateParams.optimizer.
                        adamOptimizer.learningRate.range.minValue == 0)
        self.assertTrue(spec.neuralNetwork.updateParams.optimizer.
                        adamOptimizer.learningRate.range.maxValue == 1)

        self.assertTrue(spec.neuralNetwork.updateParams.optimizer.
                        adamOptimizer.miniBatchSize.set.values == [10, 20])

        self.assertTrue(spec.neuralNetwork.updateParams.optimizer.
                        adamOptimizer.beta1.range.minValue == 0)
        self.assertTrue(spec.neuralNetwork.updateParams.optimizer.
                        adamOptimizer.beta1.range.maxValue == 1)

        self.assertTrue(spec.neuralNetwork.updateParams.optimizer.
                        adamOptimizer.beta2.range.minValue == 0)
        self.assertTrue(spec.neuralNetwork.updateParams.optimizer.
                        adamOptimizer.beta2.range.maxValue == 1)

        self.assertTrue(spec.neuralNetwork.updateParams.optimizer.
                        adamOptimizer.eps.range.minValue == 0)
        self.assertTrue(spec.neuralNetwork.updateParams.optimizer.
                        adamOptimizer.eps.range.maxValue == 1)

        self.assertTrue(
            spec.neuralNetwork.updateParams.epochs.set.values == [20])