| --- |
| license: apache-2.0 |
| tags: |
| - executorch |
| - xnnpack |
| - pte |
| - on-device |
| - image-classification |
| base_model: |
| - google/vit-base-patch16-224 |
| --- |
| # ViT-Base/16 ImageNet-1k β ExecuTorch |
|
|
| The original Vision Transformer, fine-tuned on ImageNet-1k: an image in, 1000 logits |
| out. The reference classifier most tutorials reach for, as four `.pte` files. |
|
|
| - **Source**: google/vit-base-patch16-224 β 86M parameters, ViT-Base/16, 12 layers, |
| hidden 768, 224x224 |
| - **License**: apache-2.0 |
| - **Input**: `pixel_values` `[1, 3, 224, 224]` fp32 β RGB resized to 224x224, scaled to |
| [0,1], then normalised with mean=(0.5, 0.5, 0.5) std=(0.5, 0.5, 0.5). **Not** the |
| ImageNet statistics; read off this model's own `preprocessor_config.json`. |
| - **Output**: logits `[1, 1000]`, in the order of the repo's `config.json` `id2label`. |
| Softmax is left to the caller. |
|
|
| ## Variants |
|
|
| | build | file | size (MB) | Mac median (ms)* | labels kept | margin shift at the boundary (logits) | |
| |---|---|---|---|---|---| |
| | fp32 | `imgcls_vit_base_in1k_xnnpack_fp32.pte` | 346.4 | 34.9 | 24 of 24 | 0.0000 | |
| | fp16 | `imgcls_vit_base_in1k_xnnpack_fp16.pte` | 174.6 | 71.0 | 24 of 24 | 0.0117 | |
| | Core ML (fp16, iOS) | `imgcls_vit_base_in1k_coreml_all.pte` | 173.6 | **4.0** | 24 of 24 | 0.0547 | |
|
|
| \*Mac arm64, single process, median of 10. PyTorch eager fp32 on the same machine is |
| **27.5 ms**, so the Core ML build is **6.9x eager**, 100% delegated in one subgraph. |
| fp16 is slower than fp32 β XNNPACK emulates it β and is listed only because it halves |
| the file. |
| |
| ## The int8 build is not published, and correlation would have shipped it |
| |
| Dynamic int8 converts, comes out at **89.7 MB**, runs at 31.7 ms, and reads |
| **correlation 0.999814** against fp32 eager. It keeps the fp32 label on all 24 |
| photographs. Every number a conversion normally reports says ship it. |
| |
| The number that decides says otherwise: |
| |
| ``` |
| worst margin shift at the decision boundary 0.1856 logits |
| closest photograph's distance to a decision 0.0900 logits |
| ``` |
| |
| The build's error is **twice the distance that separates the closest of these |
| photographs from being called something else**. It cannot be trusted to agree with fp32 |
| on an image the model is not already sure about. |
| |
| **What changed is the number of classes, not the quantisation.** The same recipe on |
| this shelf's two-class ViT head shifts the margin by 1.4795 logits and passes |
| comfortably β because with two classes the closest photograph sits **7.88 logits** from |
| the decision. Put a thousand classes in competition and the runner-up is usually a near |
| tie: median distance **1.09 logits**, minimum **0.09**. The error budget collapses by |
| roughly two orders of magnitude while the error itself does not. |
| |
| So the honest form of the rule is not *int8 is fine on ViTs*. It is: **an error is |
| small or large only relative to the decision it has to survive, and a 1000-way decision |
| has almost no room.** |
| |
| ## How these were checked |
| |
| Label agreement alone would not have separated any of these builds β all four keep |
| 24 of 24. So each photograph is also walked along the gradient of its class margin |
| (the winner's lead over its closest rival) until the margin crosses zero, bisected onto |
| it, and the builds compared *there*. All 6 boundary inputs were reached for every build; |
| a walk that never leaves the class is reported as not measured rather than as a zero. |
| |
| The boundary inputs are perturbed photographs, not natural ones. They exercise the |
| arithmetic where it decides something; they are not a claim about accuracy on real data. |
| |
| ## What is not tested here |
| |
| The 24 photographs are this shelf's calibration set β street scenes, animals, people, |
| general views β not an ImageNet validation split. What is verified is **fidelity to the |
| fp32 model**, not the model's own top-1 accuracy. These files reproduce whatever the |
| upstream checkpoint does. |
| |
| Worth knowing before you build on it: on these images the fp32 model's own confidence |
| runs from **0.022 to 0.501** (median). A 1000-class classifier is rarely sure, and a |
| caller that thresholds on probability should read that row before picking a threshold. |
| |
| ## Conversion |
| |
| ```bash |
| python convert/export_imgcls.py vit_base_in1k |
| python convert/check_imgcls.py vit_base_in1k int8 |
| ``` |
| |
| (conversion scripts: [executorch-models](https://github.com/john-rocky/executorch-models)) |
| |