~/satyajit

RelateAnything: no object labels, and one gate that was told the answer

mdjsonmcp

2026-09-18 · 30 min · scene-graphs · open-vocabulary · vision · benchmarks · explainer

Open-vocabulary detection accepts any class list at inference. Promptable segmentation returns regions with no class names at all. In both, the taxonomy stopped being a property of the model and became an argument you pass in. Relation prediction never made that move: scene-graph models are still trained and scored on the 50 predicates of VG150 or the 56 of PSG, with the relation head conditioned on predicted object classes, which welds it to one detector and one label space.

RelateAnything (Maëlic Neau, independent, arXiv 2609.12552v1, 11 Sep 2026) finishes the move. It is a 53M-parameter head that takes an image and a set of regions — from any detector, any segmenter, or ground truth — and returns scored relations over a predicate vocabulary handed to it at inference as a list of strings. Object class labels are never an input. There is no predicate classifier, so changing the vocabulary is a matrix substitution rather than a retrain.

That is a good idea and it is mostly delivered. What I went looking for is the gap between the three released artifacts and the prose describing them, and there is one worth naming: the predicate-routing gate that the paper presents as an emergent, unsupervised finding is initialised by a supervised probe fitted on a hand-derived spatial flag — and the routing table shipped inside the checkpoint is still that initialisation, separating the flag at an AUC of exactly 1.0000.

WhoMaëlic Neau, independent · paper · code · project page
Whatrelation prediction with the predicate vocabulary as a runtime input and no object labels anywhere
Size53.2M learned parameters (verified below), plus a 19,103 × 512 vocabulary bank that is a buffer, not a parameter
BackboneDINOv3 ViT-S/16+, fully fine-tuned at 448 px, three depths fused
CorpusRA-4M — 4,282,531 machine-generated relations over 10,102 free-text predicates, geometrically verified
Headline margin2.3–3.5× the mean recall of OvSGTR; 1.34–1.86× against ROBIN-3B, the paper's own stronger baseline
Headline latency"20 ms/frame" is the torch.compile end-to-end path on an A40; the eager path the accuracy tables use is 30.5 ms
Out todayrelsgg-vits16plus and two siblings, RA-4M, a browser demo
maelic/relsgg-vits16plus@caf70d3 · snapshot 2026-09-18
repo size
528.6 MB
task
image-text-to-text
library
relsgg
license
other
largest file
257.1 MB
files
12
downloads
0
likes
5
scene-graph-generationopen-vocabularyonnx

repo last modified 2026-09-17

Scoring against a matrix you can replace

The whole architecture follows from one refusal: nothing on the text side is learned. A projection fitted to the training vocabulary would be undefined for a string supplied later, so the predicate side is a frozen bank of unit vectors and the score is a plain cosine. Swapping the vocabulary means writing a different matrix into a buffer.

A three-band system diagram. Band 1, the visual path: one frame goes both to a region producer labelled 'any detector or segmenter' and to a fine-tuned DINOv3 backbone; a patch map fused from three depths is read by one query per box; five pooled features — subject, object, union, contact, geometry — form each ordered pair; 128 pairs of N(N−1) are kept and refined by a relation transformer and a deformable scene read. Band 2, the text path, run once offline: predicate strings go through a distilled frozen text encoder into an embedding bank, and a predicate gate reads a mixing weight alpha from each string alone, placing 'riding' and 'wearing' at the appearance-led end and 'on', 'holding' and 'above' at the geometry-led end. Band 3, training only: the InfoNCE loss on one annotated pair, and the scored relations that come out.
The architecture. The two things that make the vocabulary swappable are in band 2: a frozen text encoder with no learned projection after it, and a gate that reads its mixing weight from the string rather than from a table of known predicates. Note the label inside the gate box — 'nothing supervises it'. (Paper, Figure 2; rasterised from the project page's own architecture.svg.)

The scoring rule is Equation 2: every pair is scored twice, once from a geometry-led query and once from an appearance-led one, and the two cosines are mixed per predicate.

(i,j,p)  =  τ[αpcos(zijspa,ep)+(1αp)cos(zijsem,ep)]+β\ell(i,j,p) \;=\; \tau\big[\alpha_p \cos(z^{\mathrm{spa}}_{ij}, e_p) + (1-\alpha_p)\cos(z^{\mathrm{sem}}_{ij}, e_p)\big] + \beta

Here epe_p is the text embedding of predicate pp, zspaz^{\mathrm{spa}} and zsemz^{\mathrm{sem}} are the pair's two query vectors, and αp=g(ep)\alpha_p = g(e_p) is the mixing weight — read from the predicate's embedding alone, so it is defined for strings the model has never seen. The released code is that equation with nothing extra:

# relsgg/model/vocab_head.py — VocabHead.score_query_dual
alpha = self.current_alpha()
cos_sem = F.normalize(q_sem, dim=-1) @ self.W.T
cos_spa = F.normalize(q_spa, dim=-1) @ self.W.T
cos = (1.0 - alpha) * cos_sem + alpha * cos_spa
scale = self.logit_scale.exp().clamp(max=100.0)
return cos * scale + self.logit_bias

self.W is the vocabulary. Installing a new one is set_vocabulary_matrix(names, W), which normalises the rows and recomputes alpha; there is no third code path for "a predicate we didn't train on," because there is no notion of a predicate the head knows.

Two properties of the learning problem change at 19,103 predicate strings, and both fixes are real. First, the supervision has to be treated as positive-unlabeled: if a ⟨man, horse⟩ pair is annotated riding, then sitting on and mounted on are true but unstated, and scoring them as negatives teaches the model to suppress correct answers. The objective discounts each negative by an estimated P^(qp)\hat{P}(q \mid p), with two exemptions the paper calls essential — the annotated predicate is never down-weighted, and directional inverses always stay full-weight negatives. Both exemptions are literally in the loader:

# relsgg/training/losses.py — PredicateOntology.from_soft_supervision
np.fill_diagonal(neg_lw, 0.0)          # the annotated predicate is never discounted
# Inverse evidence ... vetoes any down-weighting: the estimator cannot tell
# opposites apart, so they must remain full negatives.
neg_lw[inv_w > 0] = 0.0

Second, the text space has to be repaired before it can carry direction. A contrastive encoder embeds above and below at cosine 0.95, in front of and behind at 0.94, and to the left of and to the right of at 0.99 — indistinguishable from its synonym pairs at 0.96 on average. Since the head regresses visual features onto text directions, that ceiling is the model's ceiling, and it applies to every method that scores relations against off-the-shelf text embeddings.

Four panels. The first two are cosine-similarity matrices over twenty spatial predicates, on the same colour scale: the teacher encoder's matrix is almost uniformly dark red above 0.8, so 'above'/'below' is as close as 'above'/'on top of'; the distilled student's matrix has red synonym blocks on the diagonal and deep blue elsewhere, with the inverse blocks driven near zero. The last two are t-SNE maps under identical settings: the teacher interleaves the members of each inverse pair, while the student splits each pair into two clusters joined by a dashed line.
Why a relation model cannot use an off-the-shelf text encoder. Left pair: the teacher (dino.txt) places every spatial predicate on top of every other, so 'above' and 'below' are the same direction. Right pair: after distillation the inverse blocks fall to near zero while the synonym blocks survive — the synonym-versus-inverse AUC goes from 0.85 to 0.99, mean inverse cosine from 0.92 to 0.09, hubness from 8.1 to 1.3. (Paper, Figure 3.)

The gate that nothing supervises

Back to αp\alpha_p. The paper's Appendix A.3 puts it plainly: "The gate of Eq. 2 receives no supervision, and the weights it learns over the training vocabulary are bimodal and semantically ordered." Figure 2's own diagram repeats it — "nothing supervises it" — and Figure 11's caption closes with "none of this is supervised."

I pulled the three released checkpoints apart to see what the gate actually holds. The statistics reproduce: recomputing α=σ(gate_mlp(W))\alpha = \sigma(\texttt{gate\_mlp}(W)) in float64 from the released weights gives a median of 0.0028 against the paper's 0.002, and 12.48% of the 19,103 strings above 0.5 against the paper's 12%. behind lands at 1.0000, below at 0.9998, on at 0.6381 — all within a rounding step of Appendix A.3. The bimodal split is real.

What the paper does not mention is where it starts. train.sh, the released recipe, calls train.py with no --init_from, and that path runs this:

# relsgg/training/setup.py — build_model
is_spatial = union_spatial_flags(args.data_roots, pred_names)   # corpus flag, bit 0 of each relation
target = spatial_probe_alpha(model.vocab_head.W.cpu().numpy(), is_spatial)
mse = model.vocab_head.warm_start_gate(target)                  # 300 Adam steps onto that target

union_spatial_flags reads a per-predicate spatial majority straight out of the packed corpus. spatial_probe_alpha fits a balanced logistic regression from the text embeddings onto that binary flag. warm_start_gate then regresses the gate MLP onto the probe's output for 300 Adam steps. The gate has no loss term of its own during training — that much is true, and is presumably what the sentence means — but the bimodal geometry-versus-appearance split it is credited with discovering is handed to it at step zero, by a supervised fit on a label the corpus supplies.

The checkpoints make this checkable, because all three ship a stale copy of that initialisation. vocab_head.alpha is a buffer, recomputed from gate_mlp whenever a vocabulary is installed — and in every released model.pth the stored buffer is not what the stored gate computes. Correlation between the two is 0.53, the largest single disagreement is 0.998, and the two are near-identical across three independently trained towers, which a learned quantity would not be.

predicate routing, 243-string release bankAUC vs. the corpus spatial flag 0.9592
← appearance branchgeometry branch →
behindbelowcontainingforming part ofbesideto the right ofnext tounderneathto the left ofaccompanyingdepictingunderin front ofabovesurroundingcontainsfacingcontained indepicted incontained withinheld bystanding in front ofcomprisingshowingattached toborderinginsidedepicted onformingstanding understanding amongfeaturingoverdisplayingstanding besideon top ofholdingnearstanding bystanding next topart ofstanding onstanding nearstanding inholding hands withstanding behindstanding withonsitting besidesitting behindsitting bysitting atsitting insitting nearleadingsitting onhavingposing in front ofwearingplayinglooking pastposing forsmiling atwalking onposing withwalking pastintegrated intosmiling withcarryingeatingriding inreadinglooking intowalking alongplaying withleaning onembedded inperching onposing for photo witheating fromapproachinglaughing withhousinglooking atdrinking fromtopped withkissinghandlingperforming nearliningenclosingrunning pastreaching forstepping onaccommodatingclimbinglooking throughdancing withstrikinggrowing in front ofcarried byleaning againstkickingtraveling alongobservingstored inembracingtalking toridingwalking acrosspassinghuggingparked behindwalking withgrippingfollowingattaching toappearing inworking onworking nearkneeling onwatchingthrowingtalking intogrowing besidelooking towardslistening toparked in front ofusingreaching towardphotographingtucked intohittingpreparingassistingsupportingspeaking intofillingtucked underlying intouchingleaning overconnected towalking throughworking atframinggrowing nearflying overperforming withtowering overblooming fromlying ongrowing amongencirclinggrowing inresting besidebending overresting insidegrazing onsinging intoparked ongrowing fromfloating inparked besidewalking towardsparked inreaching towardsgrazing ingrazing nearmounted ondisplaying content forjumping overdriving onwriting onshaking hands withparked bydecorated withclinging topushingmanipulatingcoolingworn byparked nearpointing atrunning acrosspiercingdriving pastoperatingpullingobscuringswimming inresting nearfeedingincorporatingresting inoccupyingdrivinginteracting withdriving alongpedalingunderlyingfloating in water nearrunning towardsreflected infilmingresting oncoveringhanging fromilluminatingdecoratingshadingresting againstcasting shadow onreflectingcovering head ofhanging onsteeringtoppingcovering eyes ofservingreflecting incuttingmountingcasting light onencasingcontrollingrecordingcapturing sound fromblockingdriving throughgarnishinggesturing towardsswingingfasteningpettingcushioningcasting light upontyping ondipping intoemitting sound forresting underpaddlingamplifying sound for
0.000.250.500.751.00
showing
50 of 243 above 0.5

holding — released gate 0.8036, shipped buffer 0.1722, not flagged.

sigmoid(gate_mlp(W)), recomputed from the weights. The buffer separates the corpus flag perfectly — AUC exactly 1.0000, all 15 flagged strings above every one of the 228 others — which is what an initialisation regressed onto that flag looks like. The gate the model runs scores 0.9592, because training moved 35 unflagged strings (containing, forming part of, depicting) onto the geometry branch that the flag never put there.

routing weight — the released gatestring the corpus flags spatial

Toggle between the two series above. The shipped buffer separates the corpus spatial flag at an AUC of exactly 1.0000 — all 15 flagged strings above all 228 others, no exceptions — which is the signature of a curve fitted to that flag. The gate the model actually runs scores 0.9592, because training moved 35 unflagged strings onto the geometry branch that the flag never put there: containing, forming part of, depicting, accompanying. The routing for holding swings from 0.17 in the buffer to 0.80 in the trained gate; on goes the other way, 0.93 to 0.64.

So training did real work on this gate, and the qualitative claim — projective relations to geometry, actions to appearance — holds. What does not hold is "none of this is supervised." The split was the initialisation.

The argument the paper is actually making

The model is the smaller half of this work. The larger half is a claim about measurement, and it is the part I would keep if I could keep only one: scene-graph recall, as reported, is largely a prior-matching score.

The demonstration is one table. Take the frequency baseline from Zellers et al. (2018) — for a pair of ground-truth object categories, return the most frequent training predicate. It reads no pixels. Score it and RelateAnything's zero-shot tower on the same edges, per-edge and then per-predicate.

a pixel-free lookup table against the model, on the same predictionspaper, Table 1
VG150152,535 edges
freq (no pixels)
68.4
RelateAnything
57.7

-15.6% for the model — the table that reads no pixels is ahead

PSG13,623 edges
freq (no pixels)
50.9
RelateAnything
43.3

-14.9% for the model — the table that reads no pixels is ahead

IndoorVG29,175 edges
freq (no pixels)
67.9
RelateAnything
57.3

-15.6% for the model — the table that reads no pixels is ahead

scored by

Average over edges. Head predicates dominate the average, so returning each category pair's majority string is close to optimal — and the table wins every benchmark by about 15%. This is the protocol leaderboards are ordered by.

frequency table — oracle object labels, zero pixelsRelateAnything — pixels and boxes, no object labels

On micro recall — the metric leaderboards are ordered by — a lookup table that never opens the image beats a trained model by about 15% on all three benchmarks. On macro recall, over the identical predictions, the ordering inverts by 29% to 86%. The paper is careful about what this does and does not show — the edge-by-edge join finds the model right where the table is wrong on 6.9–12.8% of edges, so pixels are demonstrably doing something, and the table receives oracle object categories the model never sees. The narrow conclusion is the right one: a metric a pixel-free table can win is not measuring relation understanding.

The second prior is the one I had not seen stated this cleanly. A benchmark and a training corpus can agree on a predicate string and still never agree on what it is asserted of — on between a person and a horse and on between a book and a table are different acts. Shared triplet mass is the share of a training corpus's relation instances whose ⟨subject category, predicate, object category⟩ triple the benchmark also annotates:

training corpusmatched onVG150PSGIndoorVGHaystack
the released mixture (19,103 predicates)predicate string53.4%38.7%49.5%38.7%
both object categories44.4%36.7%26.8%30.7%
the whole triple12.8%10.7%6.6%4.9%
VG150 train (typical baseline, 50 predicates)predicate string100.0%57.3%95.7%57.3%
both object categories100.0%22.1%12.3%7.1%
the whole triple90.9%8.6%10.4%0.6%

On VG150, the baseline's own fine-tuning corpus reproduces 90.9% of its relation mass as triples the benchmark also annotates. RelateAnything's mixture reproduces 12.8%. Micro recall tracks that statistic; the tail metrics do not. The paper's own evidence for that is the best line in it: an arm trained with a larger share of raw Visual Genome reached 54.3 R@50 on VG150, the best zero-shot figure the author is aware of, while being the worst model they trained on every tail metric. They did not release it.

The honesty extends to the leaderboard. RelateAnything's released tower has seen all 50 VG150 predicate strings, so its rows do not satisfy the open-vocabulary protocol on the novel half; the author retrained with the 15 novel predicates and their synonym groups removed, reports 22.4 Base+Novel and 11.8 Novel R@50 — mid-table, behind every published row but one on Novel recall — and writes "We make no claim to lead on those columns." The 15 "novel" predicates carry 55% of the test relations, and on, of and in account for 93% of that novel mass by themselves, so novel recall on this split is, to within a few points, recall on three of the most frequent strings in Visual Genome.

Numbers, with their denominators

The abstract's headline is "2.3–3.5× the mean recall of the strongest open-vocabulary method of comparable scale." That reproduces exactly against OvSGTR, from Table 4: mR@50 of 28.2 vs 10.4 on VG150 (2.71×), 30.6 vs 8.8 on PSG (3.48×), 29.5 vs 12.8 on IndoorVG (2.30×), 12.7 vs 4.5 on HICO-DET (2.82×). Rare-bucket recall is 5.4× to 21.5×, undefined on VG150 where the baseline scores exactly 0.0. All of it is cross-dataset — no benchmark contributed a training image — and the baseline receives ground-truth object labels throughout while RelateAnything receives none.

The load-bearing words are of comparable scale. The paper's own Table 3 names a stronger baseline on that axis: ROBIN-3B, a scene-graph model built on a 3B vision–language model, which leads OvSGTR on F1@50 on all three benchmarks both were run on. Against ROBIN the same mean-recall multiples are 28.2/15.2 = 1.86×, 30.6/22.9 = 1.34× and 29.5/21.5 = 1.37×. Still a lead on both metrics on all three, at 53.2M parameters against 3B — 1.8% of them — which is the more interesting result anyway. The abstract quotes the bigger multiple against the weaker opponent; Table 3 quotes the smaller one against the stronger. Both are in the paper, one is on the front page.

Two more places where a headline needs its footnote:

The composite is computed against one system. The 40.1-against-11.8 figure on the project page and in Figure 1 is a chance-corrected harmonic mean over five axes, and OvSGTR is the only system runnable on all five, so it is the only one that can carry a composite. ROBIN-3B, which beats OvSGTR where they overlap, is not in that number. The repo says outright: "Never select a model on it." The OVS-F1 column in the repo's model table is a different, four-axis composite (37.2 for the released tower) that drops the judge-run axis — the README flags the difference, which is more than most projects do.

A6, the spatial axis, is printed beside a number it cannot be compared to. Table 3's row reads SpatialSense, macro AUC (pooled AUC) — 59.1 (61.7) baseline, 69.0 (67.5) ours, with the note "boxes-only baseline 68.8." Read quickly, 69.0 clears 68.8. But 68.8 is the SpatialSense authors' accuracy for a baseline that never sees the image, and §6.6 gives the comparable figure: "Neither model reaches the 68.8% of the original authors' boxes-only baseline ... we reach 62.5% and the baseline 59.0%." On the metric where the comparison is apples to apples, the model is 6.3 points behind a baseline that reads only box coordinates. The paper says so, once, in prose, and calls A6 "our weakest axis." The table does not.

The axis I trust most is A2, because it is scored against negatives an annotator actually adjudicated rather than negatives the protocol assumed: 2,870 positives against 23,174 explicit negatives on Haystack. Mean federated AP goes 52.1 → 72.6 and rare-predicate fAP 44.6 → 70.7. The denominator matters here too — the baseline scores every ordered pair while RelateAnything's sampler reaches 89.0% of the 26,044 labelled cells and the rest are scored zero, a correct rejection for a negative and a miss for a positive. That is the conservative choice, and the paper states the coverage in the table rather than in a footnote. The same section carries the sharpest single number in the paper: those identical predictions score AP 0.035 when every unlabelled pair is counted as a false positive, and fAP 0.56 against explicit negatives. A factor of sixteen, entirely in what the protocol assumes about pairs nobody looked at.

One model behind any region source

The claim that object labels are never an input has a visible consequence, and it is the part of the paper that is most worth looking at rather than reading.

Left: a photograph of people queueing at a food truck in a courtyard, with seven coloured instance masks numbered 0 to 6 and labelled person, food truck and courtyard. Right: the relation graph the model reads from those regions — four people 'waiting for' or 'waiting at' the food truck at scores 0.51 to 0.64, the food truck 'parked on' the courtyard at 0.60, and two people 'standing on' the courtyard at 0.46 and 0.47. A header reads '8 relations at p ≥ 0.45, 4,585-tag prompt-free regions, 19,103 predicates'.
One checkpoint, at one calibrated operating point, reading relations from an open-vocabulary segmenter prompted with 4,585 tags. 'food truck' and 'courtyard' are names no scene-graph vocabulary contains, and the names are drawn for the reader — they never reach the relation model. (Paper, Figure 6, top row.)

The paper's own caption for this figure is careful in a way I want to repeat: both panels use a proxy-scale development checkpoint, and they illustrate the interface rather than the operating quality. The companion panel, with a class-agnostic segmenter supplying twelve unnamed regions, returns wearing clothing and holding alongside carrying person wearing and wearing under — strings that are what a 19,103-way open vocabulary looks like when it degrades, not clean output.

The project page publishes a rendered reel of the same idea in motion:

The same model, the same frame, two region contracts: six seconds of boxes, then four of masks. Trimmed by me to seconds 9-19 of the 45-second reel on the project page and scaled to 1152 px; muted and looped here, otherwise unedited — the 'Input:' tag and the CC BY-SA credit are the source's own overlays and are not cropped. This is an offline render (deploy/render_video.py), not a live capture, so playback rate is not a frame-rate claim. Clip: David Farmer, guitarist, Copped Hall open day, by Acabashi, CC BY-SA 4.0, via the project page's reel.

The measurement behind the picture is the one that matters, and it survives: with a shared YOLO-World detector supplying the regions instead of ground truth, every margin from the ground-truth table holds with the same structure — mean recall 3.3×, rare bucket 14× — because the relation model does not care where the boxes came from. What collapses is everything else. Retention relative to ground-truth boxes is 62–63% on PSG and 31–32% on IndoorVG, and when the matcher also requires the detected class to agree, 46% and 19%. A relation cannot be recovered unless both endpoints are detected, pair recall is quadratic in object recall, and no relation model can exceed it. The author's own conclusion from the backbone ladder — capacity does not raise the composite; the largest tower adds 114% of the parameters and changes it by −0.1% — is that the component to improve next is the detector.

Twenty milliseconds, and which twenty

"It runs at 20 ms/frame" is one clause in the abstract and nine measurements in the appendix.

every batch-1 latency the paper reports for the released tower1 of 8 at or under 20 ms
relation head alone
19.3
+ detector + decode, eager
30.5
eager, backbone concurrent
27.9
torch.compile, sequential
20.3
torch.compile, concurrent
22.3
CUDA graphs, concurrent
21.5
ONNX Runtime, CUDA EP
29.7
end to end, vs. the baseline
25.0

the vertical rule is 20 ms — the abstract's figure

GPU
OvSGTR Swin-T, same protocol: 194.0 ms

Blue is the eager path every accuracy number in the paper was produced under. Red is compiled: faster, and the configuration the repo's own deployment notes say never to score a model in, because compilation moves evaluation metrics by forty times the noise floor.

The A100 is the slowest card here at batch 1 on every row, and it is not close. That is not a GPU result — the head issues about 1,362 kernels per frame, so batch 1 is bound by host dispatch, and the A100 node runs an older host CPU than the A40 and H100 nodes. At batch 32 the same A100 delivers roughly twice the A40's throughput.

The abstract's figure is the fourth row: torch.compile, sequential, detector and head and decode, on an A40, 20.3 ms. The eager path on the same card is 30.5 ms, and the eager path is the one every accuracy number in the paper was produced under. Table 35's own caption says so — "compilation changes the reduction order and moves evaluation metrics by far more than the noise floor, so none of the accuracy tables uses compiled inference" — and the repo puts it more bluntly still: "moves evaluation metrics by 40× the noise floor, so never benchmark a compiled model." Both facts are published. They are just published a long way from the abstract. The 20 ms configuration and the configuration the benchmark tables came from are not the same configuration.

There is one number I could not reconcile. Table 11, the comparison against OvSGTR, gives the released system end to end, batch 1, eager PyTorch, on an A40, as 25.0 ms (40.0 FPS). Table 35 gives the same system, same batch, same card, "eager, sequential," as 30.5 ms. The two tables differ in stated vocabulary size — Table 35 names the 243-predicate release bank, Table 11 names none — and Table 11 does not say whether the decode is included. The raw cost JSONs the tables are generated from (runs/benchmark/cost/) are not in the repository, so I could not settle it from the artifacts. It does not move the conclusion: at either number the system is 6.4–7.8× faster end to end than the OvSGTR baseline's 194.0 ms, and the paper is unusually forthcoming about why, namely that it scores at most 128 sampled pairs among 20 boxes at 448 px in bf16 where the baseline scores about 9,500 pairs among 98 boxes at 800/1333 in fp32. "Under the same box budget the two would be considerably closer" is the paper's sentence, not mine.

The best thing in the cost appendix is not a speed at all. The A100 is the slowest of the three GPUs at batch 1 on every configuration — 28.1 ms against 19.3 on the A40 and H100 for the relation head alone — while delivering roughly twice the A40's throughput at batch 32. It reproduces on an idle second A100 node. The head issues about 1,362 kernels per frame, so batch 1 is bound by host dispatch, and the A100 sits on a Zen3 host while the other two sit on Zen4. The conclusion generalises well past this paper: at batch 1, naming a GPU does not identify an operating point unless you also name the host CPU.

What the artifacts say that the paper doesn't

I read the three checkpoints directly — unpickling model.pth without torch, since the Hub cannot introspect a .pth and the model cards therefore publish no parameter count.

receiptscaptured 2026-09-18

Every number RelateAnything states about its own weights, checked against the three released checkpoints by reading model.pth directly — parameter counts, the predicate-routing gate, the score scale, the training mixture. Nine of twelve reproduce. Two are rounded past what the weights say. One — the routing buffer the checkpoint ships — is not what the checkpoint's own gate computes.

quantityclaimedmeasured from the weights
params, ViT-S/16 tower46.1M46,139,281holds
params, ViT-S/16+ (released)53.2M53,235,601holds
params, ViT-B/16 tower113.8M113,797,393holds
tensors on disk, ViT-S/16+not stated63,035,4409,780,736 of them are the 19,103x512 vocabulary bank, plus its 19,103 routing weights — buffers, not learned params
predicate bank width19,103 strings19,103holds
gate alpha, median over the bank0.0020.0028holds
gate alpha, share above 0.512%12.48% (2,385 / 19,103)holds
gate alpha, "behind" / "below" / "on"1.000 / 0.9998 / 0.641.0000 / 0.9998 / 0.6381holds
gate alpha, "carrying"0.00040.0775off by 190x; no released tower reproduces it (0.0536 / 0.0775 / 0.1380)
subject/object compose gate, trained range0.014-0.0440.0141-0.0485the top of the range is 0.049, not 0.044
vocab_head.alpha buffer vs. the gate that produced itsame quantityr = 0.53, max |diff| = 0.998the shipped buffer is not what the shipped gate computes; every consumer recomputes, so it is inert
separation of the corpus spatial flag (243-string bank)the gate is unsupervisedtrained gate AUC 0.959, shipped buffer AUC 1.000an AUC of exactly 1.0 against the flag the warm-start probe was fitted on
vocab_head.logit_scale / logit_bias"received no gradient ... bit-identical to init" (docs/pitfalls.md)log-scale 2.7348 (init log 5 = 1.6094), bias -4.6971 (init 0)both trained in all three released towers
training mixture, per image72.7 / 6.3 / 21.00.7274 / 0.063 / 0.2096holds — training/configs/relsgg-vits16plus.json and train.sh agree

The three towers share one vocabulary bank byte-for-byte (19,103 x 512 float32 = 9,780,736 values in each checkpoint), which is why the same 9.8M offset separates the file size from the stated parameter count in all three. The buffer row is a defect in the artifact, not in the model: relsgg/model/vocab_head.py recomputes alpha inside set_vocabulary_matrix(), and the 243-row deployment bank shipped beside the weights matches the recomputation to 5.9e-05.

method model.pth for maelic/relsgg-vits16{,plus} and relsgg-vitb16 downloaded from the Hub and unpickled without torch (zipfile + a custom pickle.Unpickler that stubs _rebuild_tensor_v2, reading each storage out of archive/data/<key> as float32). alpha recomputed in float64 as sigmoid(gate_mlp(normalize(W))) with an erf GELU. AUC is the exact rank statistic over the 15 spatial-flagged and 228 unflagged strings of predicate_bank.npz.
data /articles/relate-anything/data/checkpoint-audit.json (14 rows, 4.4 KB)

The parameter counts are the cleanest result in the audit. The ViT-S/16+ checkpoint holds 63,035,440 float32 values; subtract the 19,103 × 512 vocabulary matrix and its 19,103 routing weights, both of which are buffers rather than learned parameters, and you get 53,235,601 — the claimed 53.2M, exactly. The same 9,780,736-value offset separates file size from claim on all three towers, which is what you would expect from three checkpoints carrying one shared bank, and it lands 46,139,281 and 113,797,393 against claims of 46.1M and 113.8M. Excluding the bank is the right call and it is the paper's own thesis restated in arithmetic: the vocabulary is an input, so it is not part of the model.

Four smaller things fell out along the way.

The published corpus is 2,069 images smaller than the paper's corpus. Table 20 and Figure 13 both count 474,413 training images, and the paper derives that number cleanly — 474,420 MegaSG training images, seven of which lose every candidate to the gates. The Hub's own parquet row counts for maelic/RA-4M are 472,344 train and 24,964 val. The relation total, 4,282,531, is identical in both, which is what makes it look carried over rather than recounted. It is 0.44% and it changes nothing, but a corpus card and its paper should agree on how many images are in the corpus.

The benchmark is the one released artifact I could not reach. The abstract says "Model, corpus and benchmark are public." The model repos and RA-4M resolve fine. huggingface.co/datasets/maelic/OV-SGG-Bench, which the README links for the evaluation packs, negatives and calibration files, returns 401 to the same unauthenticated client, today. The protocol is genuinely public — benchmark/SPEC.md and every scorer and entry point are in the repository — so this is a missing download rather than a missing method, and it may be a gate someone forgot to open.

RA-4M is CC BY-NC 4.0, and nothing outside the dataset card says so. The repo's licence section covers code (Apache-2.0), weights (DINOv3 licence) and annotations ("generated by Gemma, distributed with the Gemma Terms of Use notice"). The non-commercial clause on the corpus itself appears only in the dataset card's YAML. If you were planning to train on 43.8 GB of RA-4M for anything commercial, that is the line to read first.

docs/pitfalls.md contradicts docs/deployment.md on the claim the headline latency rests on. The README tells you to read pitfalls "before you trust a number." Pitfalls says torch.compile with reduce-overhead "produce[s] incorrect results in this pipeline" and that "resolution changes and plain compilation buy nothing anyway." Deployment says the reduce-overhead finding "was a measurement bug" and that compilation is the largest single gain measured, 1.5–1.8× on every GPU. The paper, the README and the abstract's 20 ms all side with deployment. Pitfalls is the stale file, and it is stale on exactly the mechanism the headline number depends on.

One more, on the corpus itself, because it is visible in the figure the paper chose to show the corpus at its best — and in the relation the caption singles out as the win:

Two rows, each a photograph with numbered coloured boxes beside two lists of relations. Top row, a living room: the MegaSG source list has seven relations, six of which are 'on'; the RA-4M list has twelve, including '2 hat worn by 1 person', '5 monitor resting on 4 cabinet', '3 lamp casting light on 4 cabinet' and '8 camera capturing 5 monitor'. Bottom row, a horse-drawn carriage at a show ground: the source list has seven relations, five of them 'near'; the RA-4M list has sixteen, including '2 horse pulling 1 carriage', '5 person riding 1 carriage', '7 bench part of 1 carriage' and '2 horse behind 1 carriage'.
The same images and the same boxes, annotated by MegaSG's own pipeline and by RA-4M. The density and vocabulary gain is real: 9.03 relations per image against 5.29, 107× the vocabulary, mean object degree 1.88 to 3.20. The paper's caption names '8 camera capturing 5 monitor' as the semantics a closed schema cannot express; zoom in and object 8 is a camcorder lying flat on the cabinet top beside the television, cable trailing, lens not toward it. (Paper, Figure 16.)

That is the failure mode the paper itself names — a prior-driven label on a plausible pair, which no geometric gate can catch because geometry does not constrain capturing. It is a small thing to find in a showcase figure, and a large thing to find in the relation the caption picked out.

RA-4M's precision claim is structural, and the paper says so in its limitations: the geometric gate rejects 11.3% of candidates, a rejection is a true negative up to box error, and predicates geometry cannot constrain — gaze above all, where roughly 22% of looking at / watching annotations have disjoint boxes and cannot be verified — pass through unchecked and are counted rather than checked. "We have no human-audited precision estimate, a sample of generated relations read and scored by a person. That is the measurement a reader should expect before relying on 4.3M machine-generated annotations, and the one to add first." I agree, and I would put it above every remaining item on the roadmap.

The result I did not expect

Section 7.3 asks whether relation supervision produces relational features — the representational premise behind every architecture that shares one backbone between object and relation prediction. The answer, measured on the author's own model, is no, and it is reported against interest.

Fine-tuning on relations raises class selectivity in the dense features from 0.242 to 0.281 and leaves relation selectivity flat, 0.133 to 0.138. The probability that a relation partner is more similar to the subject than an unrelated object of the same class falls from 0.469 to 0.385, against a chance level of 0.500 — relation supervision made the features worse at the one discrimination relations require. The interaction region does emerge where two objects meet, and retrieving the object class from it works at 0.761 against a chance level of 0.068; retrieving the verb reaches 0.269 against a majority-class chance of 0.424, which is below chance, at every depth. The region encodes which object is handled, not what is being done with it.

That result is consistent with the lesion ladder in §7.4: removing the object-identity channel from the relation logit costs 0.1% of micro accuracy on all three benchmarks, and an exact variance decomposition puts 87–93% of the semantic logit's variance in pair context against 0.1% and 0.0% for the subject and object features. Shuffle the object labels handed to OvSGTR and its output statistics do not move — its predicate is a function of the labels, not of the image.

The architectural argument follows from those two measurements rather than from taste: there is no shared representation to justify a shared backbone, and there is a measurable cost to the shared input. The author is careful about the scope — this shows that this recipe does not produce relational dense features, not that none could, since nothing in it supplies a patch-level relational objective. It is the kind of negative result that usually stays in a lab notebook.

What I'd still want to know

A human audit of RA-4M. Everything downstream rests on 4.3M machine-generated relations whose precision has never been sampled by a person. A thousand relations, read and scored, would cost a day and would change how much weight the rest of the paper can carry.

The gate, retrained without its warm start. The claim that routing emerges unsupervised is falsifiable in one run: delete the probe, initialise the gate at random, train, and report the α distribution. If it still comes out bimodal with behind at 1.0 and riding at 0.01, the paper's sentence was right and only its provenance was unstated. If it does not, the finding was the initialisation.

The 25.0-versus-30.5 ms gap. Publishing runs/benchmark/cost/*.json would close it in a minute; the tables are already generated from those files.

A general held-out-concept run. Every benchmark predicate occurs in the training vocabulary, and the paper says so. The held-out variant exists for the VG150 leaderboard split only; the architecture permits holding concepts out across all four benchmarks, because the predicate matrix is never learned, and that is the experiment that would test the open-vocabulary claim rather than the transfer claim.

Whether anyone else reproduces the 54.3. The discarded arm that hit the best zero-shot VG150 recall the author is aware of, while being the worst model they trained on every tail metric, is the strongest evidence in the paper for its own thesis — and it is a sentence, not a table.

What would change my mind

5 claims above, and what would falsify each

  1. The predicate-routing gate is warm-started by supervision, and the paper says it is not.

    A run of train.sh whose logs show build_model taking the --init_from branch would mean the released recipe skips the probe. It does not: train.sh passes no --init_from, so union_spatial_flagsspatial_probe_alphawarm_start_gate is the path. Separately, if the stored vocab_head.alpha buffer turned out to be a post-training snapshot rather than the warm start, its AUC of exactly 1.0000 against the corpus flag — and its near-identity across three independently trained towers — would need another explanation. I would take one.

  2. 53.2M is the right parameter count, and the 19,103 × 512 bank is correctly excluded from it.

    A checkpoint whose bank differed per tower, or a forward pass that updated W by gradient, would make the bank a parameter and the count wrong by 9.8M. Neither is the case: W is a register_buffer, the three towers carry byte-identical bank dimensions, and the arithmetic closes to the digit on all three.

  3. The abstract's 20 ms is the compiled path, not the path the accuracy tables use.

    A row in Table 35 showing an eager configuration at or under 20 ms on any GPU would overturn this. The fastest eager row is 27.9 ms (A40, concurrent backbone); the fastest compiled row is 18.1 ms (H100). If a future revision re-measures the accuracy tables under compilation and they hold, the criticism evaporates — but the repo currently says never to do that.

  4. OV-SGG-Bench's data is not publicly downloadable as of 18 Sep 2026.

    A 200 from huggingface.co/datasets/maelic/OV-SGG-Bench to an unauthenticated client. I got 401 today, from the same client that fetched RA-4M and all three model repos without trouble. This is the finding here most likely to be fixed by the time you read it, and the most trivially fixed.

  5. The headline mean-recall multiple is against OvSGTR, not against the paper's strongest baseline.

    ROBIN-3B numbers on VG150, PSG and IndoorVG that put its mR@50 below OvSGTR's would make "strongest ... of comparable scale" and "strongest" the same claim. Table 3 reports the opposite: 15.2 / 22.9 / 21.5 for ROBIN against 10.4 / 8.8 / 12.8 for OvSGTR. The margin over ROBIN is 1.34–1.86×, and it is still a win at 1.8% of the parameters.

The line worth keeping

The cheapest practice we recommend is to report the shared triplet mass between corpus and benchmark beside each recall number: how much of a model's supervision asserts the same relations, of the same kinds of object, as the benchmark.

That costs a join and a percentage, and on the evidence here it would have changed how several published scene-graph results were read. The model is a good model — small, genuinely detector-agnostic, and honest about where it is behind. But the measurement argument is the part I would hand to someone else's project, and it is free.

Cite this article

For attribution, please use the following reference or BibTeX:

Satyajit Ghana, "RelateAnything: no object labels, and one gate that was told the answer", ai.thesatyajit.com, September 2026.

bibtex
@misc{ghana2026relateanything,
  author = {Satyajit Ghana},
  title  = {RelateAnything: no object labels, and one gate that was told the answer},
  url    = {https://ai.thesatyajit.com/articles/relate-anything},
  year   = {2026}
}
share