








Whatever tagging ability appears must come from test-time compute of the embedding model.
A frozen encoder’s inference-time budget takes roughly three forms:
Same frozen encoder in all three; they differ only in what enters the computation.
Both paths end in the same space, so \( \langle p,\,e_\ell\rangle \) is well-defined: any patch of any image, scored against any word the model knows.
Every box is the frozen model or plain arithmetic: A reads more of one pass; B runs new passes on new pixels.
No curated tag list. Take all 128,260 tokens and encode each one as text into a label matrix \[ E=\big[\,e_\ell\,\big]_{\ell\in V},\qquad e_\ell=\operatorname{encode\_text}(\ell)\in\mathbb{R}^{768},\quad |V|=128{,}260 \] One matmul now scores any image against the entire vocabulary; fragments are filtered later by a word-start gate (step 4).
Why encode_text, not the embedding table? The model has tie_word_embeddings = false: the input-embedding table lives in a different space than the pooled output. You must encode each token as a text string to put labels in the image's space.
AThe patch vectors already exist in the forward pass. Scoring each label against all of them, and keeping the max, is one extra step over outputs you already have.
Raw cosine has a base-rate bias: generic words ("bed", "cat") score high on almost any image because they sit near the image modality. Estimate a per-label prior once from neutral background images, then subtract it: \[ \tilde s_\ell \;=\; s_\ell-\mu_\ell,\qquad \mu_\ell=\mathbb{E}_{x\,\sim\,\text{background}}\big[s_\ell(x)\big] \]
No calibration set, no labels, one offline pass.


μℓ per label
Word-start gate. Byte-BPE tokenizers encode a leading space as the glyph Ġ; a token beginning with it starts a new word: Ġcat is a whole word, GetComponent is a fragment. That one built-in signal is the gate; no external dictionary.
Embedding-NMS. Synonyms and multilingual variants (猫 / Cat / кот / cat) collapse into one, using cosine in the model's own space. Walk labels by score; keep \(\ell\) only if \( \max_{k\,\in\,\text{kept}}\langle e_\ell, e_k\rangle < 0.6 \). Again: no lookup table, just the geometry.
Class-Wise Reranking (CWR), the crop-and-rescore idea from TagCLIP (AAAI’24), extended to a full-coverage grid of 14 crops (overlaid right) through the same frozen model. A crop is a new input image, itself re-patchified by the tower; a small object fills whichever crop contains it, so weak signal becomes strong.
\[ S_\ell=\tilde s_\ell+1.3\big(\max_{c=1..14} s_{c,\ell}-\mu_\ell\big),\qquad s_{c,\ell}=\max\!\big(\max_{p\in P_c}\langle p,e_\ell\rangle,\;\langle g_c,e_\ell\rangle\big) \]
BPer-label max, not averaging: averaging hurt. The outlier crop is the evidence.
then \( \ell \in \text{word-gated vocabulary} \rightarrow \text{embedding-NMS}\,(\tau=0.6) \rightarrow \text{top-}k \)
No head, no logits, no learned threshold: three fixed weights, two background priors, and max operations over frozen-model outputs.
Real pipeline output, one image, all 128,260 tokens. Tagging is distribution sharpening.
| method | P@1 | P@3 | R@5 | mAP |
|---|
150 COCO-val images, real multi-label ground truth, avg 2.93 labels/image. softpool trades mAP for top-k precision; the ladder tracks the max-pool path.
mAP: global → patch → +CWR
One example: OTTER re-balances scores toward a target class distribution, which only shuffles vectors it already has. Its open circle sits at the 5-crop baseline of 0.693, and it lands at 0.699.
Calibration methods were designed for weakly calibrated, single-label, two-tower CLIP. This encoder's space is already aligned, calibrated, and multi-label: there is nothing left to recover.
The ceiling is the 1B model itself. Real test-time compute here means giving the model more to look at, not re-arranging what it already saw.
The frontier is traced by reading more of the pass and re-encoding new views; calibration sits at the same cost, at or below it (<0.1 ms/img, measured).
Every tag so far is a single word. Can more test-time compute turn it into a grounded noun phrase, with no part-of-speech tagger and no grammar?

Each slot is filled one at a time; the encoder scores the full phrase against the region: \( \langle E(\text{phrase}),\text{region}\rangle-\langle E(\text{kitty}),\text{region}\rangle \). Beam width 4.
The winning path re-orders its own words: “grey couch kitty” beats “couch grey kitty”. Word order, resolved by an embedding model with no grammar.
Default, crop re-encoding, beam-searched n-grams. Top-5 per mode, unstaged photos. Verbatim, unfiltered.
| line of work | their setup | our delta |
|---|---|---|
| Tag2Text / RAM / RAM++ | trained tagging models, curated ~6.4k tag list | training-free, label space = tokenizer vocab |
| TagCLIP | CLIP two-tower, penultimate layer, DMAR+CWR | single omni model, last layer is the output space |
| PIAA | patch-level scoring (“[CLS] is not enough”) + GDA whitening | patch thesis confirmed (+0.37 mAP); whitening collapses (0.06) |
| recent calibration (OTTER, BCA) | calibration set or target prior to de-bias | one offline background prior, zero calibration |
Both questions come out the way we hoped. A frozen embedding model does become a tagger with no training, and the only compute that scales it is the kind that adds new information.
The Python study became a feature of Omni, a native on-device semantic-search app (Swift + MLX, same frozen model). The port reuses the architecture directly:



tag chips as they appear in results; the third row is a video segment
A frozen embedding model can do more than its training reveals. You reach the rest by spending compute at inference, not by adding parameters. Both of my talks push on that same idea.