COCO Comparator Bank

One coordinate comparison per COCO category on EUPE-ViT-B features. A 768 pixel image gives 2304 patch tokens at the final layer; layernorm across the 768 channels and max-pool across patches gives one 768-D vector. Each category is decided by comparing two coordinates of that vector.

person   ⟺  feat[48]  > feat[637]
giraffe  ⟺  feat[436] > feat[713]
toilet   ⟺  feat[105] > feat[240]
from infer import CategoryBank
bank = CategoryBank.load()
present = bank.predict('image.jpg')      # {'person': True, 'chair': False, ...}

Results

Pairs are selected on COCO train2017, 118,287 images, and scored on val2017. Categories range from 54 % of images to under 0.2 %, so each is scored on a class-balanced subsample of val2017 and reported by balanced accuracy, where 0.500 is chance for every category regardless of frequency.

balanced accuracy categories
≥ 0.90 14 / 78
≥ 0.85 31 / 78
≥ 0.80 51 / 78
≥ 0.75 69 / 78
≥ 0.70 75 / 78

Median 0.8265, minimum 0.6702, maximum 0.9653. Per-category figures and the selected pair for each are in eval.json.

giraffe          0.9653      bench            0.6702
toilet           0.9430      backpack         0.6732
snowboard        0.9388      chair            0.6931
baseball glove   0.9350      handbag          0.7140
elephant         0.9326      cell phone       0.7150

Toaster and hair drier appear in 8 and 9 validation images, too few to support a balanced subsample, and are recorded in the skipped field of rules.json.

Shared reference axes

The negative side of the comparison repeats across categories. feat[240] is the reference for nine of them, including cat, chair, bed, toilet, refrigerator and book; feat[548] for eight, including cup, tv, laptop, keyboard, cell phone and toothbrush; feat[338] for fork, knife, spoon and cake. Ninety-five distinct channels carry all 78 rules.

feat[48] is the positive term for person, backpack and handbag, and the negative term for bird. It rises on people and on objects people carry, and falls on non-human animals.

Selection

choose.py searches exhaustively over ordered pairs drawn from the 128 dimensions with the largest class-mean separation for that category, scoring feat[i] > feat[j] by balanced accuracy on a class-balanced subsample of train2017 capped at 40,000 images. The search returns two indices. Nothing is fitted, and the 128-dimension restriction makes every figure a lower bound.

Dimension indices and the direction of each comparison are fixed structure. Each rule has no free parameters and two fixed ones.

Circuit

rtl_gen.py emits the bank as one Verilog module and synth.py synthesizes it with nosis for a Lattice ECP5 LFE5U-25F.

categories 78
input channels 95
slices 256
LUT4 511
carry cells 0
flip-flops 0
critical path 0.40 ns

Inputs are the 95 channels as signed INT8, post-layernorm and post-max-pool. Outputs are 78 bits, one per category. Combinational, no multipliers, no memory and no constants, at 3.3 slices per category. Category names that collide with Verilog keywords take a trailing underscore, which is how fork reaches the port list.

tests/test_rtl.py checks every comparator against rules.json and simulates the bank against a Python reference under Icarus Verilog.

Layout

common/      pooled features, the comparison rule, metrics, named pools
cache.py     pooled feature cache for a COCO split
choose.py    pair selection on train2017, writes rules.json
verify.py    scoring on val2017, writes eval.json
rtl_gen.py   Verilog generation from rules.json
synth.py     nosis synthesis, writes synth.json
infer.py     loader for the bank
rtl/         the generated bank
tests/       consistency suite, no backbone or dataset required

Each measured JSON opens with a provenance block naming its generating script and the pool it read. tests/test_artifacts.py enforces the pairing and that selection and scoring name different splits.

Running

pip install -e .
python cache.py --split train2017
python cache.py --split val2017
python choose.py
python verify.py
make synth
make test

COCO_ROOT is the dataset root. BACKBONE is the backbone repo id or a local path. BACKBONE_SRC supplies argus.py from a local directory; otherwise it is fetched from the backbone repo. Caching the two splits is a backbone forward over 123,287 images; every later step reads the cache and takes seconds.

bfloat16 kernels select reduction orders by batch size, so cached values depend on --batch. A cache must be built at one batch size throughout.

Source backbone

EUPE-ViT-B from Meta FAIR (arXiv:2603.22387, Zhu et al., March 2026), distilled from PEcore-G + PElang-G + DINOv3-H+ via a 1.9B proxy teacher. License: FAIR Research License, non-commercial. These rules are artifacts derived from that backbone's feature geometry.

Downloads last month

-

Downloads are not tracked for this model. How to track
Inference Providers NEW
This model isn't deployed by any Inference Provider. 🙋 Ask for provider support

Model tree for phanerozoic/coco-comparator-bank

Finetuned
(8)
this model

Dataset used to train phanerozoic/coco-comparator-bank

Paper for phanerozoic/coco-comparator-bank