def get_shape(inp: dict):
    if 'shape' not in inp:
        raise ValueError("shape key not found")
    shape = inp['shape']
    default_shape = inp.get('default_shape')
    if not isinstance(shape, list):
        raise ValueError("shape should be list, found {}, type {}".format(
            shape, type(shape)))

    list_items = 0
    for s in shape:
        if isinstance(s, list):
            list_items += 1
    is_enum_shapes = list_items == len(shape)
    # All or None shapes element shoud be list
    # Regular shape [1,20,20,3]
    # Enumerated Shapes [[1,20,20,3], [1,40,40,3]]
    user_assert(list_items == 0 or is_enum_shapes,
                "Can not parse shape {}".format(shape))
    if is_enum_shapes:
        enum_shapes = [transform_shape(s) for s in shape]
        print("enum_shapes:", enum_shapes)
        return ct.EnumeratedShapes(shapes=enum_shapes, default=default_shape)
    # Replace string elements such as "1..50" with RangeDim(1, 50)
    tx_shape = transform_shape(shape)
    print("tx_shape:", tx_shape)
    return ct.Shape(shape=tx_shape, default=default_shape)
    def test_multiarray_input_enumerated(self, convert_to):
        if convert_to == "mlprogram" and ct.utils._macos_version() < (12, 0):
            return

        example_input = torch.rand(1, 3, 50, 50) * 100
        traced_model = torch.jit.trace(TestConvModule().eval(), example_input)

        input_shape = ct.EnumeratedShapes(shapes=[[1, 3, 25,
                                                   25], [1, 3, 50, 50],
                                                  [1, 3, 67, 67]],
                                          default=[1, 3, 67, 67])
        model = ct.convert(traced_model,
                           inputs=[ct.TensorType(shape=input_shape)],
                           convert_to=convert_to)

        spec = model.get_spec()
        assert list(spec.description.input[0].type.multiArrayType.shape) == [
            1, 3, 67, 67
        ]
        assert list(spec.description.input[0].type.multiArrayType.
                    enumeratedShapes.shapes[0].shape) == [1, 3, 67, 67]
        assert len(spec.description.input[0].type.multiArrayType.
                   enumeratedShapes.shapes) == 3
        _assert_torch_coreml_output_shapes(model, spec, traced_model,
                                           example_input)
Пример #3
0
def _convert_to_mil_type(shape, dtype, name: str):
    mil_shape = shape
    if _check_enumerated_shape(shape):
        mil_shape = ct.EnumeratedShapes(shape)
    ml_type = TensorType(shape=mil_shape, dtype=torch_to_mil_types[dtype])
    ml_type.name = name
    return ml_type
    def test_image_input_enumerated(self, convert_to):
        if convert_to == "mlprogram" and ct.utils._macos_version() < (12, 0):
            return

        example_input = torch.rand(1, 3, 50, 50) * 255
        traced_model = torch.jit.trace(TestConvModule().eval(), example_input)

        input_shape = ct.EnumeratedShapes(shapes=[[1, 3, 25,
                                                   25], [1, 3, 50, 50],
                                                  [1, 3, 67, 67]],
                                          default=[1, 3, 67, 67])
        model = ct.convert(traced_model,
                           inputs=[ct.ImageType(shape=input_shape)],
                           convert_to=convert_to)

        spec = model.get_spec()
        assert spec.description.input[0].type.imageType.width == 67
        assert spec.description.input[0].type.imageType.height == 67
        assert len(spec.description.input[0].type.imageType.enumeratedSizes.
                   sizes) == 3
        assert spec.description.input[0].type.imageType.enumeratedSizes.sizes[
            0].width == 25
        assert spec.description.input[0].type.imageType.enumeratedSizes.sizes[
            0].height == 25
        _assert_torch_coreml_output_shapes(model,
                                           spec,
                                           traced_model,
                                           example_input,
                                           is_image_input=True)
Пример #5
0
    def test_mil_enumerated_image(self):
        enumerated_shapes = tuple([(1, 3, 10, 10), (1, 3, 10, 20),
                                   (1, 3, 10, 30)])
        input_shape = [
            ct.ImageType(name="x",
                         shape=ct.EnumeratedShapes(shapes=enumerated_shapes))
        ]
        mlmodel = ct.convert(self.basic_network,
                             source="milinternal",
                             convert_to="mlprogram",
                             inputs=input_shape)
        input_spec = mlmodel.get_spec().description.input
        assert len(input_spec) == 1, "1 input expected, got {} instead".format(
            len(input_spec))
        assert input_spec[
            0].name == "x", "input name in MLModel is {}, 'x' is expected".format(
                input_spec[0].name)
        assert input_spec[0].type.WhichOneof(
            "Type") == "imageType", "Expected imageType, got {}".format(
                input_spec[0].type.WhichOneof("Type"))
        assert input_spec[0].type.imageType.WhichOneof(
            "SizeFlexibility"
        ) == "enumeratedSizes", "Expected enumeratedShapes in ShapeFlexibility"

        spec_H = input_spec[0].type.imageType.height
        spec_W = input_spec[0].type.imageType.width
        assert spec_H == 10 and spec_W == 10, "expected [H, W] == [10, 10], got [{}, {}] instead".format(
            spec_H, spec_W)

        spec_enumerated_shapes = set()
        for enumerated in input_spec[0].type.imageType.enumeratedSizes.sizes:
            spec_enumerated_shapes.add(
                tuple([1, 3, enumerated.height, enumerated.width]))
        assert spec_enumerated_shapes == set(
            enumerated_shapes), "Enumerated shape mismatch"
Пример #6
0
    def test_torch_enumerated_shapes():
        import torch

        in_channels = 3
        out_channels = 2
        kernel_size = 3

        class TestModule(torch.nn.Module):
            def __init__(self):
                super(TestModule, self).__init__()
                self.conv = torch.nn.Conv2d(in_channels, out_channels,
                                            kernel_size)

            def forward(self, x):
                return self.conv(x)

        model = TestModule()
        model.eval()

        example_input = torch.randn(1, 3, 28, 28)
        traced_model = torch.jit.trace(model, example_input)

        shapes = [(1, 3, 28, 28), (1, 3, 56, 56)]
        enumerated_shapes = ct.EnumeratedShapes(shapes=shapes)
        tensor_input = ct.TensorType(name="input", shape=enumerated_shapes)

        mlmodel = ct.convert(
            traced_model,
            inputs=[tensor_input],
        )

        if ct.utils._is_macos():
            result = mlmodel.predict(
                {"input": example_input.detach().numpy().astype(np.float32)},
                useCPUOnly=True,
            )

            # Verify outputs
            expected = model(example_input)
            name = list(result.keys())[0]
            np.testing.assert_allclose(result[name],
                                       expected.detach().numpy(),
                                       rtol=1e-3,
                                       atol=1e-4)

            # Test (1, 3, 56, 56) shape (can't verify numerical parity with Torch
            # which doesn't support enumerated shape)
            test_input_x = np.random.rand(*shapes[1]).astype(np.float32)
            results = mlmodel.predict({"input": test_input_x})

            # Test with a wrong shape
            with pytest.raises(
                    RuntimeError,
                    match=r"not compatible with the model\'s feature"):
                test_input_x = np.random.rand(1, 3, 29, 29).astype(np.float32)
                results = mlmodel.predict({"input": test_input_x})
Пример #7
0
 def test_torch_image_enumerated_shapes():
     import torch
     import torchvision
     torch_model = torchvision.models.mobilenet_v2().features
     torch_model.eval()
     example_input = torch.rand(1, 3, 256, 256)
     traced_model = torch.jit.trace(torch_model, example_input)
     input_shapes = ct.EnumeratedShapes(shapes=[(1, 3, 256, 256), (1, 3, 224, 224)])
     image_input = ct.ImageType(shape=input_shapes,
                                bias=[-1, -1, -1], scale=1 / 127)
     model = ct.convert(traced_model, inputs=[image_input])
     assert model is not None
     spec = model.get_spec()
     assert len(spec.description.input[0].type.imageType.enumeratedSizes.sizes) == 2
Пример #8
0
 def test_tf2_image_enumerated_shapes():
     import tensorflow as tf
     keras_model = tf.keras.applications.MobileNetV2(
         input_shape=(None, None, 3,),
         classes=1000,
         include_top=False,
     )
     input_shapes = ct.EnumeratedShapes(shapes=[(1, 192, 192, 3), (1, 224, 224, 3)])
     image_input = ct.ImageType(shape=input_shapes,
                                bias=[-1,-1,-1], scale=1/127)
     model = ct.convert(keras_model, inputs=[image_input])
     assert model is not None
     spec = model.get_spec()
     assert len(spec.description.input[0].type.imageType.enumeratedSizes.sizes) == 2
Пример #9
0
    def test_tf2keras_enumerated_shapes():
        # Test examples in https://coremltools.readme.io/docs/flexible-inputs
        import tensorflow as tf

        input_shape = (28, 28, 3)
        # None denotes seq_len dimension
        x = tf.keras.Input(shape=input_shape, name="input")
        C_out = 2
        kHkW = 3
        y = tf.keras.layers.Conv2D(C_out,
                                   kHkW,
                                   activation='relu',
                                   input_shape=input_shape)(x)
        keras_model = tf.keras.Model(inputs=[x], outputs=[y])

        # One RangeDim shared by two inputs
        shapes = [(1, 28, 28, 3), (1, 56, 56, 3)]
        enumerated_shapes = ct.EnumeratedShapes(shapes=shapes)
        tensor_input = ct.TensorType(name="input", shape=enumerated_shapes)
        mlmodel = ct.convert(keras_model, inputs=[tensor_input])

        # Test (1, 28, 28, 3) shape
        test_input_x = np.random.rand(*shapes[0]).astype(np.float32)
        expected_val = keras_model([test_input_x])
        if ct.utils._is_macos():
            results = mlmodel.predict({"input": test_input_x})
            np.testing.assert_allclose(results["Identity"],
                                       expected_val,
                                       rtol=1e-2)

            # Test (1, 56, 56, 3) shape (can't verify numerical parity with Keras
            # which doesn't support enumerated shape)
            test_input_x = np.random.rand(*shapes[1]).astype(np.float32)
            results = mlmodel.predict({"input": test_input_x})

            # Test with a wrong shape
            with pytest.raises(
                    RuntimeError,
                    match=r"not compatible with the model\'s feature"):
                test_input_x = np.random.rand(1, 29, 29, 3).astype(np.float32)
                results = mlmodel.predict({"input": test_input_x})
Пример #10
0
    def test_mil_enumerated_multiarray_with_default(self):
        enumerated_shapes = tuple([(1, 3, 10, 10), (1, 3, 10, 20),
                                   (1, 3, 10, 30)])
        input_shape = [
            ct.TensorType(name="x",
                          shape=ct.EnumeratedShapes(shapes=enumerated_shapes,
                                                    default=(1, 3, 10, 30)))
        ]
        mlmodel = ct.convert(self.basic_network,
                             source="milinternal",
                             convert_to="mlprogram",
                             inputs=input_shape)
        input_spec = mlmodel.get_spec().description.input
        assert len(input_spec) == 1, "1 input expected, got {} instead".format(
            len(input_spec))
        assert input_spec[
            0].name == "x", "input name in MLModel is {}, 'x' is expected".format(
                input_spec[0].name)
        assert input_spec[0].type.WhichOneof(
            "Type"
        ) == "multiArrayType", "Expected multiArrayType, got {}".format(
            input_spec[0].type.WhichOneof("Type"))
        assert input_spec[0].type.multiArrayType.WhichOneof(
            "ShapeFlexibility"
        ) == "enumeratedShapes", "Expected enumeratedShapes in ShapeFlexibility"

        spec_default_shape = [
            s for s in input_spec[0].type.multiArrayType.shape
        ]
        spec_enumerated_shapes = set()
        for enumerated in input_spec[
                0].type.multiArrayType.enumeratedShapes.shapes:
            spec_enumerated_shapes.add(tuple([s for s in enumerated.shape]))
        assert spec_default_shape == [
            1, 3, 10, 30
        ], "Expected default shape to be [1, 3, 10, 10], got {} instead".format(
            str(spec_default_shape))
        assert spec_enumerated_shapes == set(
            enumerated_shapes), "Enumerated shape mismatch"