xref: /aosp_15_r20/external/executorch/backends/xnnpack/test/models/inception_v3.py (revision 523fa7a60841cd1ecfb9cc4201f1ca8b03ed023a)
1# Copyright (c) Meta Platforms, Inc. and affiliates.
2# All rights reserved.
3#
4# This source code is licensed under the BSD-style license found in the
5# LICENSE file in the root directory of this source tree.
6
7import unittest
8
9import torch
10from executorch.backends.xnnpack.test.tester import Tester
11from executorch.backends.xnnpack.test.tester.tester import Quantize
12from torchvision import models
13
14
15class TestInceptionV3(unittest.TestCase):
16    ic3 = models.inception_v3(weights="IMAGENET1K_V1").eval()  # noqa
17    model_inputs = (torch.randn(1, 3, 224, 224),)
18
19    all_operators = {
20        "executorch_exir_dialects_edge__ops_aten_addmm_default",
21        "executorch_exir_dialects_edge__ops_aten_add_Tensor",
22        "executorch_exir_dialects_edge__ops_aten_cat_default",
23        "executorch_exir_dialects_edge__ops_aten_convolution_default",
24        "executorch_exir_dialects_edge__ops_aten_max_pool2d_with_indices_default",
25        # "executorch.exir.dialects.edge._ops.aten.avg_pool2d.default", Currently do not have avg_pool2d partitioned
26        "executorch_exir_dialects_edge__ops_aten_mean_dim",
27        "executorch_exir_dialects_edge__ops_aten__native_batch_norm_legit_no_training_default",
28        "executorch_exir_dialects_edge__ops_aten_permute_copy_default",
29        "executorch_exir_dialects_edge__ops_aten_relu_default",
30    }
31
32    def test_fp32_ic3(self):
33
34        (
35            Tester(self.ic3, self.model_inputs)
36            .export()
37            .to_edge_transform_and_lower()
38            .check(["torch.ops.higher_order.executorch_call_delegate"])
39            .check_not(list(self.all_operators))
40            .to_executorch()
41            .serialize()
42            .run_method_and_compare_outputs()
43        )
44
45    @unittest.skip("T187799178: Debugging Numerical Issues with Calibration")
46    def _test_qs8_ic3(self):
47        # Quantization fuses away batchnorm, so it is no longer in the graph
48        ops_after_quantization = self.all_operators - {
49            "executorch_exir_dialects_edge__ops_aten__native_batch_norm_legit_no_training_default",
50        }
51
52        (
53            Tester(self.ic3, self.model_inputs)
54            .quantize()
55            .export()
56            .to_edge_transform_and_lower()
57            .check(["torch.ops.higher_order.executorch_call_delegate"])
58            .check_not(list(ops_after_quantization))
59            .to_executorch()
60            .serialize()
61            .run_method_and_compare_outputs()
62        )
63
64    # TODO: Delete and only used calibrated test after T187799178
65    def test_qs8_ic3_no_calibration(self):
66        # Quantization fuses away batchnorm, so it is no longer in the graph
67        ops_after_quantization = self.all_operators - {
68            "executorch_exir_dialects_edge__ops_aten__native_batch_norm_legit_no_training_default",
69        }
70
71        (
72            Tester(self.ic3, self.model_inputs)
73            .quantize(Quantize(calibrate=False))
74            .export()
75            .to_edge_transform_and_lower()
76            .check(["torch.ops.higher_order.executorch_call_delegate"])
77            .check_not(list(ops_after_quantization))
78            .to_executorch()
79            .serialize()
80            .run_method_and_compare_outputs()
81        )
82