|
19 | 19 | import coremltools as ct |
20 | 20 | from coremltools import RangeDim, Shape, TensorType |
21 | 21 | from coremltools._deps import _HAS_TORCH_AUDIO, _HAS_TORCH_VISION, version_lt |
| 22 | +from coremltools.converters.mil.backend.mil.load import BlobWriter |
22 | 23 | from coremltools.converters.mil import testing_reqs |
23 | 24 | from coremltools.converters.mil.frontend.torch.utils import ( |
24 | 25 | NUM_TO_TORCH_DTYPE, |
|
41 | 42 | ModuleWrapper, |
42 | 43 | TorchBaseTest, |
43 | 44 | contains_op, |
| 45 | + convert_to_mlmodel, |
44 | 46 | export_torch_model_to_frontend, |
45 | 47 | frontends, |
46 | 48 | generate_input_data, |
@@ -7110,6 +7112,52 @@ def test_bmm(self, compute_unit, backend, frontend): |
7110 | 7112 | [shape_x, shape_y], model, compute_unit=compute_unit, backend=backend, frontend=frontend |
7111 | 7113 | ) |
7112 | 7114 |
|
| 7115 | + @pytest.mark.parametrize("frontend", frontends) |
| 7116 | + @pytest.mark.parametrize( |
| 7117 | + "convert_to, minimum_deployment_target", |
| 7118 | + [("neuralnetwork", None), ("mlprogram", ct.target.iOS15)], |
| 7119 | + ) |
| 7120 | + def test_mm_with_int32_constant_weight( |
| 7121 | + self, frontend, convert_to, minimum_deployment_target |
| 7122 | + ): |
| 7123 | + class TestModel(torch.nn.Module): |
| 7124 | + def __init__(self): |
| 7125 | + super().__init__() |
| 7126 | + self.register_buffer( |
| 7127 | + "weight", torch.randint(low=-9, high=9, size=(4, 4), dtype=torch.int32) |
| 7128 | + ) |
| 7129 | + |
| 7130 | + def forward(self, x): |
| 7131 | + return torch.mm(x, self.weight) |
| 7132 | + |
| 7133 | + model = TestModel().eval() |
| 7134 | + input_data = torch.randint(low=-9, high=9, size=(4, 4), dtype=torch.int32) |
| 7135 | + model_spec = export_torch_model_to_frontend(model, input_data, frontend) |
| 7136 | + |
| 7137 | + if convert_to == "mlprogram" and BlobWriter is None: |
| 7138 | + pytest.skip("BlobWriter not loaded") |
| 7139 | + |
| 7140 | + mlmodel = convert_to_mlmodel( |
| 7141 | + model_spec, |
| 7142 | + [input_data], |
| 7143 | + backend=(convert_to, "fp32"), |
| 7144 | + converter_input_type=[ |
| 7145 | + ct.TensorType(name="x", shape=input_data.shape, dtype=np.int32) |
| 7146 | + ], |
| 7147 | + compute_unit=ct.ComputeUnit.CPU_ONLY, |
| 7148 | + minimum_deployment_target=minimum_deployment_target, |
| 7149 | + ) |
| 7150 | + |
| 7151 | + ops = get_op_types_in_program(mlmodel._mil_program) |
| 7152 | + assert "matmul" in ops |
| 7153 | + assert "linear" not in ops |
| 7154 | + |
| 7155 | + if ct.utils._is_macos() and ct.models.model._MLModelProxy is not None: |
| 7156 | + output_name = mlmodel._spec.description.output[0].name |
| 7157 | + expected = model(input_data).numpy() |
| 7158 | + prediction = mlmodel.predict({"x": input_data.numpy()})[output_name] |
| 7159 | + np.testing.assert_array_equal(prediction.astype(np.int32), expected) |
| 7160 | + |
7113 | 7161 | @pytest.mark.parametrize( |
7114 | 7162 | "compute_unit, backend, frontend", |
7115 | 7163 | itertools.product( |
|
0 commit comments