Upload README.md with huggingface_hub
Browse files
README.md
ADDED
|
@@ -0,0 +1,96 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
---
|
| 2 |
+
license: apache-2.0
|
| 3 |
+
tags:
|
| 4 |
+
- executorch
|
| 5 |
+
- xnnpack
|
| 6 |
+
- pte
|
| 7 |
+
- on-device
|
| 8 |
+
- image-classification
|
| 9 |
+
base_model:
|
| 10 |
+
- google/vit-base-patch16-224
|
| 11 |
+
---
|
| 12 |
+
# ViT-Base/16 ImageNet-1k β ExecuTorch
|
| 13 |
+
|
| 14 |
+
The original Vision Transformer, fine-tuned on ImageNet-1k: an image in, 1000 logits
|
| 15 |
+
out. The reference classifier most tutorials reach for, as four `.pte` files.
|
| 16 |
+
|
| 17 |
+
- **Source**: google/vit-base-patch16-224 β 86M parameters, ViT-Base/16, 12 layers,
|
| 18 |
+
hidden 768, 224x224
|
| 19 |
+
- **License**: apache-2.0
|
| 20 |
+
- **Input**: `pixel_values` `[1, 3, 224, 224]` fp32 β RGB resized to 224x224, scaled to
|
| 21 |
+
[0,1], then normalised with mean=(0.5, 0.5, 0.5) std=(0.5, 0.5, 0.5). **Not** the
|
| 22 |
+
ImageNet statistics; read off this model's own `preprocessor_config.json`.
|
| 23 |
+
- **Output**: logits `[1, 1000]`, in the order of the repo's `config.json` `id2label`.
|
| 24 |
+
Softmax is left to the caller.
|
| 25 |
+
|
| 26 |
+
## Variants
|
| 27 |
+
|
| 28 |
+
| build | file | size (MB) | Mac median (ms)* | labels kept | margin shift at the boundary (logits) |
|
| 29 |
+
|---|---|---|---|---|---|
|
| 30 |
+
| fp32 | `imgcls_vit_base_in1k_xnnpack_fp32.pte` | 346.4 | 34.9 | 24 of 24 | 0.0000 |
|
| 31 |
+
| fp16 | `imgcls_vit_base_in1k_xnnpack_fp16.pte` | 174.6 | 71.0 | 24 of 24 | 0.0117 |
|
| 32 |
+
| Core ML (fp16, iOS) | `imgcls_vit_base_in1k_coreml_all.pte` | 173.6 | **4.0** | 24 of 24 | 0.0547 |
|
| 33 |
+
|
| 34 |
+
\*Mac arm64, single process, median of 10. PyTorch eager fp32 on the same machine is
|
| 35 |
+
**27.5 ms**, so the Core ML build is **6.9x eager**, 100% delegated in one subgraph.
|
| 36 |
+
fp16 is slower than fp32 β XNNPACK emulates it β and is listed only because it halves
|
| 37 |
+
the file.
|
| 38 |
+
|
| 39 |
+
## The int8 build is not published, and correlation would have shipped it
|
| 40 |
+
|
| 41 |
+
Dynamic int8 converts, comes out at **89.7 MB**, runs at 31.7 ms, and reads
|
| 42 |
+
**correlation 0.999814** against fp32 eager. It keeps the fp32 label on all 24
|
| 43 |
+
photographs. Every number a conversion normally reports says ship it.
|
| 44 |
+
|
| 45 |
+
The number that decides says otherwise:
|
| 46 |
+
|
| 47 |
+
```
|
| 48 |
+
worst margin shift at the decision boundary 0.1856 logits
|
| 49 |
+
closest photograph's distance to a decision 0.0900 logits
|
| 50 |
+
```
|
| 51 |
+
|
| 52 |
+
The build's error is **twice the distance that separates the closest of these
|
| 53 |
+
photographs from being called something else**. It cannot be trusted to agree with fp32
|
| 54 |
+
on an image the model is not already sure about.
|
| 55 |
+
|
| 56 |
+
**What changed is the number of classes, not the quantisation.** The same recipe on
|
| 57 |
+
this shelf's two-class ViT head shifts the margin by 1.4795 logits and passes
|
| 58 |
+
comfortably β because with two classes the closest photograph sits **7.88 logits** from
|
| 59 |
+
the decision. Put a thousand classes in competition and the runner-up is usually a near
|
| 60 |
+
tie: median distance **1.09 logits**, minimum **0.09**. The error budget collapses by
|
| 61 |
+
roughly two orders of magnitude while the error itself does not.
|
| 62 |
+
|
| 63 |
+
So the honest form of the rule is not *int8 is fine on ViTs*. It is: **an error is
|
| 64 |
+
small or large only relative to the decision it has to survive, and a 1000-way decision
|
| 65 |
+
has almost no room.**
|
| 66 |
+
|
| 67 |
+
## How these were checked
|
| 68 |
+
|
| 69 |
+
Label agreement alone would not have separated any of these builds β all four keep
|
| 70 |
+
24 of 24. So each photograph is also walked along the gradient of its class margin
|
| 71 |
+
(the winner's lead over its closest rival) until the margin crosses zero, bisected onto
|
| 72 |
+
it, and the builds compared *there*. All 6 boundary inputs were reached for every build;
|
| 73 |
+
a walk that never leaves the class is reported as not measured rather than as a zero.
|
| 74 |
+
|
| 75 |
+
The boundary inputs are perturbed photographs, not natural ones. They exercise the
|
| 76 |
+
arithmetic where it decides something; they are not a claim about accuracy on real data.
|
| 77 |
+
|
| 78 |
+
## What is not tested here
|
| 79 |
+
|
| 80 |
+
The 24 photographs are this shelf's calibration set β street scenes, animals, people,
|
| 81 |
+
general views β not an ImageNet validation split. What is verified is **fidelity to the
|
| 82 |
+
fp32 model**, not the model's own top-1 accuracy. These files reproduce whatever the
|
| 83 |
+
upstream checkpoint does.
|
| 84 |
+
|
| 85 |
+
Worth knowing before you build on it: on these images the fp32 model's own confidence
|
| 86 |
+
runs from **0.022 to 0.501** (median). A 1000-class classifier is rarely sure, and a
|
| 87 |
+
caller that thresholds on probability should read that row before picking a threshold.
|
| 88 |
+
|
| 89 |
+
## Conversion
|
| 90 |
+
|
| 91 |
+
```bash
|
| 92 |
+
python convert/export_imgcls.py vit_base_in1k
|
| 93 |
+
python convert/check_imgcls.py vit_base_in1k int8
|
| 94 |
+
```
|
| 95 |
+
|
| 96 |
+
(conversion scripts: [executorch-models](https://github.com/john-rocky/executorch-models))
|