Unlock this feature

This feature isn’t part of your plan yet

Contact sales to get upgraded to the full DevStudio experience.

Unlock this feature

This feature isn't part of your plan yet.

Model Demo: DDRNet Classification


NOTE: The Jupyter Notebook below is included in the Chimera SDK and can be run interactively by running the following CLI command:

$ quadric sdk notebook

From the Jupyter Notebook window in your browser, select the notebook named /quadric/sdk-cli/examples/models/ddrnet/classify/ddrnet_classify.ipynb.


DDRNet Classification

Abstract

The deep dual-resolution networks (DDRNets) are specially designed for efficient backbones of real-time semantic segmentation. The proposed networks are composed of two deep branches between which multiple bilateral fusions are performed. Additionally, a new contextual information extractor named Deep Aggregation Pyramid Pooling Module (DAPPM) is designed to enlarge effective receptive fields and fuse multi-scale context based on low-resolution feature maps. This method achieves a new state-of-the-art trade-off between accuracy and speed on both Cityscapes and CamVid dataset as backbones of Semantic segmentation.

For further details, please visit the following paper.

This notebook experiments DDRNets for classification.

Set-Up

!pip3 install -r ../../../requirements.txt -q
WARNING: Running pip as the 'root' user can result in broken permissions and conflicting behaviour with the system package manager. It is recommended to use a virtual environment instead: https://pip.pypa.io/warnings/venv

import matplotlib.pyplot as plt
import gdown
from matplotlib.gridspec import GridSpec
import numpy as np
import onnx
import onnxsim
import os
from pathlib import Path
from PIL import Image
import random
import torch
from torch.utils.data import Subset
from torchvision.transforms import Compose, Normalize, ToTensor, Resize
import urllib
import zipfile

from tvm.contrib.epu.chimera_job.chimera_job import ChimeraJob
import tvm.contrib.epu.chimera_job.constants as sdk_constants
from examples.models.zoo.zoo_utils import download_file, onnx_check_and_simplify
from sdk_cli.lib.inference import InferenceEngine, batch_inference
from sdk_cli.lib.quantize import (
    QuantizedONNXModel,
    quantize_onnx_model,
)
from sdk_cli.utils.datasets import ImageNet_Mini_Quadric
from sdk_cli.utils.datasets.ImageNet import (
    IMAGENET_1K_NORMALIZATION_PARAMETERS,
    OPTIMIZED_IMAGENET_1K_LABELS,
)

DDRNet.pytorch Github Clone

basename = Path("DDRNet")

## Install DDRNet.
if basename.exists():
    print(f"Existing {basename} is used.")
else:
    url = "https://github.com/ydhongHIT/DDRNet/archive/refs/heads/main.zip"
    filename = Path(url).name

    download_file(url, filename)
    with zipfile.ZipFile(filename, "r") as fd:
        fd.extractall()

    os.rename(f"{basename}-{Path(url).stem}", basename)
    print(f"{basename} is installed.")

## Make symbolic links for later experiment.
symlink_list = ["classification"]

for sym_path in symlink_list:
    if not Path(sym_path).is_symlink():
        os.symlink(basename / sym_path, Path(sym_path).name)
        print(f"{sym_path} is symbolic")
DDRNet is installed.
classification is symbolic

Model Load

In this notebook, we are going to use DDRNet_23_slim for the experiment.

from classification import DDRNet_23_slim

MODEL_NAME = "DDRNet23_slim_classify"

weights_folder = Path("pretrained_models")
weights_folder.mkdir(exist_ok=True)
weights = weights_folder / "DDRNet23s_imagenet.pth"

DDRNet23s_imagenet_pth_url = "https://drive.google.com/uc?id=1mg5tMX7TJ9ZVcAiGSB4PEihPtrJyalB4"
gdown.download(DDRNet23s_imagenet_pth_url, str(weights), quiet=False)

model = DDRNet_23_slim.get_model()
model.load_state_dict(torch.load(weights, map_location="cpu"))
Downloading...
From: https://drive.google.com/uc?id=1mg5tMX7TJ9ZVcAiGSB4PEihPtrJyalB4
To: /quadric/sdk-cli/examples/models/ddrnet/classify/pretrained_models/DDRNet23s_imagenet.pth
100%|█████████████████████████████████████| 30.4M/30.4M [00:00<00:00, 73.8MB/s]





<All keys matched successfully>

ONNX Export

onnx_file = f"{MODEL_NAME}.onnx"

dataset_input_size = (224, 224)
dummy_data = torch.randn(1, 3, *dataset_input_size[::-1], requires_grad=False)

input_edges = ["inputs0"]
output_edges = ["outputs0"]

## Export the model
torch.onnx.export(
    model,  # model being run
    dummy_data,  # model input (or a tuple for multiple inputs)
    onnx_file,  # where to save the model (can be a file or file-like object)
    export_params=True,  # store the trained parameter weights inside the model file
    do_constant_folding=True,  # whether to execute constant folding for optimization
    opset_version=sdk_constants.DEFAULT_ONNX_OPSET,
    input_names=input_edges,  # the model's input names
    output_names=output_edges,  # the model's output names
)

onnx_model = onnx_check_and_simplify(onnx.load(onnx_file))
onnx.save(onnx_model, onnx_file)

print(f"ONNX is exported and simplified as {onnx_file}")
ONNX is exported and simplified as DDRNet23_slim_classify.onnx

Quantization

dataset_mean = IMAGENET_1K_NORMALIZATION_PARAMETERS.channel_means
dataset_std = IMAGENET_1K_NORMALIZATION_PARAMETERS.channel_standard_deviations

transforms = Compose(
    [
        Resize(dataset_input_size[0]),
        ToTensor(),
        Normalize(dataset_mean, dataset_std),
    ]
)

imagenet_dataset = ImageNet_Mini_Quadric.Dataset(transform=transforms)
subset_of_dataset = Subset(imagenet_dataset, range(100))

quantized_onnx_model: QuantizedONNXModel = quantize_onnx_model(
    onnx_file,
    subset_of_dataset,
    asymmetric_activation=False,
)
print(
    f"quantized onnx: {quantized_onnx_model.model_path}, tranges file: {quantized_onnx_model.tensor_ranges_path}"
)
2026-09-22 03:03 - INFO - sdk - quantize - ONNX model shapes inferred.
2026-09-22 03:03 - DEBUG - sdk - quantize - Forcing node types: []
2026-09-22 03:03 - DEBUG - sdk - quantize - ONNX Node types excluded from quantization: ['Softmax', 'Sigmoid', 'QuadricCustomOp']
2026-09-22 03:03 - DEBUG - sdk - quantize - ONNX Node names excluded from quantization: []
2026-09-22 03:03 - INFO - sdk - quantize - Starting quantization...
WARNING:root:Please use QuantFormat.QDQ for activation type QInt8 and weight type QInt8. Or it will lead to bad performance on x64.
2026-09-22 03:03 - INFO - sdk - quantize - Quantization completed! Quantized model saved to /quadric/sdk-cli/examples/models/ddrnet/classify/DDRNet23_slim_classify_OpSet16_optimized_sym_int8_q.onnx
2026-09-22 03:03 - INFO - sdk - quantize - ONNX full precision model size: 28.89MB
2026-09-22 03:03 - INFO - sdk - quantize - ONNX quantized model size: 7.32MB
2026-09-22 03:03 - INFO - sdk - quantize - ONNX model shapes inferred.
2026-09-22 03:03 - INFO - sdk - quantize - ONNX Model with well-defined shapes has been saved at `/quadric/sdk-cli/examples/models/ddrnet/classify/DDRNet23_slim_classify_OpSet16_optimized_sym_int8_q_shaped.onnx`.
2026-09-22 03:03 - DEBUG - sdk - quantize - Checking for FLOAT/FLOAT16 types...
2026-09-22 03:03 - INFO - sdk - quantize - Checking for remaining FLOAT/FLOAT16 types.
2026-09-22 03:03 - INFO - sdk - quantize - Model still has FLOAT/FLOAT16 types after quantization. Creating ranges for floating point tensors using calibration data...
2026-09-22 03:03 - INFO - sdk - quantize - Saved computed tensor ranges to /quadric/sdk-cli/examples/models/ddrnet/classify/DDRNet23_slim_classify_OpSet16_optimized_sym_int8_q_shaped.tranges.
2026-09-22 03:03 - INFO - sdk - quantize - 
╒══════════════════════════════════════════════════════════════════════════════════════════════════════════════════╤═════════════════════════════════════════════════════════════════════════════════════════════════════════════════════╕
 Quantized ONNX Model                                                                                              Tensor Ranges File                                                                                                  
╞══════════════════════════════════════════════════════════════════════════════════════════════════════════════════╪═════════════════════════════════════════════════════════════════════════════════════════════════════════════════════╡
 /quadric/sdk-cli/examples/models/ddrnet/classify/DDRNet23_slim_classify_OpSet16_optimized_sym_int8_q_shaped.onnx  /quadric/sdk-cli/examples/models/ddrnet/classify/DDRNet23_slim_classify_OpSet16_optimized_sym_int8_q_shaped.tranges 
╘══════════════════════════════════════════════════════════════════════════════════════════════════════════════════╧═════════════════════════════════════════════════════════════════════════════════════════════════════════════════════╛


quantized onnx: /quadric/sdk-cli/examples/models/ddrnet/classify/DDRNet23_slim_classify_OpSet16_optimized_sym_int8_q_shaped.onnx, tranges file: /quadric/sdk-cli/examples/models/ddrnet/classify/DDRNet23_slim_classify_OpSet16_optimized_sym_int8_q_shaped.tranges

Compilation

cgc_job = ChimeraJob(
    model_p=str(quantized_onnx_model.model_path),
    trange_file=str(quantized_onnx_model.tensor_ranges_path),
)
cgc_job.compile(quiet=True)
print(cgc_job)
╒═════════════════════╤══════════════════════════════════════════════════════════════════════════════════════════════════════════════════╕
│ Module Name         │ DDRNet23_slim_classify_OpSet16_optimized_sym_int8_q_shaped_QC_U_1d7_16MB_4kB_128GBps_128GBps_16_OFF_x1_x1        │
├─────────────────────┼──────────────────────────────────────────────────────────────────────────────────────────────────────────────────┤
│ ONNX File           │ /quadric/sdk-cli/examples/models/ddrnet/classify/DDRNet23_slim_classify_OpSet16_optimized_sym_int8_q_shaped.onnx │
├─────────────────────┼──────────────────────────────────────────────────────────────────────────────────────────────────────────────────┤
│ Product Target      │ QC-U                                                                                                             │
├─────────────────────┼──────────────────────────────────────────────────────────────────────────────────────────────────────────────────┤
│ Number of Cores     │ 1                                                                                                                │
├─────────────────────┼──────────────────────────────────────────────────────────────────────────────────────────────────────────────────┤
│ ISS Clock Frequency │ 1.700                                                                                                            │
├─────────────────────┼──────────────────────────────────────────────────────────────────────────────────────────────────────────────────┤
│ L2M Size            │ 16MB                                                                                                             │
├─────────────────────┼──────────────────────────────────────────────────────────────────────────────────────────────────────────────────┤
│ LRM Size            │ 4kB                                                                                                              │
├─────────────────────┼──────────────────────────────────────────────────────────────────────────────────────────────────────────────────┤
│ External Read BW    │ 128GBps                                                                                                          │
├─────────────────────┼──────────────────────────────────────────────────────────────────────────────────────────────────────────────────┤
│ External Write BW   │ 128GBps                                                                                                          │
├─────────────────────┼──────────────────────────────────────────────────────────────────────────────────────────────────────────────────┤
│ MACS per PE         │ 16                                                                                                               │
├─────────────────────┼──────────────────────────────────────────────────────────────────────────────────────────────────────────────────┤
│ Max L2M             │ 3.606MB                                                                                                          │
├─────────────────────┼──────────────────────────────────────────────────────────────────────────────────────────────────────────────────┤
│ Max LRM             │ 2.438kB                                                                                                          │
├─────────────────────┼──────────────────────────────────────────────────────────────────────────────────────────────────────────────────┤
│ Max Temp Ext Bytes  │ 0.000MB                                                                                                          │
├─────────────────────┼──────────────────────────────────────────────────────────────────────────────────────────────────────────────────┤
│ Network GMACs       │ 0.973                                                                                                            │
╘═════════════════════╧══════════════════════════════════════════════════════════════════════════════════════════════════════════════════╛

╒════╤════════╤══════════╤══════════════════╤══════════════════════════╤═══════╕
│    │ Type   │ Name     │ shape            │ type                     │ mse   │
╞════╪════════╪══════════╪══════════════════╪══════════════════════════╪═══════╡
│  0 │ Input  │ inputs0  │ [1, 3, 224, 224] │ tensor[FixedPoint32<29>] │ n/a   │
├────┼────────┼──────────┼──────────────────┼──────────────────────────┼───────┤
│  1 │ Output │ outputs0 │ [1, 1000]        │ tensor[FixedPoint32<26>] │ n/a   │
╘════╧════════╧══════════╧══════════════════╧══════════════════════════╧═══════╛

Demo

Inference

random.seed(38)
NUM_IMAGES = 3
all_images_dict = dict(random.sample(imagenet_dataset.imgs, NUM_IMAGES))
all_image_paths = list(all_images_dict.keys())

engines = {
    InferenceEngine.CHIMERA_ORT_INT8: cgc_job,
    InferenceEngine.CHIMERA_ISS_INT8: cgc_job,
}

all_images = []
for image_path in all_image_paths:
    all_images.append(np.expand_dims(transforms(Image.open(image_path)), axis=0))

outputs_per_inference_engine = {}
THREADS = min(NUM_IMAGES, 6)
for inference_engine, engine in engines.items():
    outputs_per_inference_engine[inference_engine] = batch_inference(
        inference_engine,
        engine,
        all_images,
        threads=THREADS,
    )
2026-09-22 03:04 - WARNING - epu - chimera_job - ORT is not threadsafe -- forcing single threaded batch execution
100%|████████████████████████████████████████████| 3/3 [00:00<00:00, 11.05it/s]
Processing: 100%|████████████████████████████████| 3/3 [00:04<00:00,  1.49s/it]

Run Statistics

print(cgc_job)
cgc_job.plot_run_statistics()
╒═════════════════════╤══════════════════════════════════════════════════════════════════════════════════════════════════════════════════╕
 Module Name          DDRNet23_slim_classify_OpSet16_optimized_sym_int8_q_shaped_QC_U_1d7_16MB_4kB_128GBps_128GBps_16_OFF_x1_x1        
├─────────────────────┼──────────────────────────────────────────────────────────────────────────────────────────────────────────────────┤
 ONNX File            /quadric/sdk-cli/examples/models/ddrnet/classify/DDRNet23_slim_classify_OpSet16_optimized_sym_int8_q_shaped.onnx 
├─────────────────────┼──────────────────────────────────────────────────────────────────────────────────────────────────────────────────┤
 Product Target       QC-U                                                                                                             
├─────────────────────┼──────────────────────────────────────────────────────────────────────────────────────────────────────────────────┤
 Number of Cores      1                                                                                                                
├─────────────────────┼──────────────────────────────────────────────────────────────────────────────────────────────────────────────────┤
 ISS Clock Frequency  1.700                                                                                                            
├─────────────────────┼──────────────────────────────────────────────────────────────────────────────────────────────────────────────────┤
 L2M Size             16MB                                                                                                             
├─────────────────────┼──────────────────────────────────────────────────────────────────────────────────────────────────────────────────┤
 LRM Size             4kB                                                                                                              
├─────────────────────┼──────────────────────────────────────────────────────────────────────────────────────────────────────────────────┤
 External Read BW     128GBps                                                                                                          
├─────────────────────┼──────────────────────────────────────────────────────────────────────────────────────────────────────────────────┤
 External Write BW    128GBps                                                                                                          
├─────────────────────┼──────────────────────────────────────────────────────────────────────────────────────────────────────────────────┤
 MACS per PE          16                                                                                                               
├─────────────────────┼──────────────────────────────────────────────────────────────────────────────────────────────────────────────────┤
 Max L2M              3.606MB                                                                                                          
├─────────────────────┼──────────────────────────────────────────────────────────────────────────────────────────────────────────────────┤
 Max LRM              2.438kB                                                                                                          
├─────────────────────┼──────────────────────────────────────────────────────────────────────────────────────────────────────────────────┤
 Max Temp Ext Bytes   0.000MB                                                                                                          
├─────────────────────┼──────────────────────────────────────────────────────────────────────────────────────────────────────────────────┤
 Network GMACs        0.973                                                                                                            
╘═════════════════════╧══════════════════════════════════════════════════════════════════════════════════════════════════════════════════╛

╒════╤════════╤══════════╤══════════════════╤══════════════════════════╤═══════╕
     Type    Name      shape             type                      mse   
╞════╪════════╪══════════╪══════════════════╪══════════════════════════╪═══════╡
  0  Input   inputs0   [1, 3, 224, 224]  tensor[FixedPoint32<29>]  n/a   
├────┼────────┼──────────┼──────────────────┼──────────────────────────┼───────┤
  1  Output  outputs0  [1, 1000]         tensor[FixedPoint32<26>]  0.015 
╘════╧════════╧══════════╧══════════════════╧══════════════════════════╧═══════╛

Post-ISS Report 1.7 GHz ***
Fully placed-and-routed gate simulation: 
╒══════════════════════════════════╤═════════╕
 Latency (ms)                      0.29    
├──────────────────────────────────┼─────────┤
 FPS                               3490.46 
├──────────────────────────────────┼─────────┤
 Average Power @ 3nm SSGNP (mW)    2334.12 
├──────────────────────────────────┼─────────┤
 FPS per Watt @ 3nm SSGNP (FPS/W)  1495.41 
├──────────────────────────────────┼─────────┤
 Ext Rd Bytes (MB)                 7.97    
├──────────────────────────────────┼─────────┤
 Ext Wr Bytes (MB)                 0.00    
├──────────────────────────────────┼─────────┤
 Avg Ext Rd BW (GBps)              27.18   
├──────────────────────────────────┼─────────┤
 Avg Ext Wr BW (GBps)              0.01    
├──────────────────────────────────┼─────────┤
 MAC Utilization                   12.19%  
╘══════════════════════════════════╧═════════╛
*** Data generated using 7nm SSGNP gatesim and scaled to 3nm

[SDK-CLI] : TotalCycles: 487,042
[SDK-CLI] : Executions/second: 3,490.46

compute      : ▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇ 105.491K
data_array   : ▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇ 90.144K
mac          : ▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇ 155.961K
data_external:  5.808K
data_ocm     : ▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇ 129.584K

for more information check run directory: /quadric/sdk-cli/examples/models/ddrnet/classify/ccl_build/DDRNet23_slim_classify_OpSet16_optimized_sym_int8_q_shaped_QC_U_1d7_16MB_4kB_128GBps_128GBps_16_OFF_x1_x1/run/20260922_030455_5954a2


2026-09-22 03:05 - INFO - epu - chimera_job - Combined plots generated and saved to: 
/quadric/sdk-cli/examples/models/ddrnet/classify/ccl_build/DDRNet23_slim_classify_OpSet16_optimized_sym_int8_q_shaped_QC_U_1d7_16MB_4kB_128GBps_128GBps_16_OFF_x1_x1/run/20260922_030455_5954a2/data/DDRNet23_slim_classify_OpSet16_optimized_sym_int8_q_shaped_QC_U_1d7_16MB_4kB_128GBps_128GBps_16_OFF_x1_x1.combined.png





'/quadric/sdk-cli/examples/models/ddrnet/classify/ccl_build/DDRNet23_slim_classify_OpSet16_optimized_sym_int8_q_shaped_QC_U_1d7_16MB_4kB_128GBps_128GBps_16_OFF_x1_x1/run/20260922_030455_5954a2/data'

Display Inference Results

%matplotlib inline

softmax = torch.nn.Softmax(dim=1)

for i, image_path in enumerate(all_image_paths):
    idx, ax = 0, []
    fig = plt.figure(constrained_layout=True, figsize=(12, 4))
    gs = GridSpec(2, 3, figure=fig)

    ax.append(fig.add_subplot(gs[:, 0]))
    ax.append(fig.add_subplot(gs[0, 1]))
    ax.append(fig.add_subplot(gs[1, 1], sharex=ax[1]))

    ax[idx].imshow(np.array(Image.open(image_path)))
    ax[idx].set_title(
        f"{all_images_dict[image_path]}: {OPTIMIZED_IMAGENET_1K_LABELS.class_map[all_images_dict[image_path]]}"
    )
    ax[idx].set_axis_off()

    for inference_engine in engines.keys():
        idx += 1
        outputs = outputs_per_inference_engine[inference_engine][i][0]
        top_5 = torch.topk(softmax(torch.from_numpy(outputs)), k=5)
        top5_scores = np.array(list(top_5.values[0])) * 100
        top5_labels = [
            OPTIMIZED_IMAGENET_1K_LABELS.class_map[int(class_id)] for class_id in top_5.indices[0]
        ]

        if idx == 1:
            bar_color = "deepskyblue"
            plt.setp(ax[idx].get_xticklabels(), visible=False)
        else:
            bar_color = "darkviolet"

        ax[idx].barh(top5_labels, top5_scores, color=bar_color)
        ax[idx].set_title(f"{MODEL_NAME} Top 5 (%): {str(inference_engine)}")
    fig.show()

Citation

@article{hong2021deep,
  title={Deep Dual-resolution Networks for Real-time and Accurate Semantic Segmentation of Road Scenes},
  author={Hong, Yuanduo and Pan, Huihui and Sun, Weichao and Jia, Yisong},
  journal={arXiv preprint arXiv:2101.06085},
  year={2021}
}

@article{pan2022deep,
  title={Deep Dual-Resolution Networks for Real-Time and Accurate Semantic Segmentation of Traffic Scenes},
  author={Pan, Huihui and Hong, Yuanduo and Sun, Weichao and Jia, Yisong},
  journal={IEEE Transactions on Intelligent Transportation Systems},
  year={2022},
  publisher={IEEE}
}

Sign in to your account

Don't have an account? 
By signing in, you are agreeing to our Terms of Use and Privacy Policy.
Quadric // One architecture. Every algorithm.

Develop.

Simulate.

Profile.

Collaborate.