Views
No views yet
IDEA-Research/grounding-dino-tiny
whose block-diagonal text self-attention mask is rebuilt correctly for any number of class
phrases, so a multi-class prompt such as "chair. tv. vase." is scored correctly in a
single forward pass.| file | size | notes |
|---|---|---|
model-fixedmask.onnx | 694.8 MB (662.6 MiB), opset 17 | fp32, single graph, weights embedded |
vocab.txt | 231 508 bytes | BERT-base-uncased tokenizer vocab (unchanged from upstream) |
sha256(model-fixedmask.onnx) = ae9a0026953c6d5ce5a97b421af84c065d7f07173971cb105edb0071868fc180input_ids
(generate_masks_with_special_tokens_and_transfer_map) — it is not a graph input, so any
ONNX export has to reproduce it.transformers 4.48 that function is a Python for loop over
torch.nonzero(special_tokens_mask), and torch.onnx.export bakes the trip count of that
loop into the graph. The widely used community export
onnx-community/grounding-dino-tiny-ONNX
was traced with a one-class prompt ([CLS] … . [SEP] = 3 special tokens), so its graph
contains exactly three hard-coded iterations. The signature is visible in the graph:input_ids -> Equal(101) / Equal(102) / Equal(1012) / Equal(1029)
-> Or -> NonZero -> Transpose
-> Gather(axis 0, index 0), Gather(index 1), Gather(index 2)
-> 6 ScatterND (attention mask + position_ids, per iteration).-separated phrase ever receives its attention block. Every
later phrase keeps just the identity (EyeLike) row — each token attends to itself alone —
with position_id 0. The consequence is that multi-class prompts silently drop classes and
are order-dependent. Measured on COCO 000000000139.jpg, HF PyTorch returns the same 15
detections for every reordering of a 12-class prompt, while a raw joint pass through the
community ONNX returns 4 / 0 / 0 / 3 detections depending on the ordering.input_ids /
attention_mask / token_type_ids, all shaped [1, L], and attention_mask is consumed
purely as the padding mask — it can never carry a block-diagonal [L, L] mask. The only
workaround with the community weights is to run the session once per phrase, which is
correct but costs N passes for N classes.generate_masks_with_special_tokens_and_transfer_map
is monkeypatched with an equivalent that has no Python-level loop over the token positions,
so nothing gets baked in. transformers >= 5 already vectorizes this function, but that
version does not export — the legacy exporter rejects aten::isin, and ONNX has no
CumMax / CumMin. The substitutions are:
isin -> an Equal / Or chain,cummax / cummin -> an L x L compare plus ReduceMax / ReduceMin
(L <= max_text_len = 256, so the cost is negligible),torch.eye -> (i == j) (ORT has no EyeLike kernel for bool).torch.onnx.export (legacy exporter, dynamo=False), opset 17,
dynamic_axes on sequence_length for the three text inputs, pixel inputs fixed at
[1,3,800,800] / [1,800,800] to match the community graph, and
config.disable_custom_kernels = True so deformable attention traces. The trace uses a
two-class example precisely so a baked single-phrase loop could not slip through
unnoticed; the resulting mask is then verified at L = 4, 6, 8, 12 and 26 tokens.DOUBLE. In GroundingDinoEncoder.get_reference_points,
ref_y / (valid_ratios[...] * height) has height as a traced int64 spatial-shape tensor,
and the resulting double flows into the deformable-attention sampling grid. ONNX Runtime
then refuses to load the model with "Could not find an implementation for
GridSample(16)". PyTorch itself runs this in float32, so demoting every Cast(to=DOUBLE)
and every double constant is a faithful correction (15 cast attributes and 20 attribute
tensors in this graph).inputs:
pixel_values [1, 3, 800, 800] float32 ImageNet-normalized image
pixel_mask [1, 800, 800] int64 1 for valid pixels
input_ids [1, L] int64 BERT token IDs (dynamic L)
attention_mask [1, L] int64 1 for real tokens, 0 for padding
token_type_ids [1, L] int64 all zeros (single segment)
outputs:
logits [1, Q, L] float32 per-query, per-token scores
pred_boxes [1, Q, 4] float32 cxcywh, normalized to [0, 1]Q = num_queries = 900; L is the tokenized prompt length (max_text_len = 256). The
output ranks are declared dynamically in the graph, so a loader must read them from the
returned tensor rather than assume them.sigmoid(logits), box score = max over the valid text tokens, filter by a box
threshold (0.3 is a good default) and a text threshold (0.25) for assigning label words to a
box, then decode cxcywh to original-image [x, y, w, h].[0.485, 0.456, 0.406] / std [0.229, 0.224, 0.225], NCHW, no letterbox. The prompt is
lowercased and dot-separated ("chair. tv. vase.").input_ids, against transformers PyTorch:|Δlogit| 7.3e-3, max |Δsigmoid| 1.1e-4 over the valid token range for the
12-class prompt.laptop, because per-phrase
inference never lets the fusion layers see the other classes.000000000139.jpg. The GPU was shared with other tenants, so
these are ranges rather than single figures:| weights | passes | latency |
|---|---|---|
onnx-community/grounding-dino-tiny-ONNX (per-phrase workaround) | 12 | 3860 – 4166 ms |
model-fixedmask.onnx (joint, this repo) | 1 | 227 – 285 ms |
1visionserve pull grounding-dino-fixed
2visionserve run grounding-dino-fixed img.jpg --prompt "chair. tv. vase."1import numpy as np, onnxruntime as ort
2from transformers import AutoProcessor
3
4proc = AutoProcessor.from_pretrained("IDEA-Research/grounding-dino-tiny")
5sess = ort.InferenceSession("model-fixedmask.onnx", providers=["CUDAExecutionProvider", "CPUExecutionProvider"])
6
7inputs = proc(images=image, text="chair. tv. vase.", return_tensors="np")
8logits, boxes = sess.run(
9 ["logits", "pred_boxes"],
10 {
11 "pixel_values": inputs["pixel_values"].astype(np.float32),
12 "pixel_mask": inputs["pixel_mask"].astype(np.int64),
13 "input_ids": inputs["input_ids"].astype(np.int64),
14 "attention_mask": inputs["attention_mask"].astype(np.int64),
15 "token_type_ids": inputs["token_type_ids"].astype(np.int64),
16 },
17)IDEA-Research/grounding-dino-tiny
(Apache-2.0); only the exported computation graph differs. Please cite the original
GroundingDINO work:1@article{liu2023grounding,
2 title={Grounding DINO: Marrying DINO with Grounded Pre-Training for Open-Set Object Detection},
3 author={Liu, Shilong and Zeng, Zhaoyang and Ren, Tianhe and Li, Feng and Zhang, Hao and Yang, Jie and Li, Chunyuan and Yang, Jianwei and Su, Hang and Zhu, Jun and Zhang, Lei},
4 journal={arXiv preprint arXiv:2303.05499},
5 year={2023}
6}