attr-eomt 0.1.2__tar.gz → 1.0.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {attr_eomt-0.1.2 → attr_eomt-1.0.0}/.gitignore +1 -0
- {attr_eomt-0.1.2 → attr_eomt-1.0.0}/PKG-INFO +60 -37
- {attr_eomt-0.1.2 → attr_eomt-1.0.0}/README.md +58 -36
- attr_eomt-1.0.0/docs/assets/01-architecture.png +0 -0
- {attr_eomt-0.1.2 → attr_eomt-1.0.0}/docs/assets/01-architecture.svg +1 -1
- attr_eomt-1.0.0/docs/assets/02-factorized-labels.png +0 -0
- attr_eomt-1.0.0/docs/assets/02-factorized-labels.svg +1 -0
- attr_eomt-1.0.0/docs/examples/billie_eilish.jpg +0 -0
- attr_eomt-1.0.0/docs/examples/rosalia.jpg +0 -0
- attr_eomt-1.0.0/docs/examples/sample.jpg +0 -0
- attr_eomt-1.0.0/docs/examples/taylor_swift.jpg +0 -0
- {attr_eomt-0.1.2 → attr_eomt-1.0.0}/eomt/api.py +151 -5
- attr_eomt-1.0.0/eomt/compress.py +95 -0
- {attr_eomt-0.1.2 → attr_eomt-1.0.0}/eomt/engine/predict.py +8 -3
- {attr_eomt-0.1.2 → attr_eomt-1.0.0}/eomt/engine/train.py +99 -14
- {attr_eomt-0.1.2 → attr_eomt-1.0.0}/eomt/model.py +233 -19
- {attr_eomt-0.1.2 → attr_eomt-1.0.0}/eomt/serialization.py +60 -1
- attr_eomt-1.0.0/eomt/visualize.py +159 -0
- {attr_eomt-0.1.2 → attr_eomt-1.0.0}/pyproject.toml +2 -1
- {attr_eomt-0.1.2 → attr_eomt-1.0.0}/sample_data/README.md +7 -7
- {attr_eomt-0.1.2 → attr_eomt-1.0.0}/sample_data/annotations/instances_train.json +18 -16
- attr_eomt-1.0.0/sample_data/annotations/instances_val.json +39 -0
- {attr_eomt-0.1.2 → attr_eomt-1.0.0}/sample_data/data.yaml +3 -3
- attr_eomt-1.0.0/scripts/push_to_hub.py +79 -0
- {attr_eomt-0.1.2 → attr_eomt-1.0.0}/scripts/train.py +11 -0
- {attr_eomt-0.1.2 → attr_eomt-1.0.0}/site/index.html +34 -24
- attr_eomt-1.0.0/tests/test_compress.py +61 -0
- attr_eomt-1.0.0/tools/attr_tagger/README.md +69 -0
- attr_eomt-1.0.0/tools/attr_tagger/tag.py +405 -0
- {attr_eomt-0.1.2 → attr_eomt-1.0.0}/uv.lock +12 -1
- attr_eomt-0.1.2/docs/assets/01-architecture.png +0 -0
- attr_eomt-0.1.2/docs/assets/02-factorized-labels.png +0 -0
- attr_eomt-0.1.2/docs/assets/02-factorized-labels.svg +0 -1
- attr_eomt-0.1.2/docs/examples/example_1.png +0 -0
- attr_eomt-0.1.2/eomt/visualize.py +0 -98
- attr_eomt-0.1.2/sample_data/annotations/instances_val.json +0 -37
- {attr_eomt-0.1.2 → attr_eomt-1.0.0}/.github/workflows/pages.yml +0 -0
- {attr_eomt-0.1.2 → attr_eomt-1.0.0}/.github/workflows/publish.yml +0 -0
- {attr_eomt-0.1.2 → attr_eomt-1.0.0}/.github/workflows/release.yml +0 -0
- {attr_eomt-0.1.2 → attr_eomt-1.0.0}/.github/workflows/tests.yml +0 -0
- {attr_eomt-0.1.2 → attr_eomt-1.0.0}/LICENSE +0 -0
- {attr_eomt-0.1.2 → attr_eomt-1.0.0}/configs/coco.yaml +0 -0
- {attr_eomt-0.1.2 → attr_eomt-1.0.0}/docs/assets/00-hero-banner.png +0 -0
- {attr_eomt-0.1.2 → attr_eomt-1.0.0}/docs/assets/00-hero-banner.svg +0 -0
- {attr_eomt-0.1.2 → attr_eomt-1.0.0}/docs/assets/03-training-flow.png +0 -0
- {attr_eomt-0.1.2 → attr_eomt-1.0.0}/docs/assets/03-training-flow.svg +0 -0
- {attr_eomt-0.1.2 → attr_eomt-1.0.0}/eomt/__init__.py +0 -0
- {attr_eomt-0.1.2 → attr_eomt-1.0.0}/eomt/aux_cls.py +0 -0
- {attr_eomt-0.1.2 → attr_eomt-1.0.0}/eomt/box_loss.py +0 -0
- {attr_eomt-0.1.2 → attr_eomt-1.0.0}/eomt/config.py +0 -0
- {attr_eomt-0.1.2 → attr_eomt-1.0.0}/eomt/data/__init__.py +0 -0
- {attr_eomt-0.1.2 → attr_eomt-1.0.0}/eomt/data/coco.py +0 -0
- {attr_eomt-0.1.2 → attr_eomt-1.0.0}/eomt/data/config.py +0 -0
- {attr_eomt-0.1.2 → attr_eomt-1.0.0}/eomt/data/download.py +0 -0
- {attr_eomt-0.1.2 → attr_eomt-1.0.0}/eomt/data/transforms.py +0 -0
- {attr_eomt-0.1.2 → attr_eomt-1.0.0}/eomt/device.py +0 -0
- {attr_eomt-0.1.2 → attr_eomt-1.0.0}/eomt/ema.py +0 -0
- {attr_eomt-0.1.2 → attr_eomt-1.0.0}/eomt/engine/__init__.py +0 -0
- {attr_eomt-0.1.2 → attr_eomt-1.0.0}/eomt/engine/validate.py +0 -0
- {attr_eomt-0.1.2 → attr_eomt-1.0.0}/eomt/loss.py +0 -0
- {attr_eomt-0.1.2 → attr_eomt-1.0.0}/eomt/plotting.py +0 -0
- {attr_eomt-0.1.2 → attr_eomt-1.0.0}/eomt/postprocess.py +0 -0
- {attr_eomt-0.1.2 → attr_eomt-1.0.0}/eomt/preprocess.py +0 -0
- {attr_eomt-0.1.2 → attr_eomt-1.0.0}/sample_data/images/train/.gitkeep +0 -0
- {attr_eomt-0.1.2 → attr_eomt-1.0.0}/sample_data/images/val/.gitkeep +0 -0
- {attr_eomt-0.1.2 → attr_eomt-1.0.0}/scripts/info.py +0 -0
- {attr_eomt-0.1.2 → attr_eomt-1.0.0}/scripts/predict.py +0 -0
- {attr_eomt-0.1.2 → attr_eomt-1.0.0}/scripts/train_detect_coco.sh +0 -0
- {attr_eomt-0.1.2 → attr_eomt-1.0.0}/scripts/val.py +0 -0
- {attr_eomt-0.1.2 → attr_eomt-1.0.0}/tests/test_api.py +0 -0
- {attr_eomt-0.1.2 → attr_eomt-1.0.0}/tests/test_parity.py +0 -0
- {attr_eomt-0.1.2 → attr_eomt-1.0.0}/tests/test_smoke.py +0 -0
- {attr_eomt-0.1.2 → attr_eomt-1.0.0}/tests/test_sweep.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: attr-eomt
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 1.0.0
|
|
4
4
|
Summary: Standalone EoMT (Encoder-only Mask Transformer) for instance segmentation, with DINOv2 init, COCO training/validation and inference.
|
|
5
5
|
Project-URL: Homepage, https://github.com/imagra93/attr-eomt
|
|
6
6
|
Project-URL: Documentation, https://imagra93.github.io/attr-eomt
|
|
@@ -23,6 +23,7 @@ Requires-Dist: pyyaml>=6.0
|
|
|
23
23
|
Requires-Dist: requests>=2.25.0
|
|
24
24
|
Requires-Dist: scipy>=1.7.0
|
|
25
25
|
Requires-Dist: torch>=2.4.0
|
|
26
|
+
Requires-Dist: torchao>=0.7.0
|
|
26
27
|
Requires-Dist: torchvision>=0.19.0
|
|
27
28
|
Requires-Dist: tqdm>=4.65.0
|
|
28
29
|
Requires-Dist: transformers>=5.1.0
|
|
@@ -92,9 +93,9 @@ with a fixed set of **learnable queries** (the Mask2Former idea) — each query
|
|
|
92
93
|
"slot" that latches onto one object instance. After the encoder runs, every query emits
|
|
93
94
|
a single vector, the **per-query embedding** of shape `[B, Q, hidden]`. The whole model
|
|
94
95
|
is then just "turn that embedding into predictions": a **class head** for the primary
|
|
95
|
-
label and a **mask/box head** for geometry. It is **NMS-free**, so two overlapping
|
|
96
|
-
stay two distinct queries instead of being merged — the property that lets
|
|
97
|
-
stay attached to the right instance.
|
|
96
|
+
label and a **mask/box head** for geometry. It is **NMS-free**, so two overlapping
|
|
97
|
+
garments stay two distinct queries instead of being merged — the property that lets
|
|
98
|
+
attributes stay attached to the right instance.
|
|
98
99
|
|
|
99
100
|
The attribute heads add nothing to this picture except themselves: they tap the **exact
|
|
100
101
|
same embedding** (captured non-invasively with a forward hook), each a small classifier
|
|
@@ -164,9 +165,9 @@ attribute heads add a thin linear/MLP per head and are negligible by design.
|
|
|
164
165
|
## ⭐ Method — factorizing the label space
|
|
165
166
|
|
|
166
167
|
This is the contribution. Conventional detectors fold every distinction into a single
|
|
167
|
-
flat label space. When an object has both a *type* and several *attributes* — a
|
|
168
|
-
|
|
169
|
-
the Cartesian product `type ×
|
|
168
|
+
flat label space. When an object has both a *type* and several *attributes* — a garment's
|
|
169
|
+
class **and** its viewpoint **and** whether it's occluded — the only way to express that is
|
|
170
|
+
the Cartesian product `type × viewpoint × occlusion × …`. That space explodes combinatorially,
|
|
170
171
|
starves each leaf class of training examples, and breaks Hungarian matching by
|
|
171
172
|
multiplying the query targets.
|
|
172
173
|
|
|
@@ -181,11 +182,11 @@ per-instance query embedding the detector already computes — they **add, not m
|
|
|
181
182
|
Because the heads are independent:
|
|
182
183
|
|
|
183
184
|
- **Categories stay collapsed and general.** Keep a compact, well-populated primary
|
|
184
|
-
taxonomy (`
|
|
185
|
-
into attributes — every primary class keeps its full sample count instead
|
|
186
|
-
shattered into rare leaves.
|
|
187
|
-
- **Unseen combinations generalize.** A `
|
|
188
|
-
predicts `
|
|
185
|
+
taxonomy (`short_sleeve_top`, `dress`, `trousers`) and push fine-grained or orthogonal
|
|
186
|
+
distinctions into attributes — every primary class keeps its full sample count instead
|
|
187
|
+
of being shattered into rare leaves.
|
|
188
|
+
- **Unseen combinations generalize.** A `viewpoint` head trained across many garment types
|
|
189
|
+
predicts `side` on a class it *never co-occurred with sideways*, because viewpoint is
|
|
189
190
|
learned independently of type. The model composes `attribute × class` combinations
|
|
190
191
|
that **never appear in the training data** — combinations a flat label space cannot
|
|
191
192
|
even represent.
|
|
@@ -196,25 +197,25 @@ Because the heads are independent:
|
|
|
196
197
|
matched queries — they add only a thin linear/MLP head and a cross-entropy term, not
|
|
197
198
|
a second model or a second pass.
|
|
198
199
|
|
|
199
|
-
### Example:
|
|
200
|
+
### Example: clothing with per-instance attributes
|
|
200
201
|
|
|
201
|
-
One model segments each
|
|
202
|
-
`
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
202
|
+
One model segments each garment (primary classes like `vest_dress` / `short_sleeve_top`
|
|
203
|
+
/ `long_sleeve_dress` / `skirt` / `trousers` …) and, for **every** detection, reads off
|
|
204
|
+
four **independent** attribute heads — `scale` (`small` / `modest` / `large`),
|
|
205
|
+
`occlusion` (`no` / `slight` / `medium`), `zoom_in` (`no` / `medium` / `large`) and
|
|
206
|
+
`viewpoint` (`frontal` / `side` / `back`). The renderer prints the primary class + score
|
|
207
|
+
on the first row and each attribute + its confidence on the rows beneath it.
|
|
206
208
|
|
|
207
|
-

|
|
208
210
|
|
|
209
|
-
|
|
210
|
-
the case that's awkward to fold into the primary class space. The same
|
|
211
|
-
any "class **plus** per-instance sub-labels" task: **retail shelves →
|
|
212
|
-
facing**, **
|
|
213
|
-
health**, **apparel → garment + pattern**.
|
|
211
|
+
The four attributes are *orthogonal* to the garment class — they vary independently —
|
|
212
|
+
which is exactly the case that's awkward to fold into the primary class space. The same
|
|
213
|
+
pattern fits any "class **plus** per-instance sub-labels" task: **retail shelves →
|
|
214
|
+
product + facing**, **documents → element + role**, **cells → type + health**.
|
|
214
215
|
|
|
215
|
-
>
|
|
216
|
-
>
|
|
217
|
-
>
|
|
216
|
+
> Trained on the public **[DeepFashion2](https://github.com/switchablenorms/DeepFashion2)**
|
|
217
|
+
> dataset (13 garment classes + 4 attribute heads) and rendered with the package's own
|
|
218
|
+
> renderer ([`eomt.visualize.draw_instances`](eomt/visualize.py)).
|
|
218
219
|
|
|
219
220
|
---
|
|
220
221
|
|
|
@@ -259,18 +260,19 @@ names) are discovered from the JSON, the same as `nc`.
|
|
|
259
260
|
```jsonc
|
|
260
261
|
"attributes": [
|
|
261
262
|
{
|
|
262
|
-
"name": "
|
|
263
|
+
"name": "scale",
|
|
263
264
|
"categories": [
|
|
264
|
-
{"id":
|
|
265
|
-
{"id":
|
|
266
|
-
{"id":
|
|
265
|
+
{"id": 1, "name": "small"},
|
|
266
|
+
{"id": 2, "name": "modest"},
|
|
267
|
+
{"id": 3, "name": "large"}
|
|
267
268
|
]
|
|
268
269
|
},
|
|
269
270
|
{
|
|
270
|
-
"name": "
|
|
271
|
+
"name": "viewpoint",
|
|
271
272
|
"categories": [
|
|
272
|
-
{"id":
|
|
273
|
-
{"id":
|
|
273
|
+
{"id": 0, "name": "frontal"},
|
|
274
|
+
{"id": 1, "name": "side"},
|
|
275
|
+
{"id": 2, "name": "back"}
|
|
274
276
|
]
|
|
275
277
|
}
|
|
276
278
|
]
|
|
@@ -282,14 +284,14 @@ names) are discovered from the JSON, the same as `nc`.
|
|
|
282
284
|
{
|
|
283
285
|
"id": 1, "image_id": 42, "category_id": 1,
|
|
284
286
|
"segmentation": [...], "bbox": [...], "area": 1234, "iscrowd": 0,
|
|
285
|
-
"attributes": {"
|
|
287
|
+
"attributes": {"scale": 3, "viewpoint": 0}
|
|
286
288
|
}
|
|
287
289
|
```
|
|
288
290
|
|
|
289
291
|
Notes:
|
|
290
292
|
|
|
291
|
-
- Raw ids are remapped to a contiguous `0..n-1` per head (so `
|
|
292
|
-
`0`/`1`); `categories` may be omitted, in which case the id set is inferred.
|
|
293
|
+
- Raw ids are remapped to a contiguous `0..n-1` per head (so `scale`'s `1`/`2`/`3` become
|
|
294
|
+
`0`/`1`/`2`); `categories` may be omitted, in which case the id set is inferred.
|
|
293
295
|
- A missing per-annotation value defaults to `0`; a JSON with **no** `attributes` ⇒
|
|
294
296
|
detection-only, exactly as before.
|
|
295
297
|
|
|
@@ -326,6 +328,27 @@ EoMT("runs/train/eomt-l").val(data="coco")
|
|
|
326
328
|
EoMT("runs/train/eomt-l").predict("images/", plot=True) # writes annotated images
|
|
327
329
|
```
|
|
328
330
|
|
|
331
|
+
### Compress to int8
|
|
332
|
+
|
|
333
|
+
`compress()` applies **int8 weight-only quantization** (via [torchao](https://github.com/pytorch/ao))
|
|
334
|
+
to the ViT transformer blocks — the bulk of the parameters — while keeping the
|
|
335
|
+
prediction heads in full precision. It's **data-free** (no calibration) and shrinks the
|
|
336
|
+
checkpoint ≈**3.4×** on `l` with no measurable mAP loss.
|
|
337
|
+
|
|
338
|
+
```python
|
|
339
|
+
m = EoMT("runs/train/eomt-l")
|
|
340
|
+
m.compress("int8", data="coco", save="runs/train/eomt-int8/weights/best.pt") # quantize, validate, save
|
|
341
|
+
# size/mAP/latency deltas are returned (and written to compression_metrics.json in the
|
|
342
|
+
# run folder); omit `data` to skip the before/after validation
|
|
343
|
+
|
|
344
|
+
# Reload like any run — the recipe is recorded in the checkpoint, so the int8 layout
|
|
345
|
+
# is rebuilt automatically:
|
|
346
|
+
EoMT("runs/train/eomt-int8").predict("images/")
|
|
347
|
+
```
|
|
348
|
+
|
|
349
|
+
The compressed model is **GPU-only** (torchao's int8 kernels have no CPU path), and
|
|
350
|
+
`best.pt` exported from an EMA run quantizes exactly those EMA weights.
|
|
351
|
+
|
|
329
352
|
### Useful `train()` options
|
|
330
353
|
|
|
331
354
|
Passed as keyword arguments to `model.train(...)`:
|
|
@@ -55,9 +55,9 @@ with a fixed set of **learnable queries** (the Mask2Former idea) — each query
|
|
|
55
55
|
"slot" that latches onto one object instance. After the encoder runs, every query emits
|
|
56
56
|
a single vector, the **per-query embedding** of shape `[B, Q, hidden]`. The whole model
|
|
57
57
|
is then just "turn that embedding into predictions": a **class head** for the primary
|
|
58
|
-
label and a **mask/box head** for geometry. It is **NMS-free**, so two overlapping
|
|
59
|
-
stay two distinct queries instead of being merged — the property that lets
|
|
60
|
-
stay attached to the right instance.
|
|
58
|
+
label and a **mask/box head** for geometry. It is **NMS-free**, so two overlapping
|
|
59
|
+
garments stay two distinct queries instead of being merged — the property that lets
|
|
60
|
+
attributes stay attached to the right instance.
|
|
61
61
|
|
|
62
62
|
The attribute heads add nothing to this picture except themselves: they tap the **exact
|
|
63
63
|
same embedding** (captured non-invasively with a forward hook), each a small classifier
|
|
@@ -127,9 +127,9 @@ attribute heads add a thin linear/MLP per head and are negligible by design.
|
|
|
127
127
|
## ⭐ Method — factorizing the label space
|
|
128
128
|
|
|
129
129
|
This is the contribution. Conventional detectors fold every distinction into a single
|
|
130
|
-
flat label space. When an object has both a *type* and several *attributes* — a
|
|
131
|
-
|
|
132
|
-
the Cartesian product `type ×
|
|
130
|
+
flat label space. When an object has both a *type* and several *attributes* — a garment's
|
|
131
|
+
class **and** its viewpoint **and** whether it's occluded — the only way to express that is
|
|
132
|
+
the Cartesian product `type × viewpoint × occlusion × …`. That space explodes combinatorially,
|
|
133
133
|
starves each leaf class of training examples, and breaks Hungarian matching by
|
|
134
134
|
multiplying the query targets.
|
|
135
135
|
|
|
@@ -144,11 +144,11 @@ per-instance query embedding the detector already computes — they **add, not m
|
|
|
144
144
|
Because the heads are independent:
|
|
145
145
|
|
|
146
146
|
- **Categories stay collapsed and general.** Keep a compact, well-populated primary
|
|
147
|
-
taxonomy (`
|
|
148
|
-
into attributes — every primary class keeps its full sample count instead
|
|
149
|
-
shattered into rare leaves.
|
|
150
|
-
- **Unseen combinations generalize.** A `
|
|
151
|
-
predicts `
|
|
147
|
+
taxonomy (`short_sleeve_top`, `dress`, `trousers`) and push fine-grained or orthogonal
|
|
148
|
+
distinctions into attributes — every primary class keeps its full sample count instead
|
|
149
|
+
of being shattered into rare leaves.
|
|
150
|
+
- **Unseen combinations generalize.** A `viewpoint` head trained across many garment types
|
|
151
|
+
predicts `side` on a class it *never co-occurred with sideways*, because viewpoint is
|
|
152
152
|
learned independently of type. The model composes `attribute × class` combinations
|
|
153
153
|
that **never appear in the training data** — combinations a flat label space cannot
|
|
154
154
|
even represent.
|
|
@@ -159,25 +159,25 @@ Because the heads are independent:
|
|
|
159
159
|
matched queries — they add only a thin linear/MLP head and a cross-entropy term, not
|
|
160
160
|
a second model or a second pass.
|
|
161
161
|
|
|
162
|
-
### Example:
|
|
162
|
+
### Example: clothing with per-instance attributes
|
|
163
163
|
|
|
164
|
-
One model segments each
|
|
165
|
-
`
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
164
|
+
One model segments each garment (primary classes like `vest_dress` / `short_sleeve_top`
|
|
165
|
+
/ `long_sleeve_dress` / `skirt` / `trousers` …) and, for **every** detection, reads off
|
|
166
|
+
four **independent** attribute heads — `scale` (`small` / `modest` / `large`),
|
|
167
|
+
`occlusion` (`no` / `slight` / `medium`), `zoom_in` (`no` / `medium` / `large`) and
|
|
168
|
+
`viewpoint` (`frontal` / `side` / `back`). The renderer prints the primary class + score
|
|
169
|
+
on the first row and each attribute + its confidence on the rows beneath it.
|
|
169
170
|
|
|
170
|
-

|
|
171
172
|
|
|
172
|
-
|
|
173
|
-
the case that's awkward to fold into the primary class space. The same
|
|
174
|
-
any "class **plus** per-instance sub-labels" task: **retail shelves →
|
|
175
|
-
facing**, **
|
|
176
|
-
health**, **apparel → garment + pattern**.
|
|
173
|
+
The four attributes are *orthogonal* to the garment class — they vary independently —
|
|
174
|
+
which is exactly the case that's awkward to fold into the primary class space. The same
|
|
175
|
+
pattern fits any "class **plus** per-instance sub-labels" task: **retail shelves →
|
|
176
|
+
product + facing**, **documents → element + role**, **cells → type + health**.
|
|
177
177
|
|
|
178
|
-
>
|
|
179
|
-
>
|
|
180
|
-
>
|
|
178
|
+
> Trained on the public **[DeepFashion2](https://github.com/switchablenorms/DeepFashion2)**
|
|
179
|
+
> dataset (13 garment classes + 4 attribute heads) and rendered with the package's own
|
|
180
|
+
> renderer ([`eomt.visualize.draw_instances`](eomt/visualize.py)).
|
|
181
181
|
|
|
182
182
|
---
|
|
183
183
|
|
|
@@ -222,18 +222,19 @@ names) are discovered from the JSON, the same as `nc`.
|
|
|
222
222
|
```jsonc
|
|
223
223
|
"attributes": [
|
|
224
224
|
{
|
|
225
|
-
"name": "
|
|
225
|
+
"name": "scale",
|
|
226
226
|
"categories": [
|
|
227
|
-
{"id":
|
|
228
|
-
{"id":
|
|
229
|
-
{"id":
|
|
227
|
+
{"id": 1, "name": "small"},
|
|
228
|
+
{"id": 2, "name": "modest"},
|
|
229
|
+
{"id": 3, "name": "large"}
|
|
230
230
|
]
|
|
231
231
|
},
|
|
232
232
|
{
|
|
233
|
-
"name": "
|
|
233
|
+
"name": "viewpoint",
|
|
234
234
|
"categories": [
|
|
235
|
-
{"id":
|
|
236
|
-
{"id":
|
|
235
|
+
{"id": 0, "name": "frontal"},
|
|
236
|
+
{"id": 1, "name": "side"},
|
|
237
|
+
{"id": 2, "name": "back"}
|
|
237
238
|
]
|
|
238
239
|
}
|
|
239
240
|
]
|
|
@@ -245,14 +246,14 @@ names) are discovered from the JSON, the same as `nc`.
|
|
|
245
246
|
{
|
|
246
247
|
"id": 1, "image_id": 42, "category_id": 1,
|
|
247
248
|
"segmentation": [...], "bbox": [...], "area": 1234, "iscrowd": 0,
|
|
248
|
-
"attributes": {"
|
|
249
|
+
"attributes": {"scale": 3, "viewpoint": 0}
|
|
249
250
|
}
|
|
250
251
|
```
|
|
251
252
|
|
|
252
253
|
Notes:
|
|
253
254
|
|
|
254
|
-
- Raw ids are remapped to a contiguous `0..n-1` per head (so `
|
|
255
|
-
`0`/`1`); `categories` may be omitted, in which case the id set is inferred.
|
|
255
|
+
- Raw ids are remapped to a contiguous `0..n-1` per head (so `scale`'s `1`/`2`/`3` become
|
|
256
|
+
`0`/`1`/`2`); `categories` may be omitted, in which case the id set is inferred.
|
|
256
257
|
- A missing per-annotation value defaults to `0`; a JSON with **no** `attributes` ⇒
|
|
257
258
|
detection-only, exactly as before.
|
|
258
259
|
|
|
@@ -289,6 +290,27 @@ EoMT("runs/train/eomt-l").val(data="coco")
|
|
|
289
290
|
EoMT("runs/train/eomt-l").predict("images/", plot=True) # writes annotated images
|
|
290
291
|
```
|
|
291
292
|
|
|
293
|
+
### Compress to int8
|
|
294
|
+
|
|
295
|
+
`compress()` applies **int8 weight-only quantization** (via [torchao](https://github.com/pytorch/ao))
|
|
296
|
+
to the ViT transformer blocks — the bulk of the parameters — while keeping the
|
|
297
|
+
prediction heads in full precision. It's **data-free** (no calibration) and shrinks the
|
|
298
|
+
checkpoint ≈**3.4×** on `l` with no measurable mAP loss.
|
|
299
|
+
|
|
300
|
+
```python
|
|
301
|
+
m = EoMT("runs/train/eomt-l")
|
|
302
|
+
m.compress("int8", data="coco", save="runs/train/eomt-int8/weights/best.pt") # quantize, validate, save
|
|
303
|
+
# size/mAP/latency deltas are returned (and written to compression_metrics.json in the
|
|
304
|
+
# run folder); omit `data` to skip the before/after validation
|
|
305
|
+
|
|
306
|
+
# Reload like any run — the recipe is recorded in the checkpoint, so the int8 layout
|
|
307
|
+
# is rebuilt automatically:
|
|
308
|
+
EoMT("runs/train/eomt-int8").predict("images/")
|
|
309
|
+
```
|
|
310
|
+
|
|
311
|
+
The compressed model is **GPU-only** (torchao's int8 kernels have no CPU path), and
|
|
312
|
+
`best.pt` exported from an EMA run quantizes exactly those EMA weights.
|
|
313
|
+
|
|
292
314
|
### Useful `train()` options
|
|
293
315
|
|
|
294
316
|
Passed as keyword arguments to `model.train(...)`:
|
|
Binary file
|
|
@@ -1 +1 @@
|
|
|
1
|
-
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 940 470" width="940" height="470"><rect x="1" y="1" width="938" height="468" rx="16" fill="#0e1318" stroke="#2a3744" stroke-width="1.5"/><text x="32" y="46" font-family="DejaVu Sans, sans-serif" font-size="23" fill="#d7e0e8" text-anchor="start" font-weight="bold">attr-eomt</text><text x="33" y="66" font-family="DejaVu Sans Mono, monospace" font-size="12" fill="#8c9aa8" text-anchor="start" font-weight="normal">architecture · the heads tap one shared embedding</text><circle cx="525" cy="42" r="4.5" fill="#4ec9b0"/><text x="536" y="46" font-family="DejaVu Sans Mono, monospace" font-size="11" fill="#8c9aa8">shared embedding</text><circle cx="659.6" cy="42" r="4.5" fill="#5aa6f0"/><text x="670.6" y="46" font-family="DejaVu Sans Mono, monospace" font-size="11" fill="#8c9aa8">primary head</text><circle cx="767.8" cy="42" r="4.5" fill="#e2b341"/><text x="778.8" y="46" font-family="DejaVu Sans Mono, monospace" font-size="11" fill="#8c9aa8">attribute head</text><defs><marker id="a" markerWidth="9" markerHeight="9" refX="7" refY="4.5" orient="auto"><path d="M0,0 L9,4.5 L0,9 z" fill="#5e6b78"/></marker><marker id="aq" markerWidth="9" markerHeight="9" refX="7" refY="4.5" orient="auto"><path d="M0,0 L9,4.5 L0,9 z" fill="#4ec9b0"/></marker></defs><rect x="34" y="220" width="104" height="60" rx="9" fill="#1b232c" stroke="#2a3744" stroke-width="1.4" /><text x="86" y="248" font-family="DejaVu Sans Mono, monospace" font-size="13" fill="#d7e0e8" text-anchor="middle" font-weight="normal">image</text><text x="86" y="266" font-family="DejaVu Sans Mono, monospace" font-size="10.5" fill="#5e6b78" text-anchor="middle" font-weight="normal">644²</text><path d="M138,250 H176" stroke="#5e6b78" stroke-width="1.6" fill="none" marker-end="url(#a)"/><rect x="180" y="188" width="178" height="124" rx="9" fill="#1b232c" stroke="#5aa6f0" stroke-width="1.4" /><text x="269" y="224" font-family="DejaVu Sans, sans-serif" font-size="14.5" fill="#5aa6f0" text-anchor="middle" font-weight="bold">DINOv2 ViT</text><text x="269" y="244" font-family="DejaVu Sans Mono, monospace" font-size="11" fill="#5e6b78" text-anchor="middle" font-weight="normal">last blocks +</text><text x="269" y="260" font-family="DejaVu Sans Mono, monospace" font-size="11" fill="#5e6b78" text-anchor="middle" font-weight="normal">learnable queries</text><text x="269" y="286" font-family="DejaVu Sans Mono, monospace" font-size="11" fill="#8c9aa8" text-anchor="middle" font-weight="normal">NMS-free</text><path d="M358,250 H426" stroke="#5e6b78" stroke-width="1.6" fill="none" marker-end="url(#a)"/><rect x="430" y="221" width="150" height="58" rx="9" fill="#10201c" stroke="#4ec9b0" stroke-width="1.8" /><text x="505" y="246" font-family="DejaVu Sans Mono, monospace" font-size="13.5" fill="#4ec9b0" text-anchor="middle" font-weight="bold">query_embed</text><text x="505" y="265" font-family="DejaVu Sans Mono, monospace" font-size="10.5" fill="#5e6b78" text-anchor="middle" font-weight="normal">[B, Q, hidden]</text><text x="505" y="204" font-family="DejaVu Sans Mono, monospace" font-size="11" fill="#8c9aa8" text-anchor="middle" font-weight="normal">▲ forward hook on class_predictor</text><path d="M580,205 C638,205 638,94 704,94" stroke="#4ec9b0" stroke-width="2.1" fill="none" marker-end="url(#aq)" /><rect x="708" y="70" width="200" height="48" rx="9" fill="#1b232c" stroke="#5aa6f0" stroke-width="1.4" /><text x="808.0" y="91" font-family="DejaVu Sans Mono, monospace" font-size="12.5" fill="#5aa6f0" text-anchor="middle" font-weight="normal">class_predictor</text><text x="808.0" y="107" font-family="DejaVu Sans Mono, monospace" font-size="10.5" fill="#5e6b78" text-anchor="middle" font-weight="normal">primary class · nc+1</text><path d="M580,218 C638,218 638,164 704,164" stroke="#4ec9b0" stroke-width="2.1" fill="none" marker-end="url(#aq)" /><rect x="708" y="140" width="200" height="48" rx="9" fill="#1b232c" stroke="#5aa6f0" stroke-width="1.4" /><text x="808.0" y="161" font-family="DejaVu Sans Mono, monospace" font-size="12.5" fill="#5aa6f0" text-anchor="middle" font-weight="normal">mask / box head</text><text x="808.0" y="177" font-family="DejaVu Sans Mono, monospace" font-size="10.5" fill="#5e6b78" text-anchor="middle" font-weight="normal">geometry</text><path d="M580,228 C638,228 638,254 704,254" stroke="#4ec9b0" stroke-width="2.1" fill="none" marker-end="url(#aq)" /><rect x="708" y="230" width="200" height="48" rx="9" fill="#1b232c" stroke="#e2b341" stroke-width="1.4" /><text x="808.0" y="251" font-family="DejaVu Sans Mono, monospace" font-size="12.5" fill="#e2b341" text-anchor="middle" font-weight="normal">aux · "
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 940 470" width="940" height="470"><rect x="1" y="1" width="938" height="468" rx="16" fill="#0e1318" stroke="#2a3744" stroke-width="1.5"/><text x="32" y="46" font-family="DejaVu Sans, sans-serif" font-size="23" fill="#d7e0e8" text-anchor="start" font-weight="bold">attr-eomt</text><text x="33" y="66" font-family="DejaVu Sans Mono, monospace" font-size="12" fill="#8c9aa8" text-anchor="start" font-weight="normal">architecture · the heads tap one shared embedding</text><circle cx="525" cy="42" r="4.5" fill="#4ec9b0"/><text x="536" y="46" font-family="DejaVu Sans Mono, monospace" font-size="11" fill="#8c9aa8">shared embedding</text><circle cx="659.6" cy="42" r="4.5" fill="#5aa6f0"/><text x="670.6" y="46" font-family="DejaVu Sans Mono, monospace" font-size="11" fill="#8c9aa8">primary head</text><circle cx="767.8" cy="42" r="4.5" fill="#e2b341"/><text x="778.8" y="46" font-family="DejaVu Sans Mono, monospace" font-size="11" fill="#8c9aa8">attribute head</text><defs><marker id="a" markerWidth="9" markerHeight="9" refX="7" refY="4.5" orient="auto"><path d="M0,0 L9,4.5 L0,9 z" fill="#5e6b78"/></marker><marker id="aq" markerWidth="9" markerHeight="9" refX="7" refY="4.5" orient="auto"><path d="M0,0 L9,4.5 L0,9 z" fill="#4ec9b0"/></marker></defs><rect x="34" y="220" width="104" height="60" rx="9" fill="#1b232c" stroke="#2a3744" stroke-width="1.4" /><text x="86" y="248" font-family="DejaVu Sans Mono, monospace" font-size="13" fill="#d7e0e8" text-anchor="middle" font-weight="normal">image</text><text x="86" y="266" font-family="DejaVu Sans Mono, monospace" font-size="10.5" fill="#5e6b78" text-anchor="middle" font-weight="normal">644²</text><path d="M138,250 H176" stroke="#5e6b78" stroke-width="1.6" fill="none" marker-end="url(#a)"/><rect x="180" y="188" width="178" height="124" rx="9" fill="#1b232c" stroke="#5aa6f0" stroke-width="1.4" /><text x="269" y="224" font-family="DejaVu Sans, sans-serif" font-size="14.5" fill="#5aa6f0" text-anchor="middle" font-weight="bold">DINOv2 ViT</text><text x="269" y="244" font-family="DejaVu Sans Mono, monospace" font-size="11" fill="#5e6b78" text-anchor="middle" font-weight="normal">last blocks +</text><text x="269" y="260" font-family="DejaVu Sans Mono, monospace" font-size="11" fill="#5e6b78" text-anchor="middle" font-weight="normal">learnable queries</text><text x="269" y="286" font-family="DejaVu Sans Mono, monospace" font-size="11" fill="#8c9aa8" text-anchor="middle" font-weight="normal">NMS-free</text><path d="M358,250 H426" stroke="#5e6b78" stroke-width="1.6" fill="none" marker-end="url(#a)"/><rect x="430" y="221" width="150" height="58" rx="9" fill="#10201c" stroke="#4ec9b0" stroke-width="1.8" /><text x="505" y="246" font-family="DejaVu Sans Mono, monospace" font-size="13.5" fill="#4ec9b0" text-anchor="middle" font-weight="bold">query_embed</text><text x="505" y="265" font-family="DejaVu Sans Mono, monospace" font-size="10.5" fill="#5e6b78" text-anchor="middle" font-weight="normal">[B, Q, hidden]</text><text x="505" y="204" font-family="DejaVu Sans Mono, monospace" font-size="11" fill="#8c9aa8" text-anchor="middle" font-weight="normal">▲ forward hook on class_predictor</text><path d="M580,205 C638,205 638,94 704,94" stroke="#4ec9b0" stroke-width="2.1" fill="none" marker-end="url(#aq)" /><rect x="708" y="70" width="200" height="48" rx="9" fill="#1b232c" stroke="#5aa6f0" stroke-width="1.4" /><text x="808.0" y="91" font-family="DejaVu Sans Mono, monospace" font-size="12.5" fill="#5aa6f0" text-anchor="middle" font-weight="normal">class_predictor</text><text x="808.0" y="107" font-family="DejaVu Sans Mono, monospace" font-size="10.5" fill="#5e6b78" text-anchor="middle" font-weight="normal">primary class · nc+1</text><path d="M580,218 C638,218 638,164 704,164" stroke="#4ec9b0" stroke-width="2.1" fill="none" marker-end="url(#aq)" /><rect x="708" y="140" width="200" height="48" rx="9" fill="#1b232c" stroke="#5aa6f0" stroke-width="1.4" /><text x="808.0" y="161" font-family="DejaVu Sans Mono, monospace" font-size="12.5" fill="#5aa6f0" text-anchor="middle" font-weight="normal">mask / box head</text><text x="808.0" y="177" font-family="DejaVu Sans Mono, monospace" font-size="10.5" fill="#5e6b78" text-anchor="middle" font-weight="normal">geometry</text><path d="M580,228 C638,228 638,254 704,254" stroke="#4ec9b0" stroke-width="2.1" fill="none" marker-end="url(#aq)" /><rect x="708" y="230" width="200" height="48" rx="9" fill="#1b232c" stroke="#e2b341" stroke-width="1.4" /><text x="808.0" y="251" font-family="DejaVu Sans Mono, monospace" font-size="12.5" fill="#e2b341" text-anchor="middle" font-weight="normal">aux · "scale"</text><text x="808.0" y="267" font-family="DejaVu Sans Mono, monospace" font-size="10.5" fill="#5e6b78" text-anchor="middle" font-weight="normal">3 classes</text><path d="M580,236 C638,236 638,324 704,324" stroke="#4ec9b0" stroke-width="2.1" fill="none" marker-end="url(#aq)" /><rect x="708" y="300" width="200" height="48" rx="9" fill="#1b232c" stroke="#e2b341" stroke-width="1.4" /><text x="808.0" y="321" font-family="DejaVu Sans Mono, monospace" font-size="12.5" fill="#e2b341" text-anchor="middle" font-weight="normal">aux · "viewpoint"</text><text x="808.0" y="337" font-family="DejaVu Sans Mono, monospace" font-size="10.5" fill="#5e6b78" text-anchor="middle" font-weight="normal">3 classes</text><path d="M580,243 C638,243 638,396 704,396" stroke="#4ec9b0" stroke-width="2.1" fill="none" marker-end="url(#aq)" stroke-dasharray="3 4"/><rect x="708" y="372" width="200" height="48" rx="9" fill="#1b232c" stroke="#5e6b78" stroke-width="1.4" stroke-dasharray="4 4"/><text x="808.0" y="393" font-family="DejaVu Sans Mono, monospace" font-size="12.5" fill="#8c9aa8" text-anchor="middle" font-weight="normal">… as many as data defines</text><text x="470.0" y="444" font-family="DejaVu Sans Mono, monospace" font-size="11.5" fill="#5e6b78" text-anchor="middle" font-weight="normal">teal = the single per-query embedding · every head is a small classifier on top of it</text></svg>
|
|
Binary file
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 940 500" width="940" height="500"><rect x="1" y="1" width="938" height="498" rx="16" fill="#0e1318" stroke="#2a3744" stroke-width="1.5"/><text x="32" y="48" font-family="DejaVu Sans, sans-serif" font-size="23" fill="#d7e0e8" text-anchor="start" font-weight="bold">Factorize the label space</text><text x="33" y="69" font-family="DejaVu Sans Mono, monospace" font-size="12" fill="#8c9aa8" text-anchor="start" font-weight="normal">a garment's type, viewpoint and occlusion are orthogonal — don't multiply them</text><line x1="470.0" y1="110" x2="470.0" y2="430" stroke="#2a3744" stroke-width="1.2" stroke-dasharray="3 5"/><text x="470.0" y="254.0" font-family="DejaVu Sans, sans-serif" font-size="13" fill="#5e6b78" text-anchor="middle" font-weight="bold">vs</text><circle cx="470.0" cy="248.0" r="18" fill="#0e1318" stroke="#2a3744"/><text x="470.0" y="254.0" font-family="DejaVu Sans, sans-serif" font-size="13" fill="#8c9aa8" text-anchor="middle" font-weight="bold">vs</text><text x="245" y="128" font-family="DejaVu Sans Mono, monospace" font-size="12" fill="#e07a5f" text-anchor="middle" font-weight="bold">FLAT · ONE HEAD</text><text x="108" y="171.0" font-family="DejaVu Sans Mono, monospace" font-size="10.5" fill="#8c9aa8" text-anchor="end" font-weight="normal">top</text><rect x="120" y="150" width="72" height="34" rx="5" fill="#1b232c" stroke="rgba(224,122,95,.45)" stroke-width="1"/><text x="156.0" y="171.0" font-family="DejaVu Sans Mono, monospace" font-size="9.5" fill="#5e6b78" text-anchor="middle" font-weight="normal">top·frnt</text><rect x="200" y="150" width="72" height="34" rx="5" fill="#1b232c" stroke="rgba(224,122,95,.45)" stroke-width="1"/><text x="236.0" y="171.0" font-family="DejaVu Sans Mono, monospace" font-size="9.5" fill="#5e6b78" text-anchor="middle" font-weight="normal">top·side</text><rect x="280" y="150" width="72" height="34" rx="5" fill="#1b232c" stroke="rgba(224,122,95,.45)" stroke-width="1"/><text x="316.0" y="171.0" font-family="DejaVu Sans Mono, monospace" font-size="9.5" fill="#5e6b78" text-anchor="middle" font-weight="normal">top·back</text><text x="108" y="213.0" font-family="DejaVu Sans Mono, monospace" font-size="10.5" fill="#8c9aa8" text-anchor="end" font-weight="normal">dress</text><rect x="120" y="192" width="72" height="34" rx="5" fill="#1b232c" stroke="rgba(224,122,95,.45)" stroke-width="1"/><text x="156.0" y="213.0" font-family="DejaVu Sans Mono, monospace" font-size="9.5" fill="#5e6b78" text-anchor="middle" font-weight="normal">drs·frnt</text><rect x="200" y="192" width="72" height="34" rx="5" fill="#1b232c" stroke="rgba(224,122,95,.45)" stroke-width="1"/><text x="236.0" y="213.0" font-family="DejaVu Sans Mono, monospace" font-size="9.5" fill="#5e6b78" text-anchor="middle" font-weight="normal">drs·side</text><rect x="280" y="192" width="72" height="34" rx="5" fill="#1b232c" stroke="rgba(224,122,95,.45)" stroke-width="1"/><text x="316.0" y="213.0" font-family="DejaVu Sans Mono, monospace" font-size="9.5" fill="#5e6b78" text-anchor="middle" font-weight="normal">drs·back</text><text x="108" y="255.0" font-family="DejaVu Sans Mono, monospace" font-size="10.5" fill="#8c9aa8" text-anchor="end" font-weight="normal">skirt</text><rect x="120" y="234" width="72" height="34" rx="5" fill="#1b232c" stroke="rgba(224,122,95,.45)" stroke-width="1"/><text x="156.0" y="255.0" font-family="DejaVu Sans Mono, monospace" font-size="9.5" fill="#5e6b78" text-anchor="middle" font-weight="normal">skt·frnt</text><rect x="200" y="234" width="72" height="34" rx="5" fill="#1b232c" stroke="rgba(224,122,95,.45)" stroke-width="1"/><text x="236.0" y="255.0" font-family="DejaVu Sans Mono, monospace" font-size="9.5" fill="#5e6b78" text-anchor="middle" font-weight="normal">skt·side</text><rect x="280" y="234" width="72" height="34" rx="5" fill="#1b232c" stroke="rgba(224,122,95,.45)" stroke-width="1"/><text x="316.0" y="255.0" font-family="DejaVu Sans Mono, monospace" font-size="9.5" fill="#5e6b78" text-anchor="middle" font-weight="normal">skt·back</text><text x="108" y="297.0" font-family="DejaVu Sans Mono, monospace" font-size="10.5" fill="#8c9aa8" text-anchor="end" font-weight="normal">trousers</text><rect x="120" y="276" width="72" height="34" rx="5" fill="#1b232c" stroke="rgba(224,122,95,.45)" stroke-width="1"/><text x="156.0" y="297.0" font-family="DejaVu Sans Mono, monospace" font-size="9.5" fill="#5e6b78" text-anchor="middle" font-weight="normal">trs·frnt</text><rect x="200" y="276" width="72" height="34" rx="5" fill="#1b232c" stroke="rgba(224,122,95,.45)" stroke-width="1"/><text x="236.0" y="297.0" font-family="DejaVu Sans Mono, monospace" font-size="9.5" fill="#5e6b78" text-anchor="middle" font-weight="normal">trs·side</text><rect x="280" y="276" width="72" height="34" rx="5" fill="#1b232c" stroke="rgba(224,122,95,.45)" stroke-width="1"/><text x="316.0" y="297.0" font-family="DejaVu Sans Mono, monospace" font-size="9.5" fill="#5e6b78" text-anchor="middle" font-weight="normal">trs·back</text><text x="245" y="338" font-family="DejaVu Sans Mono, monospace" font-size="11" fill="#8c9aa8" text-anchor="middle" font-weight="normal">× {visible, occluded} states</text><text x="245" y="376" font-family="DejaVu Sans Mono, monospace" font-size="15" fill="#e07a5f" text-anchor="middle" font-weight="bold">4 × 3 × 2</text><text x="245" y="402" font-family="DejaVu Sans Mono, monospace" font-size="11" fill="#5e6b78" text-anchor="middle" font-weight="normal">= 24 leaf classes</text><text x="700" y="128" font-family="DejaVu Sans Mono, monospace" font-size="12" fill="#e2b341" text-anchor="middle" font-weight="bold">FACTORIZED · INDEPENDENT HEADS</text><rect x="560" y="165" width="320" height="58" rx="9" fill="#1b232c" stroke="#e2b341" stroke-width="1.3"/><text x="576" y="190" font-family="DejaVu Sans Mono, monospace" font-size="13" fill="#e2b341" text-anchor="start" font-weight="bold">type head</text><text x="576" y="208" font-family="DejaVu Sans Mono, monospace" font-size="10.5" fill="#5e6b78" text-anchor="start" font-weight="normal">top · dress · skirt · trousers</text><circle cx="852" cy="194" r="15" fill="#10201c" stroke="#e2b341"/><text x="852" y="199" font-family="DejaVu Sans Mono, monospace" font-size="14" fill="#4ec9b0" text-anchor="middle" font-weight="bold">4</text><rect x="560" y="237" width="320" height="58" rx="9" fill="#1b232c" stroke="#e2b341" stroke-width="1.3"/><text x="576" y="262" font-family="DejaVu Sans Mono, monospace" font-size="13" fill="#e2b341" text-anchor="start" font-weight="bold">viewpoint head</text><text x="576" y="280" font-family="DejaVu Sans Mono, monospace" font-size="10.5" fill="#5e6b78" text-anchor="start" font-weight="normal">frontal · side · back</text><circle cx="852" cy="266" r="15" fill="#10201c" stroke="#e2b341"/><text x="852" y="271" font-family="DejaVu Sans Mono, monospace" font-size="14" fill="#4ec9b0" text-anchor="middle" font-weight="bold">3</text><rect x="560" y="309" width="320" height="58" rx="9" fill="#1b232c" stroke="#e2b341" stroke-width="1.3"/><text x="576" y="334" font-family="DejaVu Sans Mono, monospace" font-size="13" fill="#e2b341" text-anchor="start" font-weight="bold">occlusion head</text><text x="576" y="352" font-family="DejaVu Sans Mono, monospace" font-size="10.5" fill="#5e6b78" text-anchor="start" font-weight="normal">visible · occluded</text><circle cx="852" cy="338" r="15" fill="#10201c" stroke="#e2b341"/><text x="852" y="343" font-family="DejaVu Sans Mono, monospace" font-size="14" fill="#4ec9b0" text-anchor="middle" font-weight="bold">2</text><text x="700" y="399" font-family="DejaVu Sans Mono, monospace" font-size="15" fill="#4ec9b0" text-anchor="middle" font-weight="bold">4 + 3 + 2</text><text x="700" y="425" font-family="DejaVu Sans Mono, monospace" font-size="11" fill="#5e6b78" text-anchor="middle" font-weight="normal">= 9 outputs · each head sees every instance</text><text x="470.0" y="472" font-family="DejaVu Sans Mono, monospace" font-size="11" fill="#5e6b78" text-anchor="middle" font-weight="normal">compact primary taxonomy keeps its sample counts · unseen attribute × class combinations still generalize</text></svg>
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|