Upload README.md with huggingface_hub
Browse files
README.md
ADDED
|
@@ -0,0 +1,102 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
---
|
| 2 |
+
license: apache-2.0
|
| 3 |
+
tags:
|
| 4 |
+
- executorch
|
| 5 |
+
- xnnpack
|
| 6 |
+
- pte
|
| 7 |
+
- on-device
|
| 8 |
+
- object-detection
|
| 9 |
+
- zero-shot-object-detection
|
| 10 |
+
base_model:
|
| 11 |
+
- IDEA-Research/grounding-dino-tiny
|
| 12 |
+
---
|
| 13 |
+
# Grounding DINO tiny — ExecuTorch (open-vocabulary detection)
|
| 14 |
+
|
| 15 |
+
You name the thing in text and it finds it. No fixed class list: the prompt is
|
| 16 |
+
"a person. a car. a bicycle. a dog." today and "a fire hydrant. a traffic cone."
|
| 17 |
+
on the next call, with the same weights.
|
| 18 |
+
|
| 19 |
+
```
|
| 20 |
+
(pixel_values (1,3,640,640), input_ids (1,32), token_type_ids (1,32),
|
| 21 |
+
attention_mask (1,32), text_masks (1,32,32), position_ids (1,32))
|
| 22 |
+
-> scores (1,900,256), boxes (1,900,4)
|
| 23 |
+
```
|
| 24 |
+
|
| 25 |
+
| build | file | MB | scores corr | boxes corr | Mac ms* |
|
| 26 |
+
|---|---|---|---|---|---|
|
| 27 |
+
| fp32 | `grounding_dino_tiny_xnnpack_fp32.pte` | 690.3 | 0.999833 | 0.998992 | 584.1 |
|
| 28 |
+
|
| 29 |
+
\*Mac arm64, single process, median of 5 — a reference point for relative cost, not a
|
| 30 |
+
device number. Torch eager fp32 on the same machine: 376.7 ms. XNNPACK delegate
|
| 31 |
+
coverage 63.0% (3503/5559 ops).
|
| 32 |
+
|
| 33 |
+
**There is no Core ML build.** The graph reshapes to rank 6 and Core ML's ceiling is 5 —
|
| 34 |
+
the same wall RAFT-small hits with its correlation volume. This one is XNNPACK only, and
|
| 35 |
+
the same file runs on Android and on the Mac.
|
| 36 |
+
|
| 37 |
+
## Running it
|
| 38 |
+
|
| 39 |
+
**1. The image.** RGB, divide by 255, ImageNet normalise (mean .485/.456/.406, std
|
| 40 |
+
.229/.224/.225), resize to 640×640.
|
| 41 |
+
|
| 42 |
+
**2. The prompt.** Lower-case phrases separated by `". "`, ending in a period. Tokenise
|
| 43 |
+
with the repo's tokenizer at `padding="max_length", max_length=32`. `input_ids`,
|
| 44 |
+
`token_type_ids` and `attention_mask` are int64 `(1,32)`.
|
| 45 |
+
|
| 46 |
+
**3. The two text tensors that are not the tokenizer's.** `text_masks` and `position_ids`
|
| 47 |
+
come from transformers' `generate_masks_with_special_tokens_and_transfer_map(input_ids)`
|
| 48 |
+
— the mask that keeps each phrase's tokens attending only to their own phrase. It is
|
| 49 |
+
built with `cummax`/`cummin`, which are not in the Core ATen opset, so it is lifted out of
|
| 50 |
+
the graph and passed in — `text_masks` is **bool** `(1,32,32)` and `position_ids` is int64
|
| 51 |
+
`(1,32)`, and ExecuTorch will not coerce either. Both depend on `input_ids` alone, never
|
| 52 |
+
on the image, so compute them once when the user types the prompt. The model stays
|
| 53 |
+
open-vocabulary; only the token count is fixed.
|
| 54 |
+
|
| 55 |
+
**4. Reading the answer.** `boxes` is `(cx, cy, w, h)` normalised to the input square.
|
| 56 |
+
`scores[0, q, t]` is how much query `q` points at text position `t`. A detection is a
|
| 57 |
+
query whose best score clears your threshold (0.3 is a reasonable default), and its label
|
| 58 |
+
is the `input_ids` token at that argmax.
|
| 59 |
+
|
| 60 |
+
Two things about that text axis. It is always 256 wide — the model's `max_text_len` — no
|
| 61 |
+
matter how long your prompt is, and every column past your prompt's tokens is exactly 0.
|
| 62 |
+
And the peak often lands on an article rather than the noun: a query for a person may
|
| 63 |
+
argmax on the `a` of "a person". Map the winning token back to the **phrase** it belongs
|
| 64 |
+
to, the way transformers' own post-processor does, rather than reading the single token
|
| 65 |
+
as the label.
|
| 66 |
+
|
| 67 |
+
## What is measured
|
| 68 |
+
|
| 69 |
+
The number that decides is detections, not correlation. Against eager PyTorch on five
|
| 70 |
+
street photographs at threshold 0.3:
|
| 71 |
+
|
| 72 |
+
**26 of 26 of eager's detections are reproduced**, each at IoU > 0.5 with the same prompt
|
| 73 |
+
token. That includes a photo with 17 detections in it.
|
| 74 |
+
|
| 75 |
+
```bash
|
| 76 |
+
python convert/audit_int8.py grounding_dino_tiny --variant fp32
|
| 77 |
+
python convert/verify_cards.py grounding_dino_tiny
|
| 78 |
+
```
|
| 79 |
+
|
| 80 |
+
Correlation is in the table above for completeness, and the boxes figure (0.998992) is
|
| 81 |
+
below this shelf's usual fp32 bar of 0.999. It is not measuring what it looks like: the
|
| 82 |
+
largest box differences are on queries that fire at nothing, where a coordinate is free to
|
| 83 |
+
wander without changing any answer. The detection count is what was gated on.
|
| 84 |
+
|
| 85 |
+
### The number that had this model filed as broken
|
| 86 |
+
|
| 87 |
+
Grounding DINO writes **-inf** into every text column the prompt does not use. The score
|
| 88 |
+
tensor is 900 queries × 256 columns; a four-phrase prompt uses 14 of them, so **94.5% of
|
| 89 |
+
the raw logits are -inf**. Correlation over that tensor is undefined, and subtracting two
|
| 90 |
+
builds gives NaN rather than a difference. Measured that way this conversion read "corr
|
| 91 |
+
0.857, returns the stopword 'a' where eager finds four people" and sat parked. Both halves
|
| 92 |
+
were artefacts: eager returns that same `a` query at the same 0.385, and the detections
|
| 93 |
+
were identical all along.
|
| 94 |
+
|
| 95 |
+
The shipped graph ends in a `sigmoid`, so those positions are exactly 0, the output is in
|
| 96 |
+
the 0..1 an app wants, and the gate measures the model instead of its padding.
|
| 97 |
+
|
| 98 |
+
- **Source**: [IDEA-Research/grounding-dino-tiny](https://huggingface.co/IDEA-Research/grounding-dino-tiny)
|
| 99 |
+
- **License**: Apache-2.0
|
| 100 |
+
|
| 101 |
+
torch.export -> to_edge_transform_and_lower(partitioner) -> .pte
|
| 102 |
+
(conversion scripts: [executorch-models](https://github.com/john-rocky/executorch-models))
|