Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions backends/nxp/tests/generic_tests/test_aot_example.py
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ def _assert_profiling(


def test_aot_example__mobilenet_v2():
"""Test that mobilenet can be lowered to Neutron backend via `aot_neutron_compile.py` and all ops are delegated."""
"""Test that MobileNetV2 can be lowered to Neutron backend via `aot_neutron_compile.py` and all ops are delegated."""
Comment thread
roman-janik-nxp marked this conversation as resolved.
Resolved

num_random_samples = 1

Expand Down Expand Up @@ -154,7 +154,7 @@ def test_aot_example__mobilenet_v2():


def test_aot_example__mobilenet_v2__profiling():
"""Test that mobilenet_v2 can be lowered to Neutron backend via `aot_neutron_compile.py`, all ops are delegated,
"""Test that MobileNetV2 can be lowered to Neutron backend via `aot_neutron_compile.py`, all ops are delegated,
Comment thread
roman-janik-nxp marked this conversation as resolved.
Resolved
the output model is profilable and ETRecord is generated properly."""

num_random_samples = 1
Expand Down
102 changes: 102 additions & 0 deletions backends/nxp/tests/models/test_mobilenet_v3.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
# Copyright 2026 NXP
#
# This source code is licensed under the BSD-style license found in the
# LICENSE file in the root directory of this source tree.

from functools import partial

import numpy as np

# noinspection PyUnusedImports
import pytest
import torch

from executorch.backends.nxp.tests.dataset_creator import (
FromCalibrationDataDatasetCreator,
)
from executorch.backends.nxp.tests.executorch_pipeline import ModelInputSpec
from executorch.backends.nxp.tests.graph_verifier import (
BaseGraphVerifier,
NonDelegatedNode,
)
from executorch.backends.nxp.tests.model_output_comparator import (
NumericalStatsOutputComparator,
)
from executorch.backends.nxp.tests.nsys_testing import lower_run_compare
from executorch.backends.nxp.tests.use_qat import * # noqa F403
from executorch.examples.nxp.models.mobilenet_v3 import MobileNetV3

BOUNDS_MSE = {
"PTQ": {"channels-last": 7e-03, "channels-first": 8e-03},
"QAT": {"channels-last": 6e-03, "channels-first": 3e-03},
}


@pytest.fixture(autouse=True)
def reseed_model_per_test_run():
torch.manual_seed(23)
np.random.seed(23)


@pytest.mark.parametrize("channels_last", [False, True])
def test_mobilenet_v3_mse_cpu_vs_npu(
mocker,
request,
channels_last,
use_qat,
):
num_samples = 1

mobilenet_v3 = MobileNetV3(
num_samples=num_samples,
use_random_dataset=True,
balanced_dataset=False,
Comment thread
roman-janik-nxp marked this conversation as resolved.
Resolved
)
model = mobilenet_v3.get_eager_model()
dataset = mobilenet_v3.dataset
labels = mobilenet_v3.labels

dataset_creator = FromCalibrationDataDatasetCreator(
dataset, num_examples=num_samples, idx_to_label=labels
)

input_spec = ModelInputSpec(mobilenet_v3.input_shape)
if channels_last:
model.to(memory_format=torch.channels_last)
input_spec.dim_order = torch.channels_last
quant_type_key = "QAT" if use_qat else "PTQ"
format_key = "channels-last" if channels_last else "channels-first"

mse = BOUNDS_MSE[quant_type_key][format_key]
comparator = NumericalStatsOutputComparator(
max_mse_error=mse, is_classification_task=True
)
model_verifier = BaseGraphVerifier(
1,
[
NonDelegatedNode("aten_add_tensor", 13),
NonDelegatedNode("aten_div_tensor", 9),
NonDelegatedNode("aten_clamp_default", 18),
],
)
train_fn = (
partial(mobilenet_v3.train_model_fn, channels_last=channels_last)
if use_qat
else None
)

ref_input_spec = ModelInputSpec(input_spec.shape)
ref_input_spec.dim_order = torch.contiguous_format

lower_run_compare(
model,
[input_spec],
model_verifier,
request,
dataset_creator=dataset_creator,
output_comparator=comparator,
reference_input_spec=[ref_input_spec],
mocker=mocker,
use_qat=use_qat,
train_fn=train_fn,
)
4 changes: 4 additions & 0 deletions examples/nxp/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,10 @@ $ ./examples/nxp/setup.sh
## Supported models
* CifarNet
* MobileNetV2
* MLPerfTinyAnomalyDetection
* MLPerfTinyImageClassification
* MLPerfTinyKeywordSpotting
* MLPerfTinyVisualWakeWords

## PyTorch Model Delegation to Neutron Backend
First we will start with an example script converting the model. This example show the CifarNet model preparation.
Expand Down
21 changes: 21 additions & 0 deletions examples/nxp/models/mobilenet_v3.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# Copyright 2026 NXP
#
# This source code is licensed under the BSD-style license found in the
# LICENSE file in the root directory of this source tree.

import torch

from executorch.examples.models.mobilenet_v3 import MV3Model
from executorch.examples.nxp.models.mobilenet_v2 import MobileNetV2


class MobileNetV3(MobileNetV2):
"""
MobileNet V3 model. Shares most parameters with MobileNet V2.

Calibration data for MobileNet V2 and V3 can be generated by backends/nxp/tests/prepare_calibration_data_mobilenet_v2.py
from Imagenette dataset, a subset of 10 classes from ImageNet dataset the model is trained on.
"""

def _init_eager_model(self) -> torch.nn.Module:
return MV3Model().get_eager_model().eval()
Loading