aorabdel's picture
Sync model repo (text/metadata)
d42b422 verified
|
Raw
History Blame
7.51 kB
---
library_name: executorch
license: apache-2.0
base_model: kadirnar/RRDB_PSNR_x4
base_model_relation: quantized
tags:
- image-to-image
- esrgan
- int8
- quantized
- xnnpack
- arm
- executorch
- edge-ai
- urban100
- super-resolution
pipeline_tag: image-to-image
datasets:
- urban100
metrics:
- psnr
model-index:
- name: esrgan-int8-xnnpack-executorch-graviton-g4
results:
- task:
type: image-to-image
name: Super Resolution
dataset:
type: urban100
name: Urban100
split: validation
args:
evaluation_samples: 100
metrics:
- type: psnr
value: 26.81
name: PSNR (dB)
---
# ESRGAN x4 INT8 (ExecuTorch + XNNPACK)
This is an INT8-quantized version of [ESRGAN RRDBNet](https://github.com/xinntao/ESRGAN) optimized for edge deployment on ARM devices using [ExecuTorch](https://github.com/pytorch/executorch) with the XNNPACK backend. The model was quantized using PT2E static symmetric per-channel quantization and exported to the `.pte` format for efficient inference on ARM Cortex-A processors (AWS Graviton, mobile ARM, embedded).
The PSNR-oriented weights (`RRDB_PSNR_x4.pth`) from [kadirnar/RRDB_PSNR_x4](https://huggingface.co/kadirnar/RRDB_PSNR_x4) are used β€” the L1-trained high-PSNR variant whose metrics are directly comparable to standard SR benchmark figures.
## Key Highlights
Compared to the FP32 baseline:
- **2.76x smaller** β€” 64.07 MB to 23.18 MB
- **2.44x faster** β€” 1763 ms to 724 ms on AWS Graviton (Neoverse-V2)
- **Minimal quality loss** β€” βˆ’0.22 dB PSNR on Urban100
## Model Details
### Model Description
Quantized version of ESRGAN (Enhanced Super-Resolution Generative Adversarial Network) with a 23-block RRDBNet backbone. The model performs 4x bicubic super-resolution on urban scene images, optimized for efficient edge inference via INT8 quantization and the ExecuTorch runtime.
- **Developed by:** Xintao Wang et al. (ESRGAN), Marvik AI (quantization & optimization)
- **Model type:** Super Resolution (4x upscaling)
- **License:** Apache-2.0
- **Base model:** [ESRGAN RRDBNet](https://github.com/xinntao/ESRGAN) β€” quantized, not finetuned
### Model Sources
- **Repository:** https://github.com/xinntao/ESRGAN
- **Pretrained weights:** https://huggingface.co/kadirnar/RRDB_PSNR_x4
## How to Get Started with the Model
### Install dependencies
```bash
pip install executorch torch torchvision pillow numpy
```
### Download the model
```python
from huggingface_hub import hf_hub_download
model_path = hf_hub_download(
repo_id="Arm/esrgan-int8-xnnpack-executorch-graviton-g4",
filename="esrgan-x4-int8-executorch.pte",
)
```
### Run inference
```bash
python example.py
```
Or use the core inference loop directly:
```python
from executorch.runtime import Runtime
from PIL import Image
from torchvision import transforms
# Load model
runtime = Runtime.get()
program = runtime.load_program("esrgan-x4-int8-executorch.pte")
method = program.load_method("forward")
# Preprocess (no normalization β€” model expects raw [0, 1] values)
image = Image.open("input.jpg").convert("RGB")
to_tensor = transforms.ToTensor()
input_tensor = to_tensor(image).unsqueeze(0) # [1, 3, H, W]
# Run a single 128x128 tile
tile = input_tensor[:, :, :128, :128]
outputs = method.execute([tile])
# outputs[0] shape: [1, 3, 512, 512] β€” the 4x super-resolved tile
# See example.py for full tiled inference on arbitrary-size images
```
## Evaluation
### Testing Data, Factors & Metrics
#### Testing Data
Evaluated on 100 images from Urban100 (validation split). Urban100 is a standard super-resolution benchmark consisting of urban scenes with repetitive structures, specifically chosen to challenge SR models on fine detail reconstruction.
#### Metrics
- **PSNR (Peak Signal-to-Noise Ratio, dB)** β€” measures pixel-level fidelity between the super-resolved output and the ground-truth high-resolution image; higher is better
- **SSIM (Structural Similarity Index)** β€” measures perceived structural similarity; higher is better
### Results
#### Quality
| Metric | FP32 (Original) | INT8 (Optimized) | Delta |
|:---|:---:|:---:|:---:|
| PSNR (dB) | 27.03 | 26.81 | βˆ’0.22 dB |
| SSIM | 0.8176 | 0.8109 | βˆ’0.007 |
#### Efficiency
| Metric | FP32 (Original) | INT8 (Optimized) | Improvement |
|:---|:---:|:---:|:---:|
| Model Size (.pte) | 64.07 MB | 23.18 MB | **2.76x smaller** |
| Graviton Latency (mean) | 1763 ms | 724 ms | **2.44x faster** |
| Graviton Latency (p50) | 1763 ms | 704 ms | **2.50x faster** |
| Graviton Latency (p90) | 1765 ms | 780 ms | **2.26x faster** |
| Graviton Cold Start | 66.3 ms | 36.7 ms | **1.81x faster** |
*Latency measured on AWS Graviton G4 (Neoverse-V2, 16 cores) with ExecuTorch 1.1.0, XNNPACK + KleidiAI backend, batch size 1, 10 warmup runs + 100 measurement runs.*
## Technical Specifications
### Objective
4x single-image super-resolution from bicubic-degraded low-resolution inputs, targeting urban scenes with repetitive structures.
### Quantization
- **Method**: PT2E Static Quantization via XNNPACKQuantizer
- **Precision**: INT8 symmetric, per-channel
- **Backend**: XNNPACK
- **Layers kept in FP32**: upsampling layers (`upconv1`, `upconv2`, `HRconv`, `conv_last`) and the first 3 RRDB body blocks (`body.0`–`body.2`) to preserve output fidelity
- **Calibration**: 100 images from Urban100 (random subset, patch mode)
### Export Pipeline
1. Load pretrained FP32 RRDBNet with PSNR-oriented weights from HuggingFace (`kadirnar/RRDB_PSNR_x4`)
2. Capture model graph via `torch.export` at fixed 128Γ—128 tile size
3. Insert quantization observers (XNNPACKQuantizer, skipping upsampling + first 3 body blocks)
4. Calibrate with 100 Urban100 patches
5. Convert observers to Q/DQ pairs
6. Post-quantization graph surgery (remove spurious Q/DQ pairs from `cat` nodes in FP32 body blocks)
7. Export to ExecuTorch `.pte` with XNNPACK backend
### Preprocessing
| Property | Value |
|---|---|
| Input shape | `[1, 3, 128, 128]` (BCHW, single tile) |
| Data type | float32 |
| Value range | [0.0, 1.0] |
| Color space | RGB |
**Steps**:
1. Convert PIL image to float32 tensor via `ToTensor()` (maps [0, 255] β†’ [0, 1])
2. For images larger than 128Γ—128: split into overlapping 128Γ—128 tiles with 8-pixel overlap; each tile is processed independently
**Normalization**: None required β€” the model expects raw [0, 1] pixel values.
### Postprocessing
| Property | Value |
|---|---|
| Output shape | `[1, 3, 512, 512]` per tile (4x upscaled) |
| Output format | Float32 RGB tensor, values may exceed [0, 1] before clamping |
**Steps**:
1. Clamp output tensor to [0, 1]
2. For tiled inputs: accumulate tile outputs into a full-resolution canvas, averaging overlapping regions
3. Convert to uint8 for saving (`* 255`, round, cast)
## Known Limitations
- Evaluated on 100 images from Urban100 β€” a benchmark focused on urban/architectural scenes; performance on natural landscapes or faces may differ
- Fixed tile size of 128Γ—128: images must be at least 128Γ—128; the tiling inference handles arbitrary sizes automatically
- Input images are not aspect-ratio padded β€” tiles are extracted at stride `tile_size - overlap` with edge tiles placed at the image boundary
- XNNPACK operator coverage is approximately 49%: upsampling, LeakyReLU, and some transpose operations fall back to non-XNNPACK kernels; latency figures reflect this mixed execution