|
Download README.md from Arm/esrgan-int8-xnnpack-executorch-graviton-g4: direct link, hf CLI and curl.
- Browser
- Download file 7.51 kB
-
https://huggingface.co/Arm/esrgan-int8-xnnpack-executorch-graviton-g4/resolve/d42b422895581f13472312e024c6c38c0f70c8ce/README.md
- Command line
-
hf download hf://Arm/esrgan-int8-xnnpack-executorch-graviton-g4@d42b422895581f13472312e024c6c38c0f70c8ce/README.md
-
curl -L -o README.md https://huggingface.co/Arm/esrgan-int8-xnnpack-executorch-graviton-g4/resolve/d42b422895581f13472312e024c6c38c0f70c8ce/README.md
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 | |