s0um0r0y commited on
Commit
5e77f55
·
verified ·
1 Parent(s): 473f455

Upload 12 head(s) from 1a8130c92226

Browse files
This view is limited to 50 files because it contains too many changes.   See raw diff
Files changed (50) hide show
  1. DMS/dinov2_clip_gated/README.md +52 -0
  2. DMS/dinov2_clip_gated/config.toml +62 -0
  3. DMS/dinov2_clip_gated/head.json +99 -0
  4. DMS/dinov2_clip_gated/metrics.json +296 -0
  5. DMS/dinov2_clip_gated/model.pth +3 -0
  6. DMS/dinov2_clip_gated/model.safetensors +3 -0
  7. DMS/dinov2_clip_gated/split.json +0 -0
  8. DMS/dinov2_clip_mlp/README.md +52 -0
  9. DMS/dinov2_clip_mlp/config.toml +68 -0
  10. DMS/dinov2_clip_mlp/head.json +99 -0
  11. DMS/dinov2_clip_mlp/metrics.json +296 -0
  12. DMS/dinov2_clip_mlp/model.pth +3 -0
  13. DMS/dinov2_clip_mlp/model.safetensors +3 -0
  14. DMS/dinov2_clip_mlp/split.json +0 -0
  15. DMS/dinov3_siglip2_gated/README.md +52 -0
  16. DMS/dinov3_siglip2_gated/config.toml +59 -0
  17. DMS/dinov3_siglip2_gated/head.json +99 -0
  18. DMS/dinov3_siglip2_gated/metrics.json +296 -0
  19. DMS/dinov3_siglip2_gated/model.pth +3 -0
  20. DMS/dinov3_siglip2_gated/model.safetensors +3 -0
  21. DMS/dinov3_siglip2_gated/split.json +0 -0
  22. DMS/dinov3_siglip2_gated_reg/README.md +52 -0
  23. DMS/dinov3_siglip2_gated_reg/config.toml +72 -0
  24. DMS/dinov3_siglip2_gated_reg/head.json +99 -0
  25. DMS/dinov3_siglip2_gated_reg/metrics.json +296 -0
  26. DMS/dinov3_siglip2_gated_reg/model.pth +3 -0
  27. DMS/dinov3_siglip2_gated_reg/model.safetensors +3 -0
  28. DMS/dinov3_siglip2_gated_reg/split.json +0 -0
  29. DMS/dinov3_siglip2_lmf/README.md +52 -0
  30. DMS/dinov3_siglip2_lmf/config.toml +77 -0
  31. DMS/dinov3_siglip2_lmf/head.json +103 -0
  32. DMS/dinov3_siglip2_lmf/metrics.json +296 -0
  33. DMS/dinov3_siglip2_lmf/model.pth +3 -0
  34. DMS/dinov3_siglip2_lmf/model.safetensors +3 -0
  35. DMS/dinov3_siglip2_lmf/split.json +0 -0
  36. DMS/dinov3_siglip2_lmf_reg/README.md +52 -0
  37. DMS/dinov3_siglip2_lmf_reg/config.toml +89 -0
  38. DMS/dinov3_siglip2_lmf_reg/head.json +103 -0
  39. DMS/dinov3_siglip2_lmf_reg/metrics.json +296 -0
  40. DMS/dinov3_siglip2_lmf_reg/model.pth +3 -0
  41. DMS/dinov3_siglip2_lmf_reg/model.safetensors +3 -0
  42. DMS/dinov3_siglip2_lmf_reg/split.json +0 -0
  43. DMS/dinov3_siglip2_mlp/README.md +52 -0
  44. DMS/dinov3_siglip2_mlp/config.toml +64 -0
  45. DMS/dinov3_siglip2_mlp/head.json +99 -0
  46. DMS/dinov3_siglip2_mlp/metrics.json +296 -0
  47. DMS/dinov3_siglip2_mlp/model.pth +3 -0
  48. DMS/dinov3_siglip2_mlp/model.safetensors +3 -0
  49. DMS/dinov3_siglip2_mlp/split.json +0 -0
  50. FMD/dinov2_clip_gated/README.md +52 -0
DMS/dinov2_clip_gated/README.md ADDED
@@ -0,0 +1,52 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # DINOv2-CLIP + Gated Multimodal Unit on Apple Dense Material Segmentation
2
+
3
+ A material-classification **fusion head** from SegObjectMaterial. It classifies the
4
+ material of a masked object from two frozen embeddings:
5
+
6
+ | | |
7
+ |---|---|
8
+ | vision | DINOv2 ViT-B/14 (CLS token, frozen) -> 768-d |
9
+ | language | CLIP ViT-L/14 text encoder over Qwen2.5-VL-7B captions (frozen) -> 768-d |
10
+ | head | Gated Multimodal Unit (`gated`, defaults), 1,722,937 parameters |
11
+ | classes | 57 (Apple Dense Material Segmentation) |
12
+
13
+ **This repo holds only the head.** Features must come from the same encoders,
14
+ captioner and prompts as training (see the SegObjectMaterial repository); the
15
+ encoders are downloaded from their own model pages under their own licenses.
16
+
17
+ ## Evaluation
18
+
19
+ Held-out split recorded in `split.json` (source images never seen in training).
20
+ Single training run -- differences under ~0.5 mIoU points between heads are within
21
+ run-to-run noise.
22
+
23
+ | mIoU | mAcc | eval samples |
24
+ |---|---|---|
25
+ | 0.4543 | 0.6373 | 186,231 |
26
+
27
+ ## Training
28
+
29
+ ```json
30
+ {
31
+ "learning_rate": 5e-05,
32
+ "epochs": 50,
33
+ "batch_size": 32,
34
+ "weight_decay": 0.0001,
35
+ "lr_schedule": "constant",
36
+ "early_stopping_patience": 0,
37
+ "checkpoint": "best validation loss"
38
+ }
39
+ ```
40
+
41
+ ## Use
42
+
43
+ ```python
44
+ from utils.hub import load_head_from_hub # SegObjectMaterial repository
45
+ head, info = load_head_from_hub("s0um0r0y/SegObjectMaterial", "DMS/dinov2_clip_gated")
46
+ logits = head(vision_features, language_features) # [B, 768], [B, 768]
47
+ ```
48
+
49
+ ## Integrity
50
+
51
+ - `model.safetensors` sha256 `0715e31f97766d6da1185b402bf47e44a44db6f0bcb24f7e9cb743b30232200c`
52
+ - source config `config/config_dinov2_clip.toml`, code commit `1a8130c922267fb0786a33e3854a7e00763cc38f+dirty`
DMS/dinov2_clip_gated/config.toml ADDED
@@ -0,0 +1,62 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Apple DMS -- BASE pipeline: DINOv2 ViT-B/14 (768) + Qwen2.5-VL -> CLIP text (768)
2
+ #
3
+ # Pair this with:
4
+ # src/vision_stream.py + src/language_stream.py
5
+ # run_serialization.py -> train.py (the raw/original scripts)
6
+ #
7
+ # config/config.toml is the OTHER pipeline (DINOv3 ViT-L/16 1024 + SigLIP2),
8
+ # driven by run_serialization_latest_models.py -> train_latest_models.py.
9
+ # Mixing them raises the dimension-mismatch ValueError in the fusion head.
10
+
11
+ [data]
12
+ dataset_type = "apple_dms"
13
+ image_dir = "<local>/images"
14
+ mask_dir = "<local>/labels"
15
+ # Rebuilt automatically on first run; the index now stores one entry per
16
+ # CONNECTED COMPONENT, so any pre-existing labels.json must be removed first.
17
+ labels_file = "<local>/labels_instances.json"
18
+ # Fresh directory: features are now object-grounded (bbox-cropped vision,
19
+ # bbox-prompted captions), so the old tensor_cache_dir/ contents are stale.
20
+ tensor_cache_dir = "<local>/tensor_cache_dir_grounded"
21
+
22
+ # Connected-component filtering (measured on 400 real DMS masks):
23
+ # keeping every component gives 7.5x more samples than the old per-(image,class)
24
+ # scheme -- 2.45M samples / 47 GB / ~7.5x the VLM captioning time -- because 69%
25
+ # of components are under 0.1% of the frame and crop to a few pixels.
26
+ # A component is kept when area >= max(min_instance_area, min_instance_frac * frame).
27
+ min_instance_area = 1000 # absolute pixel floor
28
+ min_instance_frac = 0.001 # and at least 0.1% of the frame
29
+ max_instances_per_class = 0 # 0 = keep all; set e.g. 3 to cap the long tail
30
+
31
+
32
+ [model]
33
+ # fusion head, read by train_latest_models.py. This config always trained "gated"
34
+ # (the default when the key was absent) -- best_model_dinov2_clip.pth / best_model_fmd.pth
35
+ # are gated heads. config_dinov2_clip_mlp.toml / fmd_config_dinov2_clip_mlp.toml hold the MLP.
36
+ fusion = "gated"
37
+ vision_dim = 768 # DINOv2 ViT-B/14 CLS token
38
+ language_dim = 768 # CLIP ViT-L/14 text pooler_output
39
+ num_classes = 57
40
+
41
+ [training]
42
+ batch_size = 32
43
+
44
+ # Batch size for the OFFLINE SERIALIZATION pass, which is a completely different
45
+ # memory regime from training: it pushes full-resolution images through the 7B
46
+ # VLM, whereas [training].batch_size only moves cached 768-d vectors through a
47
+ # small MLP. Measured on the 23.6 GiB 4090 -- static weights 16.2 GiB, so only
48
+ # ~7.4 GiB is left: batch 8 peaks at 17.7 GiB, 16 at 19.2 GiB, and 32 OOMs.
49
+ # 8 leaves headroom for a labmate's job to coexist; raise to 16 on a free card.
50
+ serialization_batch_size = 8
51
+ learning_rate = 5e-5
52
+ epochs = 50
53
+ train_ratio = 0.8 # 80% for training
54
+ val_ratio = 0.2 # 20% for validation
55
+ tensorboard_log_dir = "<local>/dms_dinov2_clip"
56
+
57
+ [inference]
58
+ checkpoint_path = "<local>/best_model_dinov2_clip.pth"
59
+
60
+ [logging]
61
+ wandb_project = "material-classification"
62
+ wandb_run_name = "dms-dinov2-clip-grounded"
DMS/dinov2_clip_gated/head.json ADDED
@@ -0,0 +1,99 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "fusion": "gated",
3
+ "head": "Gated Multimodal Unit",
4
+ "head_kwargs": {},
5
+ "vision_dim": 768,
6
+ "language_dim": 768,
7
+ "num_classes": 57,
8
+ "classes": [
9
+ "No label",
10
+ "Animal skin",
11
+ "Bone/teeth/horn",
12
+ "Brickwork",
13
+ "Cardboard",
14
+ "Carpet/rug",
15
+ "Ceiling tile",
16
+ "Ceramic",
17
+ "Chalkboard/blackboard",
18
+ "Clutter",
19
+ "Concrete",
20
+ "Cork/corkboard",
21
+ "Engineered stone",
22
+ "Fabric/cloth",
23
+ "Fiberglass wool",
24
+ "Fire",
25
+ "Foliage",
26
+ "Food",
27
+ "Fur",
28
+ "Gemstone/quartz",
29
+ "Glass",
30
+ "Hair",
31
+ "I cannot tell",
32
+ "Ice",
33
+ "Leather",
34
+ "Liquid, non-water",
35
+ "Metal",
36
+ "Mirror",
37
+ "Not on list",
38
+ "Paint/plaster/enamel",
39
+ "Paper",
40
+ "Pearl",
41
+ "Photograph/painting",
42
+ "Plastic, clear",
43
+ "Plastic, non-clear",
44
+ "Rubber/latex",
45
+ "Sand",
46
+ "Skin/lips",
47
+ "Sky",
48
+ "Snow",
49
+ "Soap",
50
+ "Soil/mud",
51
+ "Sponge",
52
+ "Stone, natural",
53
+ "Stone, polished",
54
+ "Styrofoam",
55
+ "Tile",
56
+ "Wallpaper",
57
+ "Water",
58
+ "Wax",
59
+ "Whiteboard",
60
+ "Wicker",
61
+ "Wood",
62
+ "Wood, tree",
63
+ "Bad polygon",
64
+ "Multiple materials",
65
+ "Asphalt"
66
+ ],
67
+ "dataset": "Apple Dense Material Segmentation",
68
+ "dataset_key": "DMS",
69
+ "encoders": {
70
+ "vision": "DINOv2 ViT-B/14 (CLS token, frozen)",
71
+ "language": "CLIP ViT-L/14 text encoder over Qwen2.5-VL-7B captions (frozen)",
72
+ "short": "DINOv2-CLIP",
73
+ "slug": "dinov2_clip"
74
+ },
75
+ "parameters": 1722937,
76
+ "training": {
77
+ "learning_rate": 5e-05,
78
+ "epochs": 50,
79
+ "batch_size": 32,
80
+ "weight_decay": 0.0001,
81
+ "lr_schedule": "constant",
82
+ "early_stopping_patience": 0,
83
+ "checkpoint": "best validation loss"
84
+ },
85
+ "sha256": {
86
+ "safetensors": "0715e31f97766d6da1185b402bf47e44a44db6f0bcb24f7e9cb743b30232200c",
87
+ "pth": "045aaa0553e384bca097835a3689c8aedeef15118c1c6f69c5b38d1d04dfb20f"
88
+ },
89
+ "source": {
90
+ "config": "config/config_dinov2_clip.toml",
91
+ "git_commit": "1a8130c922267fb0786a33e3854a7e00763cc38f+dirty",
92
+ "checkpoint_mtime": "2026-09-23T13:35:51"
93
+ },
94
+ "metrics": {
95
+ "mIoU": 0.45433338700912007,
96
+ "mAcc": 0.6372685795566289,
97
+ "eval_samples": 186231
98
+ }
99
+ }
DMS/dinov2_clip_gated/metrics.json ADDED
@@ -0,0 +1,296 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "dataset": "DMS",
3
+ "config": "config/config_dinov2_clip.toml",
4
+ "checkpoint": "<local>/best_model_dinov2_clip.pth",
5
+ "fusion_type": "gated",
6
+ "num_eval_samples": 186231,
7
+ "mIoU": 0.45433338700912007,
8
+ "mAcc": 0.6372685795566289,
9
+ "per_class": {
10
+ "No label": {
11
+ "accuracy": 0.0,
12
+ "iou": 0.0,
13
+ "support": 0
14
+ },
15
+ "Animal skin": {
16
+ "accuracy": 0.5964912280701754,
17
+ "iou": 0.4657534246575342,
18
+ "support": 114
19
+ },
20
+ "Bone/teeth/horn": {
21
+ "accuracy": 0.7954545454545454,
22
+ "iou": 0.603448275862069,
23
+ "support": 44
24
+ },
25
+ "Brickwork": {
26
+ "accuracy": 0.775692582663092,
27
+ "iou": 0.4849162011173184,
28
+ "support": 1119
29
+ },
30
+ "Cardboard": {
31
+ "accuracy": 0.7605083088954057,
32
+ "iou": 0.44431753283837805,
33
+ "support": 1023
34
+ },
35
+ "Carpet/rug": {
36
+ "accuracy": 0.7795339412360689,
37
+ "iou": 0.46450132818159867,
38
+ "support": 4935
39
+ },
40
+ "Ceiling tile": {
41
+ "accuracy": 0.7887323943661971,
42
+ "iou": 0.4783404514948139,
43
+ "support": 994
44
+ },
45
+ "Ceramic": {
46
+ "accuracy": 0.8392311052861512,
47
+ "iou": 0.5887220349371743,
48
+ "support": 2289
49
+ },
50
+ "Chalkboard/blackboard": {
51
+ "accuracy": 0.7023255813953488,
52
+ "iou": 0.5171232876712328,
53
+ "support": 215
54
+ },
55
+ "Clutter": {
56
+ "accuracy": 0.39622641509433965,
57
+ "iou": 0.2692307692307692,
58
+ "support": 53
59
+ },
60
+ "Concrete": {
61
+ "accuracy": 0.496372430471584,
62
+ "iou": 0.27467380394780866,
63
+ "support": 1654
64
+ },
65
+ "Cork/corkboard": {
66
+ "accuracy": 0.4117647058823529,
67
+ "iou": 0.2441860465116279,
68
+ "support": 51
69
+ },
70
+ "Engineered stone": {
71
+ "accuracy": 0.2247191011235955,
72
+ "iou": 0.13986013986013987,
73
+ "support": 89
74
+ },
75
+ "Fabric/cloth": {
76
+ "accuracy": 0.7702929239456503,
77
+ "iou": 0.702627660858718,
78
+ "support": 22668
79
+ },
80
+ "Fiberglass wool": {
81
+ "accuracy": 0.55,
82
+ "iou": 0.3055555555555556,
83
+ "support": 20
84
+ },
85
+ "Fire": {
86
+ "accuracy": 0.78,
87
+ "iou": 0.65,
88
+ "support": 50
89
+ },
90
+ "Foliage": {
91
+ "accuracy": 0.9052897705173084,
92
+ "iou": 0.7798626235550343,
93
+ "support": 5142
94
+ },
95
+ "Food": {
96
+ "accuracy": 0.8737430167597765,
97
+ "iou": 0.6085603112840466,
98
+ "support": 895
99
+ },
100
+ "Fur": {
101
+ "accuracy": 0.8283062645011601,
102
+ "iou": 0.68,
103
+ "support": 431
104
+ },
105
+ "Gemstone/quartz": {
106
+ "accuracy": 0.72,
107
+ "iou": 0.2926829268292683,
108
+ "support": 50
109
+ },
110
+ "Glass": {
111
+ "accuracy": 0.760976692563818,
112
+ "iou": 0.6663686195233838,
113
+ "support": 22525
114
+ },
115
+ "Hair": {
116
+ "accuracy": 0.9763929618768329,
117
+ "iou": 0.9157040704070407,
118
+ "support": 6820
119
+ },
120
+ "I cannot tell": {
121
+ "accuracy": 0.0,
122
+ "iou": 0.0,
123
+ "support": 0
124
+ },
125
+ "Ice": {
126
+ "accuracy": 0.6363636363636364,
127
+ "iou": 0.44871794871794873,
128
+ "support": 55
129
+ },
130
+ "Leather": {
131
+ "accuracy": 0.7150890346766635,
132
+ "iou": 0.42721164613661816,
133
+ "support": 2134
134
+ },
135
+ "Liquid, non-water": {
136
+ "accuracy": 0.4444444444444444,
137
+ "iou": 0.3404255319148936,
138
+ "support": 36
139
+ },
140
+ "Metal": {
141
+ "accuracy": 0.7975601714474118,
142
+ "iou": 0.5638256545722943,
143
+ "support": 9099
144
+ },
145
+ "Mirror": {
146
+ "accuracy": 0.6700125470514429,
147
+ "iou": 0.3729050279329609,
148
+ "support": 797
149
+ },
150
+ "Not on list": {
151
+ "accuracy": 0.0,
152
+ "iou": 0.0,
153
+ "support": 0
154
+ },
155
+ "Paint/plaster/enamel": {
156
+ "accuracy": 0.5913390528267496,
157
+ "iou": 0.5186604189636164,
158
+ "support": 31821
159
+ },
160
+ "Paper": {
161
+ "accuracy": 0.8254024411816735,
162
+ "iou": 0.6823632641123135,
163
+ "support": 11306
164
+ },
165
+ "Pearl": {
166
+ "accuracy": 0.0,
167
+ "iou": 0.0,
168
+ "support": 1
169
+ },
170
+ "Photograph/painting": {
171
+ "accuracy": 0.7118034751348112,
172
+ "iou": 0.3496174220129488,
173
+ "support": 1669
174
+ },
175
+ "Plastic, clear": {
176
+ "accuracy": 0.6816199376947041,
177
+ "iou": 0.43830128205128205,
178
+ "support": 1605
179
+ },
180
+ "Plastic, non-clear": {
181
+ "accuracy": 0.6442321302193914,
182
+ "iou": 0.5032896555537126,
183
+ "support": 14130
184
+ },
185
+ "Rubber/latex": {
186
+ "accuracy": 0.6570363466915191,
187
+ "iou": 0.34474327628361856,
188
+ "support": 1073
189
+ },
190
+ "Sand": {
191
+ "accuracy": 0.42045454545454547,
192
+ "iou": 0.2890625,
193
+ "support": 88
194
+ },
195
+ "Skin/lips": {
196
+ "accuracy": 0.9697943988493104,
197
+ "iou": 0.9154952076677316,
198
+ "support": 11819
199
+ },
200
+ "Sky": {
201
+ "accuracy": 0.9127205199628597,
202
+ "iou": 0.6920098556846181,
203
+ "support": 2154
204
+ },
205
+ "Snow": {
206
+ "accuracy": 0.5963302752293578,
207
+ "iou": 0.40372670807453415,
208
+ "support": 109
209
+ },
210
+ "Soap": {
211
+ "accuracy": 0.0,
212
+ "iou": 0.0,
213
+ "support": 7
214
+ },
215
+ "Soil/mud": {
216
+ "accuracy": 0.624048706240487,
217
+ "iou": 0.4257528556593977,
218
+ "support": 657
219
+ },
220
+ "Sponge": {
221
+ "accuracy": 0.16666666666666666,
222
+ "iou": 0.125,
223
+ "support": 18
224
+ },
225
+ "Stone, natural": {
226
+ "accuracy": 0.6322686322686323,
227
+ "iou": 0.4419004006868918,
228
+ "support": 1221
229
+ },
230
+ "Stone, polished": {
231
+ "accuracy": 0.39580602883355176,
232
+ "iou": 0.252297410192147,
233
+ "support": 763
234
+ },
235
+ "Styrofoam": {
236
+ "accuracy": 0.16129032258064516,
237
+ "iou": 0.13513513513513514,
238
+ "support": 31
239
+ },
240
+ "Tile": {
241
+ "accuracy": 0.645155679248565,
242
+ "iou": 0.42412807318467693,
243
+ "support": 5749
244
+ },
245
+ "Wallpaper": {
246
+ "accuracy": 0.5654761904761905,
247
+ "iou": 0.3445149592021759,
248
+ "support": 672
249
+ },
250
+ "Water": {
251
+ "accuracy": 0.6651532349602725,
252
+ "iou": 0.5195035460992907,
253
+ "support": 881
254
+ },
255
+ "Wax": {
256
+ "accuracy": 0.8245614035087719,
257
+ "iou": 0.6861313868613139,
258
+ "support": 114
259
+ },
260
+ "Whiteboard": {
261
+ "accuracy": 0.6486486486486487,
262
+ "iou": 0.46652267818574517,
263
+ "support": 333
264
+ },
265
+ "Wicker": {
266
+ "accuracy": 0.7702479338842976,
267
+ "iou": 0.548235294117647,
268
+ "support": 605
269
+ },
270
+ "Wood": {
271
+ "accuracy": 0.7891884833844748,
272
+ "iou": 0.6155726434791465,
273
+ "support": 15317
274
+ },
275
+ "Wood, tree": {
276
+ "accuracy": 0.7431972789115646,
277
+ "iou": 0.4765539803707743,
278
+ "support": 588
279
+ },
280
+ "Bad polygon": {
281
+ "accuracy": 0.0,
282
+ "iou": 0.0,
283
+ "support": 0
284
+ },
285
+ "Multiple materials": {
286
+ "accuracy": 0.0,
287
+ "iou": 0.0,
288
+ "support": 0
289
+ },
290
+ "Asphalt": {
291
+ "accuracy": 0.5,
292
+ "iou": 0.2972972972972973,
293
+ "support": 198
294
+ }
295
+ }
296
+ }
DMS/dinov2_clip_gated/model.pth ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:045aaa0553e384bca097835a3689c8aedeef15118c1c6f69c5b38d1d04dfb20f
3
+ size 6910974
DMS/dinov2_clip_gated/model.safetensors ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:0715e31f97766d6da1185b402bf47e44a44db6f0bcb24f7e9cb743b30232200c
3
+ size 6904172
DMS/dinov2_clip_gated/split.json ADDED
The diff for this file is too large to render. See raw diff
 
DMS/dinov2_clip_mlp/README.md ADDED
@@ -0,0 +1,52 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # DINOv2-CLIP + Concat + MLP on Apple Dense Material Segmentation
2
+
3
+ A material-classification **fusion head** from SegObjectMaterial. It classifies the
4
+ material of a masked object from two frozen embeddings:
5
+
6
+ | | |
7
+ |---|---|
8
+ | vision | DINOv2 ViT-B/14 (CLS token, frozen) -> 768-d |
9
+ | language | CLIP ViT-L/14 text encoder over Qwen2.5-VL-7B captions (frozen) -> 768-d |
10
+ | head | Concat + MLP (`mlp`, defaults), 934,457 parameters |
11
+ | classes | 57 (Apple Dense Material Segmentation) |
12
+
13
+ **This repo holds only the head.** Features must come from the same encoders,
14
+ captioner and prompts as training (see the SegObjectMaterial repository); the
15
+ encoders are downloaded from their own model pages under their own licenses.
16
+
17
+ ## Evaluation
18
+
19
+ Held-out split recorded in `split.json` (source images never seen in training).
20
+ Single training run -- differences under ~0.5 mIoU points between heads are within
21
+ run-to-run noise.
22
+
23
+ | mIoU | mAcc | eval samples |
24
+ |---|---|---|
25
+ | 0.4744 | 0.6672 | 186,231 |
26
+
27
+ ## Training
28
+
29
+ ```json
30
+ {
31
+ "learning_rate": 5e-05,
32
+ "epochs": 50,
33
+ "batch_size": 32,
34
+ "weight_decay": 0.0001,
35
+ "lr_schedule": "constant",
36
+ "early_stopping_patience": 0,
37
+ "checkpoint": "best validation loss"
38
+ }
39
+ ```
40
+
41
+ ## Use
42
+
43
+ ```python
44
+ from utils.hub import load_head_from_hub # SegObjectMaterial repository
45
+ head, info = load_head_from_hub("s0um0r0y/SegObjectMaterial", "DMS/dinov2_clip_mlp")
46
+ logits = head(vision_features, language_features) # [B, 768], [B, 768]
47
+ ```
48
+
49
+ ## Integrity
50
+
51
+ - `model.safetensors` sha256 `b91f86016abb3734031738c48537d2ed499d7c0bbbaf90ea8a8fc4219f649c9e`
52
+ - source config `config/config_dinov2_clip_mlp.toml`, code commit `1a8130c922267fb0786a33e3854a7e00763cc38f+dirty`
DMS/dinov2_clip_mlp/config.toml ADDED
@@ -0,0 +1,68 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # DINOv2-CLIP + concat-MLP head: the ORIGINAL-PAPER fusion, retrained on the
2
+ # current grounded cache. The old MLP checkpoints (best_model.pth / _v2) were
3
+ # trained on a cache that no longer exists, with no held-out split recorded, so
4
+ # they cannot be evaluated fairly. Same cache as config_dinov2_clip.toml;
5
+ # own checkpoint, TensorBoard dir and W&B run, so nothing is overwritten.
6
+ # Baseline recipe (wd 1e-4, constant LR, 50 epochs) to match the other baseline rows.
7
+
8
+ # Apple DMS -- BASE pipeline: DINOv2 ViT-B/14 (768) + Qwen2.5-VL -> CLIP text (768)
9
+ #
10
+ # Pair this with:
11
+ # src/vision_stream.py + src/language_stream.py
12
+ # run_serialization.py -> train.py (the raw/original scripts)
13
+ #
14
+ # config/config.toml is the OTHER pipeline (DINOv3 ViT-L/16 1024 + SigLIP2),
15
+ # driven by run_serialization_latest_models.py -> train_latest_models.py.
16
+ # Mixing them raises the dimension-mismatch ValueError in the fusion head.
17
+
18
+ [data]
19
+ dataset_type = "apple_dms"
20
+ image_dir = "<local>/images"
21
+ mask_dir = "<local>/labels"
22
+ # Rebuilt automatically on first run; the index now stores one entry per
23
+ # CONNECTED COMPONENT, so any pre-existing labels.json must be removed first.
24
+ labels_file = "<local>/labels_instances.json"
25
+ # Fresh directory: features are now object-grounded (bbox-cropped vision,
26
+ # bbox-prompted captions), so the old tensor_cache_dir/ contents are stale.
27
+ tensor_cache_dir = "<local>/tensor_cache_dir_grounded"
28
+
29
+ # Connected-component filtering (measured on 400 real DMS masks):
30
+ # keeping every component gives 7.5x more samples than the old per-(image,class)
31
+ # scheme -- 2.45M samples / 47 GB / ~7.5x the VLM captioning time -- because 69%
32
+ # of components are under 0.1% of the frame and crop to a few pixels.
33
+ # A component is kept when area >= max(min_instance_area, min_instance_frac * frame).
34
+ min_instance_area = 1000 # absolute pixel floor
35
+ min_instance_frac = 0.001 # and at least 0.1% of the frame
36
+ max_instances_per_class = 0 # 0 = keep all; set e.g. 3 to cap the long tail
37
+
38
+
39
+ [model]
40
+ # fusion head: read by train_latest_models.py. Without this key it defaults to
41
+ # "gated" -- which is how best_model_dinov2_clip.pth / best_model_fmd.pth were trained.
42
+ fusion = "mlp"
43
+ vision_dim = 768 # DINOv2 ViT-B/14 CLS token
44
+ language_dim = 768 # CLIP ViT-L/14 text pooler_output
45
+ num_classes = 57
46
+
47
+ [training]
48
+ batch_size = 32
49
+
50
+ # Batch size for the OFFLINE SERIALIZATION pass, which is a completely different
51
+ # memory regime from training: it pushes full-resolution images through the 7B
52
+ # VLM, whereas [training].batch_size only moves cached 768-d vectors through a
53
+ # small MLP. Measured on the 23.6 GiB 4090 -- static weights 16.2 GiB, so only
54
+ # ~7.4 GiB is left: batch 8 peaks at 17.7 GiB, 16 at 19.2 GiB, and 32 OOMs.
55
+ # 8 leaves headroom for a labmate's job to coexist; raise to 16 on a free card.
56
+ serialization_batch_size = 8
57
+ learning_rate = 5e-5
58
+ epochs = 50
59
+ train_ratio = 0.8 # 80% for training
60
+ val_ratio = 0.2 # 20% for validation
61
+ tensorboard_log_dir = "<local>/dms_dinov2_clip_mlp"
62
+
63
+ [inference]
64
+ checkpoint_path = "<local>/best_model_dms_dinov2_clip_mlp.pth"
65
+
66
+ [logging]
67
+ wandb_project = "material-classification"
68
+ wandb_run_name = "dms-dinov2-clip-mlp"
DMS/dinov2_clip_mlp/head.json ADDED
@@ -0,0 +1,99 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "fusion": "mlp",
3
+ "head": "Concat + MLP",
4
+ "head_kwargs": {},
5
+ "vision_dim": 768,
6
+ "language_dim": 768,
7
+ "num_classes": 57,
8
+ "classes": [
9
+ "No label",
10
+ "Animal skin",
11
+ "Bone/teeth/horn",
12
+ "Brickwork",
13
+ "Cardboard",
14
+ "Carpet/rug",
15
+ "Ceiling tile",
16
+ "Ceramic",
17
+ "Chalkboard/blackboard",
18
+ "Clutter",
19
+ "Concrete",
20
+ "Cork/corkboard",
21
+ "Engineered stone",
22
+ "Fabric/cloth",
23
+ "Fiberglass wool",
24
+ "Fire",
25
+ "Foliage",
26
+ "Food",
27
+ "Fur",
28
+ "Gemstone/quartz",
29
+ "Glass",
30
+ "Hair",
31
+ "I cannot tell",
32
+ "Ice",
33
+ "Leather",
34
+ "Liquid, non-water",
35
+ "Metal",
36
+ "Mirror",
37
+ "Not on list",
38
+ "Paint/plaster/enamel",
39
+ "Paper",
40
+ "Pearl",
41
+ "Photograph/painting",
42
+ "Plastic, clear",
43
+ "Plastic, non-clear",
44
+ "Rubber/latex",
45
+ "Sand",
46
+ "Skin/lips",
47
+ "Sky",
48
+ "Snow",
49
+ "Soap",
50
+ "Soil/mud",
51
+ "Sponge",
52
+ "Stone, natural",
53
+ "Stone, polished",
54
+ "Styrofoam",
55
+ "Tile",
56
+ "Wallpaper",
57
+ "Water",
58
+ "Wax",
59
+ "Whiteboard",
60
+ "Wicker",
61
+ "Wood",
62
+ "Wood, tree",
63
+ "Bad polygon",
64
+ "Multiple materials",
65
+ "Asphalt"
66
+ ],
67
+ "dataset": "Apple Dense Material Segmentation",
68
+ "dataset_key": "DMS",
69
+ "encoders": {
70
+ "vision": "DINOv2 ViT-B/14 (CLS token, frozen)",
71
+ "language": "CLIP ViT-L/14 text encoder over Qwen2.5-VL-7B captions (frozen)",
72
+ "short": "DINOv2-CLIP",
73
+ "slug": "dinov2_clip"
74
+ },
75
+ "parameters": 934457,
76
+ "training": {
77
+ "learning_rate": 5e-05,
78
+ "epochs": 50,
79
+ "batch_size": 32,
80
+ "weight_decay": 0.0001,
81
+ "lr_schedule": "constant",
82
+ "early_stopping_patience": 0,
83
+ "checkpoint": "best validation loss"
84
+ },
85
+ "sha256": {
86
+ "safetensors": "b91f86016abb3734031738c48537d2ed499d7c0bbbaf90ea8a8fc4219f649c9e",
87
+ "pth": "0fe9af49a1f493b61a55aed60cef6a809458c6baeea9a5e8d2f15d3e2c4d0ad8"
88
+ },
89
+ "source": {
90
+ "config": "config/config_dinov2_clip_mlp.toml",
91
+ "git_commit": "1a8130c922267fb0786a33e3854a7e00763cc38f+dirty",
92
+ "checkpoint_mtime": "2026-10-09T00:26:13"
93
+ },
94
+ "metrics": {
95
+ "mIoU": 0.4743560437589232,
96
+ "mAcc": 0.6672396382567987,
97
+ "eval_samples": 186231
98
+ }
99
+ }
DMS/dinov2_clip_mlp/metrics.json ADDED
@@ -0,0 +1,296 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "dataset": "DMS",
3
+ "config": "config/config_dinov2_clip_mlp.toml",
4
+ "checkpoint": "<local>/best_model_dms_dinov2_clip_mlp.pth",
5
+ "fusion_type": "mlp",
6
+ "num_eval_samples": 186231,
7
+ "mIoU": 0.4743560437589232,
8
+ "mAcc": 0.6672396382567987,
9
+ "per_class": {
10
+ "No label": {
11
+ "accuracy": 0.0,
12
+ "iou": 0.0,
13
+ "support": 0
14
+ },
15
+ "Animal skin": {
16
+ "accuracy": 0.6228070175438597,
17
+ "iou": 0.47019867549668876,
18
+ "support": 114
19
+ },
20
+ "Bone/teeth/horn": {
21
+ "accuracy": 0.7954545454545454,
22
+ "iou": 0.625,
23
+ "support": 44
24
+ },
25
+ "Brickwork": {
26
+ "accuracy": 0.7587131367292225,
27
+ "iou": 0.5322884012539185,
28
+ "support": 1119
29
+ },
30
+ "Cardboard": {
31
+ "accuracy": 0.7223851417399805,
32
+ "iou": 0.4737179487179487,
33
+ "support": 1023
34
+ },
35
+ "Carpet/rug": {
36
+ "accuracy": 0.8028368794326242,
37
+ "iou": 0.4522314804246091,
38
+ "support": 4935
39
+ },
40
+ "Ceiling tile": {
41
+ "accuracy": 0.7937625754527163,
42
+ "iou": 0.499683343888537,
43
+ "support": 994
44
+ },
45
+ "Ceramic": {
46
+ "accuracy": 0.8217562254259502,
47
+ "iou": 0.6011505273250239,
48
+ "support": 2289
49
+ },
50
+ "Chalkboard/blackboard": {
51
+ "accuracy": 0.7209302325581395,
52
+ "iou": 0.49363057324840764,
53
+ "support": 215
54
+ },
55
+ "Clutter": {
56
+ "accuracy": 0.4528301886792453,
57
+ "iou": 0.32432432432432434,
58
+ "support": 53
59
+ },
60
+ "Concrete": {
61
+ "accuracy": 0.56590084643289,
62
+ "iou": 0.2826940501359106,
63
+ "support": 1654
64
+ },
65
+ "Cork/corkboard": {
66
+ "accuracy": 0.35294117647058826,
67
+ "iou": 0.21951219512195122,
68
+ "support": 51
69
+ },
70
+ "Engineered stone": {
71
+ "accuracy": 0.21348314606741572,
72
+ "iou": 0.1484375,
73
+ "support": 89
74
+ },
75
+ "Fabric/cloth": {
76
+ "accuracy": 0.765528498323628,
77
+ "iou": 0.700876448968052,
78
+ "support": 22668
79
+ },
80
+ "Fiberglass wool": {
81
+ "accuracy": 0.55,
82
+ "iou": 0.2558139534883721,
83
+ "support": 20
84
+ },
85
+ "Fire": {
86
+ "accuracy": 0.82,
87
+ "iou": 0.6307692307692307,
88
+ "support": 50
89
+ },
90
+ "Foliage": {
91
+ "accuracy": 0.9142357059509918,
92
+ "iou": 0.7736998025016458,
93
+ "support": 5142
94
+ },
95
+ "Food": {
96
+ "accuracy": 0.8737430167597765,
97
+ "iou": 0.6201427438540841,
98
+ "support": 895
99
+ },
100
+ "Fur": {
101
+ "accuracy": 0.8213457076566125,
102
+ "iou": 0.6941176470588235,
103
+ "support": 431
104
+ },
105
+ "Gemstone/quartz": {
106
+ "accuracy": 0.64,
107
+ "iou": 0.24806201550387597,
108
+ "support": 50
109
+ },
110
+ "Glass": {
111
+ "accuracy": 0.7659045504994451,
112
+ "iou": 0.667672897557955,
113
+ "support": 22525
114
+ },
115
+ "Hair": {
116
+ "accuracy": 0.9778592375366569,
117
+ "iou": 0.9158198297171107,
118
+ "support": 6820
119
+ },
120
+ "I cannot tell": {
121
+ "accuracy": 0.0,
122
+ "iou": 0.0,
123
+ "support": 0
124
+ },
125
+ "Ice": {
126
+ "accuracy": 0.6545454545454545,
127
+ "iou": 0.4931506849315068,
128
+ "support": 55
129
+ },
130
+ "Leather": {
131
+ "accuracy": 0.7146204311152765,
132
+ "iou": 0.43348493462194426,
133
+ "support": 2134
134
+ },
135
+ "Liquid, non-water": {
136
+ "accuracy": 0.5833333333333334,
137
+ "iou": 0.42,
138
+ "support": 36
139
+ },
140
+ "Metal": {
141
+ "accuracy": 0.8061325420375866,
142
+ "iou": 0.5545055941941337,
143
+ "support": 9099
144
+ },
145
+ "Mirror": {
146
+ "accuracy": 0.6750313676286073,
147
+ "iou": 0.38156028368794326,
148
+ "support": 797
149
+ },
150
+ "Not on list": {
151
+ "accuracy": 0.0,
152
+ "iou": 0.0,
153
+ "support": 0
154
+ },
155
+ "Paint/plaster/enamel": {
156
+ "accuracy": 0.5959586436629899,
157
+ "iou": 0.5222228341686402,
158
+ "support": 31821
159
+ },
160
+ "Paper": {
161
+ "accuracy": 0.8380505926056961,
162
+ "iou": 0.6929715497696189,
163
+ "support": 11306
164
+ },
165
+ "Pearl": {
166
+ "accuracy": 1.0,
167
+ "iou": 0.5,
168
+ "support": 1
169
+ },
170
+ "Photograph/painting": {
171
+ "accuracy": 0.6674655482324745,
172
+ "iou": 0.36369572314724125,
173
+ "support": 1669
174
+ },
175
+ "Plastic, clear": {
176
+ "accuracy": 0.6990654205607477,
177
+ "iou": 0.42275810097965333,
178
+ "support": 1605
179
+ },
180
+ "Plastic, non-clear": {
181
+ "accuracy": 0.6428167020523708,
182
+ "iou": 0.5052286127489154,
183
+ "support": 14130
184
+ },
185
+ "Rubber/latex": {
186
+ "accuracy": 0.6365330848089469,
187
+ "iou": 0.3490035769034236,
188
+ "support": 1073
189
+ },
190
+ "Sand": {
191
+ "accuracy": 0.4318181818181818,
192
+ "iou": 0.2733812949640288,
193
+ "support": 88
194
+ },
195
+ "Skin/lips": {
196
+ "accuracy": 0.9684406464167865,
197
+ "iou": 0.9211331079993562,
198
+ "support": 11819
199
+ },
200
+ "Sky": {
201
+ "accuracy": 0.9103992571959145,
202
+ "iou": 0.675973802137194,
203
+ "support": 2154
204
+ },
205
+ "Snow": {
206
+ "accuracy": 0.6055045871559633,
207
+ "iou": 0.4074074074074074,
208
+ "support": 109
209
+ },
210
+ "Soap": {
211
+ "accuracy": 0.2857142857142857,
212
+ "iou": 0.2857142857142857,
213
+ "support": 7
214
+ },
215
+ "Soil/mud": {
216
+ "accuracy": 0.6529680365296804,
217
+ "iou": 0.41690962099125367,
218
+ "support": 657
219
+ },
220
+ "Sponge": {
221
+ "accuracy": 0.2777777777777778,
222
+ "iou": 0.17857142857142858,
223
+ "support": 18
224
+ },
225
+ "Stone, natural": {
226
+ "accuracy": 0.5995085995085995,
227
+ "iou": 0.4566437928883344,
228
+ "support": 1221
229
+ },
230
+ "Stone, polished": {
231
+ "accuracy": 0.38794233289646135,
232
+ "iou": 0.26690712353471596,
233
+ "support": 763
234
+ },
235
+ "Styrofoam": {
236
+ "accuracy": 0.16129032258064516,
237
+ "iou": 0.1388888888888889,
238
+ "support": 31
239
+ },
240
+ "Tile": {
241
+ "accuracy": 0.6155853191859454,
242
+ "iou": 0.4333292518672707,
243
+ "support": 5749
244
+ },
245
+ "Wallpaper": {
246
+ "accuracy": 0.5818452380952381,
247
+ "iou": 0.3010007698229407,
248
+ "support": 672
249
+ },
250
+ "Water": {
251
+ "accuracy": 0.6867196367763905,
252
+ "iou": 0.4954954954954955,
253
+ "support": 881
254
+ },
255
+ "Wax": {
256
+ "accuracy": 0.8421052631578947,
257
+ "iou": 0.7007299270072993,
258
+ "support": 114
259
+ },
260
+ "Whiteboard": {
261
+ "accuracy": 0.6576576576576577,
262
+ "iou": 0.4524793388429752,
263
+ "support": 333
264
+ },
265
+ "Wicker": {
266
+ "accuracy": 0.7735537190082644,
267
+ "iou": 0.572827417380661,
268
+ "support": 605
269
+ },
270
+ "Wood": {
271
+ "accuracy": 0.7940197166546974,
272
+ "iou": 0.6218109310291937,
273
+ "support": 15317
274
+ },
275
+ "Wood, tree": {
276
+ "accuracy": 0.7329931972789115,
277
+ "iou": 0.5149342891278376,
278
+ "support": 588
279
+ },
280
+ "Bad polygon": {
281
+ "accuracy": 0.0,
282
+ "iou": 0.0,
283
+ "support": 0
284
+ },
285
+ "Multiple materials": {
286
+ "accuracy": 0.0,
287
+ "iou": 0.0,
288
+ "support": 0
289
+ },
290
+ "Asphalt": {
291
+ "accuracy": 0.46464646464646464,
292
+ "iou": 0.2839506172839506,
293
+ "support": 198
294
+ }
295
+ }
296
+ }
DMS/dinov2_clip_mlp/model.pth ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:0fe9af49a1f493b61a55aed60cef6a809458c6baeea9a5e8d2f15d3e2c4d0ad8
3
+ size 3750066
DMS/dinov2_clip_mlp/model.safetensors ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:b91f86016abb3734031738c48537d2ed499d7c0bbbaf90ea8a8fc4219f649c9e
3
+ size 3745260
DMS/dinov2_clip_mlp/split.json ADDED
The diff for this file is too large to render. See raw diff
 
DMS/dinov3_siglip2_gated/README.md ADDED
@@ -0,0 +1,52 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # DINOv3-SigLIP2 + Gated Multimodal Unit on Apple Dense Material Segmentation
2
+
3
+ A material-classification **fusion head** from SegObjectMaterial. It classifies the
4
+ material of a masked object from two frozen embeddings:
5
+
6
+ | | |
7
+ |---|---|
8
+ | vision | DINOv3 ViT-L/16 (CLS token, frozen) -> 1024-d |
9
+ | language | SigLIP2 base text encoder over Qwen3-VL-8B captions (frozen) -> 768-d |
10
+ | head | Gated Multimodal Unit (`gated`, defaults), 1,985,081 parameters |
11
+ | classes | 57 (Apple Dense Material Segmentation) |
12
+
13
+ **This repo holds only the head.** Features must come from the same encoders,
14
+ captioner and prompts as training (see the SegObjectMaterial repository); the
15
+ encoders are downloaded from their own model pages under their own licenses.
16
+
17
+ ## Evaluation
18
+
19
+ Held-out split recorded in `split.json` (source images never seen in training).
20
+ Single training run -- differences under ~0.5 mIoU points between heads are within
21
+ run-to-run noise.
22
+
23
+ | mIoU | mAcc | eval samples |
24
+ |---|---|---|
25
+ | 0.4630 | 0.6386 | 186,231 |
26
+
27
+ ## Training
28
+
29
+ ```json
30
+ {
31
+ "learning_rate": 5e-05,
32
+ "epochs": 50,
33
+ "batch_size": 32,
34
+ "weight_decay": 0.0001,
35
+ "lr_schedule": "constant",
36
+ "early_stopping_patience": 0,
37
+ "checkpoint": "best validation loss"
38
+ }
39
+ ```
40
+
41
+ ## Use
42
+
43
+ ```python
44
+ from utils.hub import load_head_from_hub # SegObjectMaterial repository
45
+ head, info = load_head_from_hub("s0um0r0y/SegObjectMaterial", "DMS/dinov3_siglip2_gated")
46
+ logits = head(vision_features, language_features) # [B, 1024], [B, 768]
47
+ ```
48
+
49
+ ## Integrity
50
+
51
+ - `model.safetensors` sha256 `8c71607a87521793b66f1fc13ba984fe2b6954774b0caad559ae94d72de33b12`
52
+ - source config `config/config.toml`, code commit `1a8130c922267fb0786a33e3854a7e00763cc38f+dirty`
DMS/dinov3_siglip2_gated/config.toml ADDED
@@ -0,0 +1,59 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Apple DMS -- LATEST-MODELS pipeline: DINOv3 ViT-L/16 (1024) + Qwen3-VL -> SigLIP2 text (768)
2
+ #
3
+ # Pair this with:
4
+ # src/vision_stream_latest_models.py + src/language_stream_latest_models.py
5
+ # run_serialization_latest_models.py -> train_latest_models.py
6
+ #
7
+ # For the base DINOv2/CLIP pipeline (run_serialization.py -> train.py) use
8
+ # config/config_dinov2_clip.toml instead -- its vision_dim is 768, not 1024.
9
+
10
+ [data]
11
+ dataset_type = "apple_dms"
12
+ image_dir = "<local>/images"
13
+ mask_dir = "<local>/labels"
14
+ # Rebuilt automatically on first run; the index now stores one entry per
15
+ # CONNECTED COMPONENT, so any pre-existing labels.json must be removed first.
16
+ labels_file = "<local>/labels_instances.json"
17
+ # Separate cache: DINOv3 features are 1024-d and must not mix with the
18
+ # 768-d DINOv2 cache written by run_serialization.py.
19
+ tensor_cache_dir = "<local>/tensor_cache_dir_latest_models"
20
+
21
+ # Connected-component filtering (measured on 400 real DMS masks):
22
+ # keeping every component gives 7.5x more samples than the old per-(image,class)
23
+ # scheme -- 2.45M samples / 47 GB / ~7.5x the VLM captioning time -- because 69%
24
+ # of components are under 0.1% of the frame and crop to a few pixels.
25
+ # A component is kept when area >= max(min_instance_area, min_instance_frac * frame).
26
+ min_instance_area = 1000 # absolute pixel floor
27
+ min_instance_frac = 0.001 # and at least 0.1% of the frame
28
+ max_instances_per_class = 0 # 0 = keep all; set e.g. 3 to cap the long tail
29
+
30
+
31
+ [model]
32
+ # fusion head: "gated" (GMU) or "mlp" (concat+MLP). Read by train_latest_models.py; a contradicting --fusion flag is an error, so checkpoint_path can't hold the wrong head.
33
+ fusion = "gated"
34
+ vision_dim = 1024 # DINOv3 ViT-L/16 CLS token
35
+ language_dim = 768 # SigLIP2 base text embedding
36
+ num_classes = 57
37
+
38
+ [training]
39
+ batch_size = 32
40
+
41
+ # Batch size for the OFFLINE SERIALIZATION pass, which is a completely different
42
+ # memory regime from training: it pushes full-resolution images through the 7B
43
+ # VLM, whereas [training].batch_size only moves cached 768-d vectors through a
44
+ # small MLP. Measured on the 23.6 GiB 4090 -- static weights 16.2 GiB, so only
45
+ # ~7.4 GiB is left: batch 8 peaks at 17.7 GiB, 16 at 19.2 GiB, and 32 OOMs.
46
+ # 8 leaves headroom for a labmate's job to coexist; raise to 16 on a free card.
47
+ serialization_batch_size = 8
48
+ learning_rate = 5e-5
49
+ epochs = 50
50
+ train_ratio = 0.8 # 80% for training
51
+ val_ratio = 0.2 # 20% for validation
52
+ tensorboard_log_dir = "<local>/dms_dinov3_siglip2"
53
+
54
+ [inference]
55
+ checkpoint_path = "<local>/best_model_SigLIP_DINOv3.pth"
56
+
57
+ [logging]
58
+ wandb_project = "material-classification"
59
+ wandb_run_name = "dinov3-siglip2"
DMS/dinov3_siglip2_gated/head.json ADDED
@@ -0,0 +1,99 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "fusion": "gated",
3
+ "head": "Gated Multimodal Unit",
4
+ "head_kwargs": {},
5
+ "vision_dim": 1024,
6
+ "language_dim": 768,
7
+ "num_classes": 57,
8
+ "classes": [
9
+ "No label",
10
+ "Animal skin",
11
+ "Bone/teeth/horn",
12
+ "Brickwork",
13
+ "Cardboard",
14
+ "Carpet/rug",
15
+ "Ceiling tile",
16
+ "Ceramic",
17
+ "Chalkboard/blackboard",
18
+ "Clutter",
19
+ "Concrete",
20
+ "Cork/corkboard",
21
+ "Engineered stone",
22
+ "Fabric/cloth",
23
+ "Fiberglass wool",
24
+ "Fire",
25
+ "Foliage",
26
+ "Food",
27
+ "Fur",
28
+ "Gemstone/quartz",
29
+ "Glass",
30
+ "Hair",
31
+ "I cannot tell",
32
+ "Ice",
33
+ "Leather",
34
+ "Liquid, non-water",
35
+ "Metal",
36
+ "Mirror",
37
+ "Not on list",
38
+ "Paint/plaster/enamel",
39
+ "Paper",
40
+ "Pearl",
41
+ "Photograph/painting",
42
+ "Plastic, clear",
43
+ "Plastic, non-clear",
44
+ "Rubber/latex",
45
+ "Sand",
46
+ "Skin/lips",
47
+ "Sky",
48
+ "Snow",
49
+ "Soap",
50
+ "Soil/mud",
51
+ "Sponge",
52
+ "Stone, natural",
53
+ "Stone, polished",
54
+ "Styrofoam",
55
+ "Tile",
56
+ "Wallpaper",
57
+ "Water",
58
+ "Wax",
59
+ "Whiteboard",
60
+ "Wicker",
61
+ "Wood",
62
+ "Wood, tree",
63
+ "Bad polygon",
64
+ "Multiple materials",
65
+ "Asphalt"
66
+ ],
67
+ "dataset": "Apple Dense Material Segmentation",
68
+ "dataset_key": "DMS",
69
+ "encoders": {
70
+ "vision": "DINOv3 ViT-L/16 (CLS token, frozen)",
71
+ "language": "SigLIP2 base text encoder over Qwen3-VL-8B captions (frozen)",
72
+ "short": "DINOv3-SigLIP2",
73
+ "slug": "dinov3_siglip2"
74
+ },
75
+ "parameters": 1985081,
76
+ "training": {
77
+ "learning_rate": 5e-05,
78
+ "epochs": 50,
79
+ "batch_size": 32,
80
+ "weight_decay": 0.0001,
81
+ "lr_schedule": "constant",
82
+ "early_stopping_patience": 0,
83
+ "checkpoint": "best validation loss"
84
+ },
85
+ "sha256": {
86
+ "safetensors": "8c71607a87521793b66f1fc13ba984fe2b6954774b0caad559ae94d72de33b12",
87
+ "pth": "5751d9a8428036b671c11a9fc440931ad0888d497feb7b2a0f93271b4f18b293"
88
+ },
89
+ "source": {
90
+ "config": "config/config.toml",
91
+ "git_commit": "1a8130c922267fb0786a33e3854a7e00763cc38f+dirty",
92
+ "checkpoint_mtime": "2026-09-27T16:03:35"
93
+ },
94
+ "metrics": {
95
+ "mIoU": 0.4630038334240617,
96
+ "mAcc": 0.638554054441271,
97
+ "eval_samples": 186231
98
+ }
99
+ }
DMS/dinov3_siglip2_gated/metrics.json ADDED
@@ -0,0 +1,296 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "dataset": "DMS",
3
+ "checkpoint": "<local>/best_model_SigLIP_DINOv3.pth",
4
+ "fusion_type": "gated",
5
+ "num_eval_samples": 186231,
6
+ "mIoU": 0.4630038334240617,
7
+ "mAcc": 0.638554054441271,
8
+ "per_class": {
9
+ "No label": {
10
+ "accuracy": 0.0,
11
+ "iou": 0.0,
12
+ "support": 0
13
+ },
14
+ "Animal skin": {
15
+ "accuracy": 0.6052631578947368,
16
+ "iou": 0.4107142857142857,
17
+ "support": 114
18
+ },
19
+ "Bone/teeth/horn": {
20
+ "accuracy": 0.7272727272727273,
21
+ "iou": 0.64,
22
+ "support": 44
23
+ },
24
+ "Brickwork": {
25
+ "accuracy": 0.7667560321715817,
26
+ "iou": 0.516245487364621,
27
+ "support": 1119
28
+ },
29
+ "Cardboard": {
30
+ "accuracy": 0.7526881720430108,
31
+ "iou": 0.48951048951048953,
32
+ "support": 1023
33
+ },
34
+ "Carpet/rug": {
35
+ "accuracy": 0.7797365754812563,
36
+ "iou": 0.49056603773584906,
37
+ "support": 4935
38
+ },
39
+ "Ceiling tile": {
40
+ "accuracy": 0.772635814889336,
41
+ "iou": 0.5140562248995983,
42
+ "support": 994
43
+ },
44
+ "Ceramic": {
45
+ "accuracy": 0.8396679772826562,
46
+ "iou": 0.5924784217016029,
47
+ "support": 2289
48
+ },
49
+ "Chalkboard/blackboard": {
50
+ "accuracy": 0.7534883720930232,
51
+ "iou": 0.5472972972972973,
52
+ "support": 215
53
+ },
54
+ "Clutter": {
55
+ "accuracy": 0.5094339622641509,
56
+ "iou": 0.40298507462686567,
57
+ "support": 53
58
+ },
59
+ "Concrete": {
60
+ "accuracy": 0.5126964933494559,
61
+ "iou": 0.2870683818551117,
62
+ "support": 1654
63
+ },
64
+ "Cork/corkboard": {
65
+ "accuracy": 0.3333333333333333,
66
+ "iou": 0.2125,
67
+ "support": 51
68
+ },
69
+ "Engineered stone": {
70
+ "accuracy": 0.23595505617977527,
71
+ "iou": 0.13725490196078433,
72
+ "support": 89
73
+ },
74
+ "Fabric/cloth": {
75
+ "accuracy": 0.7962766896064938,
76
+ "iou": 0.7181221404416153,
77
+ "support": 22668
78
+ },
79
+ "Fiberglass wool": {
80
+ "accuracy": 0.25,
81
+ "iou": 0.1724137931034483,
82
+ "support": 20
83
+ },
84
+ "Fire": {
85
+ "accuracy": 0.86,
86
+ "iou": 0.6142857142857143,
87
+ "support": 50
88
+ },
89
+ "Foliage": {
90
+ "accuracy": 0.9225982108129133,
91
+ "iou": 0.7788540469545231,
92
+ "support": 5142
93
+ },
94
+ "Food": {
95
+ "accuracy": 0.870391061452514,
96
+ "iou": 0.6411522633744856,
97
+ "support": 895
98
+ },
99
+ "Fur": {
100
+ "accuracy": 0.8190255220417634,
101
+ "iou": 0.6948818897637795,
102
+ "support": 431
103
+ },
104
+ "Gemstone/quartz": {
105
+ "accuracy": 0.66,
106
+ "iou": 0.2578125,
107
+ "support": 50
108
+ },
109
+ "Glass": {
110
+ "accuracy": 0.7757602663706992,
111
+ "iou": 0.6716119609501114,
112
+ "support": 22525
113
+ },
114
+ "Hair": {
115
+ "accuracy": 0.9737536656891496,
116
+ "iou": 0.9276435256320715,
117
+ "support": 6820
118
+ },
119
+ "I cannot tell": {
120
+ "accuracy": 0.0,
121
+ "iou": 0.0,
122
+ "support": 0
123
+ },
124
+ "Ice": {
125
+ "accuracy": 0.45454545454545453,
126
+ "iou": 0.3787878787878788,
127
+ "support": 55
128
+ },
129
+ "Leather": {
130
+ "accuracy": 0.7155576382380506,
131
+ "iou": 0.44094715564539416,
132
+ "support": 2134
133
+ },
134
+ "Liquid, non-water": {
135
+ "accuracy": 0.5,
136
+ "iou": 0.36,
137
+ "support": 36
138
+ },
139
+ "Metal": {
140
+ "accuracy": 0.8040444004835696,
141
+ "iou": 0.5635061233921281,
142
+ "support": 9099
143
+ },
144
+ "Mirror": {
145
+ "accuracy": 0.685069008782936,
146
+ "iou": 0.3976693372177713,
147
+ "support": 797
148
+ },
149
+ "Not on list": {
150
+ "accuracy": 0.0,
151
+ "iou": 0.0,
152
+ "support": 0
153
+ },
154
+ "Paint/plaster/enamel": {
155
+ "accuracy": 0.6256245875365325,
156
+ "iou": 0.5428516892536743,
157
+ "support": 31821
158
+ },
159
+ "Paper": {
160
+ "accuracy": 0.8281443481337343,
161
+ "iou": 0.6981582283200358,
162
+ "support": 11306
163
+ },
164
+ "Pearl": {
165
+ "accuracy": 0.0,
166
+ "iou": 0.0,
167
+ "support": 1
168
+ },
169
+ "Photograph/painting": {
170
+ "accuracy": 0.7112043139604554,
171
+ "iou": 0.3851395197923426,
172
+ "support": 1669
173
+ },
174
+ "Plastic, clear": {
175
+ "accuracy": 0.6785046728971963,
176
+ "iou": 0.4403558431055398,
177
+ "support": 1605
178
+ },
179
+ "Plastic, non-clear": {
180
+ "accuracy": 0.6440905874026893,
181
+ "iou": 0.5220558710491596,
182
+ "support": 14130
183
+ },
184
+ "Rubber/latex": {
185
+ "accuracy": 0.5712954333643989,
186
+ "iou": 0.3383002207505519,
187
+ "support": 1073
188
+ },
189
+ "Sand": {
190
+ "accuracy": 0.32954545454545453,
191
+ "iou": 0.25,
192
+ "support": 88
193
+ },
194
+ "Skin/lips": {
195
+ "accuracy": 0.975886284795668,
196
+ "iou": 0.9366574630501868,
197
+ "support": 11819
198
+ },
199
+ "Sky": {
200
+ "accuracy": 0.9308263695450325,
201
+ "iou": 0.6852358168147642,
202
+ "support": 2154
203
+ },
204
+ "Snow": {
205
+ "accuracy": 0.7064220183486238,
206
+ "iou": 0.5,
207
+ "support": 109
208
+ },
209
+ "Soap": {
210
+ "accuracy": 0.14285714285714285,
211
+ "iou": 0.14285714285714285,
212
+ "support": 7
213
+ },
214
+ "Soil/mud": {
215
+ "accuracy": 0.6636225266362252,
216
+ "iou": 0.41366223908918404,
217
+ "support": 657
218
+ },
219
+ "Sponge": {
220
+ "accuracy": 0.2777777777777778,
221
+ "iou": 0.19230769230769232,
222
+ "support": 18
223
+ },
224
+ "Stone, natural": {
225
+ "accuracy": 0.6101556101556102,
226
+ "iou": 0.4482551143200963,
227
+ "support": 1221
228
+ },
229
+ "Stone, polished": {
230
+ "accuracy": 0.41153342070773263,
231
+ "iou": 0.26364399664147775,
232
+ "support": 763
233
+ },
234
+ "Styrofoam": {
235
+ "accuracy": 0.16129032258064516,
236
+ "iou": 0.11627906976744186,
237
+ "support": 31
238
+ },
239
+ "Tile": {
240
+ "accuracy": 0.6489824317272569,
241
+ "iou": 0.4471476510067114,
242
+ "support": 5749
243
+ },
244
+ "Wallpaper": {
245
+ "accuracy": 0.59375,
246
+ "iou": 0.328125,
247
+ "support": 672
248
+ },
249
+ "Water": {
250
+ "accuracy": 0.6821793416572077,
251
+ "iou": 0.5207972270363952,
252
+ "support": 881
253
+ },
254
+ "Wax": {
255
+ "accuracy": 0.868421052631579,
256
+ "iou": 0.5789473684210527,
257
+ "support": 114
258
+ },
259
+ "Whiteboard": {
260
+ "accuracy": 0.6606606606606606,
261
+ "iou": 0.46218487394957986,
262
+ "support": 333
263
+ },
264
+ "Wicker": {
265
+ "accuracy": 0.7851239669421488,
266
+ "iou": 0.5771567436208992,
267
+ "support": 605
268
+ },
269
+ "Wood": {
270
+ "accuracy": 0.7963700463537247,
271
+ "iou": 0.6331689592525305,
272
+ "support": 15317
273
+ },
274
+ "Wood, tree": {
275
+ "accuracy": 0.7346938775510204,
276
+ "iou": 0.48758465011286684,
277
+ "support": 588
278
+ },
279
+ "Bad polygon": {
280
+ "accuracy": 0.0,
281
+ "iou": 0.0,
282
+ "support": 0
283
+ },
284
+ "Multiple materials": {
285
+ "accuracy": 0.0,
286
+ "iou": 0.0,
287
+ "support": 0
288
+ },
289
+ "Asphalt": {
290
+ "accuracy": 0.4898989898989899,
291
+ "iou": 0.3069620253164557,
292
+ "support": 198
293
+ }
294
+ },
295
+ "config": "config/config.toml"
296
+ }
DMS/dinov3_siglip2_gated/model.pth ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:5751d9a8428036b671c11a9fc440931ad0888d497feb7b2a0f93271b4f18b293
3
+ size 7959608
DMS/dinov3_siglip2_gated/model.safetensors ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:8c71607a87521793b66f1fc13ba984fe2b6954774b0caad559ae94d72de33b12
3
+ size 7952748
DMS/dinov3_siglip2_gated/split.json ADDED
The diff for this file is too large to render. See raw diff
 
DMS/dinov3_siglip2_gated_reg/README.md ADDED
@@ -0,0 +1,52 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # DINOv3-SigLIP2 + Gated Multimodal Unit on Apple Dense Material Segmentation
2
+
3
+ A material-classification **fusion head** from SegObjectMaterial. It classifies the
4
+ material of a masked object from two frozen embeddings:
5
+
6
+ | | |
7
+ |---|---|
8
+ | vision | DINOv3 ViT-L/16 (CLS token, frozen) -> 1024-d |
9
+ | language | SigLIP2 base text encoder over Qwen3-VL-8B captions (frozen) -> 768-d |
10
+ | head | Gated Multimodal Unit (`gated`, defaults), 1,985,081 parameters |
11
+ | classes | 57 (Apple Dense Material Segmentation) |
12
+
13
+ **This repo holds only the head.** Features must come from the same encoders,
14
+ captioner and prompts as training (see the SegObjectMaterial repository); the
15
+ encoders are downloaded from their own model pages under their own licenses.
16
+
17
+ ## Evaluation
18
+
19
+ Held-out split recorded in `split.json` (source images never seen in training).
20
+ Single training run -- differences under ~0.5 mIoU points between heads are within
21
+ run-to-run noise.
22
+
23
+ | mIoU | mAcc | eval samples |
24
+ |---|---|---|
25
+ | 0.4606 | 0.6403 | 186,231 |
26
+
27
+ ## Training
28
+
29
+ ```json
30
+ {
31
+ "learning_rate": 5e-05,
32
+ "epochs": 50,
33
+ "batch_size": 32,
34
+ "weight_decay": 0.01,
35
+ "lr_schedule": "cosine",
36
+ "early_stopping_patience": 8,
37
+ "checkpoint": "best validation loss"
38
+ }
39
+ ```
40
+
41
+ ## Use
42
+
43
+ ```python
44
+ from utils.hub import load_head_from_hub # SegObjectMaterial repository
45
+ head, info = load_head_from_hub("s0um0r0y/SegObjectMaterial", "DMS/dinov3_siglip2_gated_reg")
46
+ logits = head(vision_features, language_features) # [B, 1024], [B, 768]
47
+ ```
48
+
49
+ ## Integrity
50
+
51
+ - `model.safetensors` sha256 `651edac500aacfb32bec53e14e7b2da4c660eb67acdaa350a8a700f5cf060453`
52
+ - source config `config/config_latest_models_gated_reg.toml`, code commit `1a8130c922267fb0786a33e3854a7e00763cc38f+dirty`
DMS/dinov3_siglip2_gated_reg/config.toml ADDED
@@ -0,0 +1,72 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # REGULARISED GATED run: config.toml (gated head) trained with the SAME recipe
2
+ # as config_latest_models_lmf_reg.toml -- weight decay 1e-2, cosine LR, early
3
+ # stopping. Without this control, an LMF gain could be the recipe, not the head.
4
+ # (No modality dropout: only the LMF head implements it.) Own checkpoint.
5
+
6
+ # Apple DMS -- LATEST-MODELS pipeline: DINOv3 ViT-L/16 (1024) + Qwen3-VL -> SigLIP2 text (768)
7
+ #
8
+ # Pair this with:
9
+ # src/vision_stream_latest_models.py + src/language_stream_latest_models.py
10
+ # run_serialization_latest_models.py -> train_latest_models.py
11
+ #
12
+ # For the base DINOv2/CLIP pipeline (run_serialization.py -> train.py) use
13
+ # config/config_dinov2_clip.toml instead -- its vision_dim is 768, not 1024.
14
+
15
+ [data]
16
+ dataset_type = "apple_dms"
17
+ image_dir = "<local>/images"
18
+ mask_dir = "<local>/labels"
19
+ # Rebuilt automatically on first run; the index now stores one entry per
20
+ # CONNECTED COMPONENT, so any pre-existing labels.json must be removed first.
21
+ labels_file = "<local>/labels_instances.json"
22
+ # Separate cache: DINOv3 features are 1024-d and must not mix with the
23
+ # 768-d DINOv2 cache written by run_serialization.py.
24
+ tensor_cache_dir = "<local>/tensor_cache_dir_latest_models"
25
+
26
+ # Connected-component filtering (measured on 400 real DMS masks):
27
+ # keeping every component gives 7.5x more samples than the old per-(image,class)
28
+ # scheme -- 2.45M samples / 47 GB / ~7.5x the VLM captioning time -- because 69%
29
+ # of components are under 0.1% of the frame and crop to a few pixels.
30
+ # A component is kept when area >= max(min_instance_area, min_instance_frac * frame).
31
+ min_instance_area = 1000 # absolute pixel floor
32
+ min_instance_frac = 0.001 # and at least 0.1% of the frame
33
+ max_instances_per_class = 0 # 0 = keep all; set e.g. 3 to cap the long tail
34
+
35
+
36
+ [model]
37
+ # fusion head: "gated" (GMU) or "mlp" (concat+MLP). Read by train_latest_models.py; a contradicting --fusion flag is an error, so checkpoint_path can't hold the wrong head.
38
+ fusion = "gated"
39
+ vision_dim = 1024 # DINOv3 ViT-L/16 CLS token
40
+ language_dim = 768 # SigLIP2 base text embedding
41
+ num_classes = 57
42
+
43
+ [training]
44
+ batch_size = 32
45
+
46
+ # Batch size for the OFFLINE SERIALIZATION pass, which is a completely different
47
+ # memory regime from training: it pushes full-resolution images through the 7B
48
+ # VLM, whereas [training].batch_size only moves cached 768-d vectors through a
49
+ # small MLP. Measured on the 23.6 GiB 4090 -- static weights 16.2 GiB, so only
50
+ # ~7.4 GiB is left: batch 8 peaks at 17.7 GiB, 16 at 19.2 GiB, and 32 OOMs.
51
+ # 8 leaves headroom for a labmate's job to coexist; raise to 16 on a free card.
52
+ serialization_batch_size = 8
53
+ learning_rate = 5e-5
54
+ epochs = 50
55
+ train_ratio = 0.8 # 80% for training
56
+ val_ratio = 0.2 # 20% for validation
57
+ tensorboard_log_dir = "<local>/dms_dinov3_siglip2_gated_reg"
58
+
59
+ # ---- regularisation / schedule (train_latest_models.py; all optional) ----
60
+ # The baseline runs (wd 1e-4, constant LR, 50 epochs) overfit on DMS: val loss
61
+ # bottomed at epoch 13-15 and then rose while train accuracy kept climbing.
62
+ weight_decay = 1e-2 # was 1e-4 (the default when this key is absent)
63
+ lr_schedule = "cosine" # "constant" (default) | "cosine", stepped per epoch over `epochs`
64
+ min_lr = 1e-6 # cosine floor
65
+ early_stopping_patience = 8 # stop after 8 epochs without val-loss improvement; 0 = off
66
+
67
+ [inference]
68
+ checkpoint_path = "<local>/best_model_dms_latest_gated_reg.pth"
69
+
70
+ [logging]
71
+ wandb_project = "material-classification"
72
+ wandb_run_name = "dms-dinov3-siglip2-gated-reg"
DMS/dinov3_siglip2_gated_reg/head.json ADDED
@@ -0,0 +1,99 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "fusion": "gated",
3
+ "head": "Gated Multimodal Unit",
4
+ "head_kwargs": {},
5
+ "vision_dim": 1024,
6
+ "language_dim": 768,
7
+ "num_classes": 57,
8
+ "classes": [
9
+ "No label",
10
+ "Animal skin",
11
+ "Bone/teeth/horn",
12
+ "Brickwork",
13
+ "Cardboard",
14
+ "Carpet/rug",
15
+ "Ceiling tile",
16
+ "Ceramic",
17
+ "Chalkboard/blackboard",
18
+ "Clutter",
19
+ "Concrete",
20
+ "Cork/corkboard",
21
+ "Engineered stone",
22
+ "Fabric/cloth",
23
+ "Fiberglass wool",
24
+ "Fire",
25
+ "Foliage",
26
+ "Food",
27
+ "Fur",
28
+ "Gemstone/quartz",
29
+ "Glass",
30
+ "Hair",
31
+ "I cannot tell",
32
+ "Ice",
33
+ "Leather",
34
+ "Liquid, non-water",
35
+ "Metal",
36
+ "Mirror",
37
+ "Not on list",
38
+ "Paint/plaster/enamel",
39
+ "Paper",
40
+ "Pearl",
41
+ "Photograph/painting",
42
+ "Plastic, clear",
43
+ "Plastic, non-clear",
44
+ "Rubber/latex",
45
+ "Sand",
46
+ "Skin/lips",
47
+ "Sky",
48
+ "Snow",
49
+ "Soap",
50
+ "Soil/mud",
51
+ "Sponge",
52
+ "Stone, natural",
53
+ "Stone, polished",
54
+ "Styrofoam",
55
+ "Tile",
56
+ "Wallpaper",
57
+ "Water",
58
+ "Wax",
59
+ "Whiteboard",
60
+ "Wicker",
61
+ "Wood",
62
+ "Wood, tree",
63
+ "Bad polygon",
64
+ "Multiple materials",
65
+ "Asphalt"
66
+ ],
67
+ "dataset": "Apple Dense Material Segmentation",
68
+ "dataset_key": "DMS",
69
+ "encoders": {
70
+ "vision": "DINOv3 ViT-L/16 (CLS token, frozen)",
71
+ "language": "SigLIP2 base text encoder over Qwen3-VL-8B captions (frozen)",
72
+ "short": "DINOv3-SigLIP2",
73
+ "slug": "dinov3_siglip2"
74
+ },
75
+ "parameters": 1985081,
76
+ "training": {
77
+ "learning_rate": 5e-05,
78
+ "epochs": 50,
79
+ "batch_size": 32,
80
+ "weight_decay": 0.01,
81
+ "lr_schedule": "cosine",
82
+ "early_stopping_patience": 8,
83
+ "checkpoint": "best validation loss"
84
+ },
85
+ "sha256": {
86
+ "safetensors": "651edac500aacfb32bec53e14e7b2da4c660eb67acdaa350a8a700f5cf060453",
87
+ "pth": "b3dd5b15372df360a54de3889039b15cced829cbe485bfd4ab07e0e92bc9d340"
88
+ },
89
+ "source": {
90
+ "config": "config/config_latest_models_gated_reg.toml",
91
+ "git_commit": "1a8130c922267fb0786a33e3854a7e00763cc38f+dirty",
92
+ "checkpoint_mtime": "2026-10-07T18:00:41"
93
+ },
94
+ "metrics": {
95
+ "mIoU": 0.4606188697826707,
96
+ "mAcc": 0.6402625240517726,
97
+ "eval_samples": 186231
98
+ }
99
+ }
DMS/dinov3_siglip2_gated_reg/metrics.json ADDED
@@ -0,0 +1,296 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "dataset": "DMS",
3
+ "config": "config/config_latest_models_gated_reg.toml",
4
+ "checkpoint": "<local>/best_model_dms_latest_gated_reg.pth",
5
+ "fusion_type": "gated",
6
+ "num_eval_samples": 186231,
7
+ "mIoU": 0.4606188697826707,
8
+ "mAcc": 0.6402625240517726,
9
+ "per_class": {
10
+ "No label": {
11
+ "accuracy": 0.0,
12
+ "iou": 0.0,
13
+ "support": 0
14
+ },
15
+ "Animal skin": {
16
+ "accuracy": 0.631578947368421,
17
+ "iou": 0.4,
18
+ "support": 114
19
+ },
20
+ "Bone/teeth/horn": {
21
+ "accuracy": 0.75,
22
+ "iou": 0.6470588235294118,
23
+ "support": 44
24
+ },
25
+ "Brickwork": {
26
+ "accuracy": 0.7631814119749777,
27
+ "iou": 0.5381222432262129,
28
+ "support": 1119
29
+ },
30
+ "Cardboard": {
31
+ "accuracy": 0.7526881720430108,
32
+ "iou": 0.48826886493341787,
33
+ "support": 1023
34
+ },
35
+ "Carpet/rug": {
36
+ "accuracy": 0.8024316109422492,
37
+ "iou": 0.4708120318630365,
38
+ "support": 4935
39
+ },
40
+ "Ceiling tile": {
41
+ "accuracy": 0.7756539235412475,
42
+ "iou": 0.5102581072137657,
43
+ "support": 994
44
+ },
45
+ "Ceramic": {
46
+ "accuracy": 0.8300567933595456,
47
+ "iou": 0.6176853055916776,
48
+ "support": 2289
49
+ },
50
+ "Chalkboard/blackboard": {
51
+ "accuracy": 0.7302325581395349,
52
+ "iou": 0.548951048951049,
53
+ "support": 215
54
+ },
55
+ "Clutter": {
56
+ "accuracy": 0.4716981132075472,
57
+ "iou": 0.3424657534246575,
58
+ "support": 53
59
+ },
60
+ "Concrete": {
61
+ "accuracy": 0.5145102781136639,
62
+ "iou": 0.28263035536366654,
63
+ "support": 1654
64
+ },
65
+ "Cork/corkboard": {
66
+ "accuracy": 0.37254901960784315,
67
+ "iou": 0.21348314606741572,
68
+ "support": 51
69
+ },
70
+ "Engineered stone": {
71
+ "accuracy": 0.23595505617977527,
72
+ "iou": 0.1640625,
73
+ "support": 89
74
+ },
75
+ "Fabric/cloth": {
76
+ "accuracy": 0.7821157578965943,
77
+ "iou": 0.7193167525459488,
78
+ "support": 22668
79
+ },
80
+ "Fiberglass wool": {
81
+ "accuracy": 0.3,
82
+ "iou": 0.18181818181818182,
83
+ "support": 20
84
+ },
85
+ "Fire": {
86
+ "accuracy": 0.8,
87
+ "iou": 0.49382716049382713,
88
+ "support": 50
89
+ },
90
+ "Foliage": {
91
+ "accuracy": 0.9101516919486581,
92
+ "iou": 0.7878787878787878,
93
+ "support": 5142
94
+ },
95
+ "Food": {
96
+ "accuracy": 0.8636871508379889,
97
+ "iou": 0.6578723404255319,
98
+ "support": 895
99
+ },
100
+ "Fur": {
101
+ "accuracy": 0.8259860788863109,
102
+ "iou": 0.688588007736944,
103
+ "support": 431
104
+ },
105
+ "Gemstone/quartz": {
106
+ "accuracy": 0.68,
107
+ "iou": 0.2677165354330709,
108
+ "support": 50
109
+ },
110
+ "Glass": {
111
+ "accuracy": 0.7577358490566037,
112
+ "iou": 0.6721008072455208,
113
+ "support": 22525
114
+ },
115
+ "Hair": {
116
+ "accuracy": 0.9782991202346041,
117
+ "iou": 0.9238438105787871,
118
+ "support": 6820
119
+ },
120
+ "I cannot tell": {
121
+ "accuracy": 0.0,
122
+ "iou": 0.0,
123
+ "support": 0
124
+ },
125
+ "Ice": {
126
+ "accuracy": 0.5454545454545454,
127
+ "iou": 0.46875,
128
+ "support": 55
129
+ },
130
+ "Leather": {
131
+ "accuracy": 0.7197750702905342,
132
+ "iou": 0.43986254295532645,
133
+ "support": 2134
134
+ },
135
+ "Liquid, non-water": {
136
+ "accuracy": 0.4722222222222222,
137
+ "iou": 0.2698412698412698,
138
+ "support": 36
139
+ },
140
+ "Metal": {
141
+ "accuracy": 0.8048137157929443,
142
+ "iou": 0.5654389622422978,
143
+ "support": 9099
144
+ },
145
+ "Mirror": {
146
+ "accuracy": 0.6888331242158093,
147
+ "iou": 0.43364928909952605,
148
+ "support": 797
149
+ },
150
+ "Not on list": {
151
+ "accuracy": 0.0,
152
+ "iou": 0.0,
153
+ "support": 0
154
+ },
155
+ "Paint/plaster/enamel": {
156
+ "accuracy": 0.619308004148204,
157
+ "iou": 0.5437013739447112,
158
+ "support": 31821
159
+ },
160
+ "Paper": {
161
+ "accuracy": 0.8385812842738369,
162
+ "iou": 0.693562545720556,
163
+ "support": 11306
164
+ },
165
+ "Pearl": {
166
+ "accuracy": 0.0,
167
+ "iou": 0.0,
168
+ "support": 1
169
+ },
170
+ "Photograph/painting": {
171
+ "accuracy": 0.7142001198322349,
172
+ "iou": 0.38402061855670105,
173
+ "support": 1669
174
+ },
175
+ "Plastic, clear": {
176
+ "accuracy": 0.7065420560747664,
177
+ "iou": 0.4186046511627907,
178
+ "support": 1605
179
+ },
180
+ "Plastic, non-clear": {
181
+ "accuracy": 0.6639065817409766,
182
+ "iou": 0.5230263157894737,
183
+ "support": 14130
184
+ },
185
+ "Rubber/latex": {
186
+ "accuracy": 0.6011183597390494,
187
+ "iou": 0.3425385023898035,
188
+ "support": 1073
189
+ },
190
+ "Sand": {
191
+ "accuracy": 0.3409090909090909,
192
+ "iou": 0.24793388429752067,
193
+ "support": 88
194
+ },
195
+ "Skin/lips": {
196
+ "accuracy": 0.973601827565784,
197
+ "iou": 0.9409600130836536,
198
+ "support": 11819
199
+ },
200
+ "Sky": {
201
+ "accuracy": 0.9201485608170845,
202
+ "iou": 0.7038352272727273,
203
+ "support": 2154
204
+ },
205
+ "Snow": {
206
+ "accuracy": 0.7431192660550459,
207
+ "iou": 0.5436241610738255,
208
+ "support": 109
209
+ },
210
+ "Soap": {
211
+ "accuracy": 0.0,
212
+ "iou": 0.0,
213
+ "support": 7
214
+ },
215
+ "Soil/mud": {
216
+ "accuracy": 0.6773211567732116,
217
+ "iou": 0.3938053097345133,
218
+ "support": 657
219
+ },
220
+ "Sponge": {
221
+ "accuracy": 0.2777777777777778,
222
+ "iou": 0.2,
223
+ "support": 18
224
+ },
225
+ "Stone, natural": {
226
+ "accuracy": 0.6347256347256347,
227
+ "iou": 0.4487550665894615,
228
+ "support": 1221
229
+ },
230
+ "Stone, polished": {
231
+ "accuracy": 0.399737876802097,
232
+ "iou": 0.2654482158398607,
233
+ "support": 763
234
+ },
235
+ "Styrofoam": {
236
+ "accuracy": 0.12903225806451613,
237
+ "iou": 0.08695652173913043,
238
+ "support": 31
239
+ },
240
+ "Tile": {
241
+ "accuracy": 0.649852148199687,
242
+ "iou": 0.44124247076886736,
243
+ "support": 5749
244
+ },
245
+ "Wallpaper": {
246
+ "accuracy": 0.6175595238095238,
247
+ "iou": 0.3312051077414206,
248
+ "support": 672
249
+ },
250
+ "Water": {
251
+ "accuracy": 0.6696935300794552,
252
+ "iou": 0.508182601205857,
253
+ "support": 881
254
+ },
255
+ "Wax": {
256
+ "accuracy": 0.8771929824561403,
257
+ "iou": 0.6711409395973155,
258
+ "support": 114
259
+ },
260
+ "Whiteboard": {
261
+ "accuracy": 0.6636636636636637,
262
+ "iou": 0.4258188824662813,
263
+ "support": 333
264
+ },
265
+ "Wicker": {
266
+ "accuracy": 0.7884297520661157,
267
+ "iou": 0.5740072202166066,
268
+ "support": 605
269
+ },
270
+ "Wood": {
271
+ "accuracy": 0.8096232943787948,
272
+ "iou": 0.631544102668568,
273
+ "support": 15317
274
+ },
275
+ "Wood, tree": {
276
+ "accuracy": 0.7482993197278912,
277
+ "iou": 0.5034324942791762,
278
+ "support": 588
279
+ },
280
+ "Bad polygon": {
281
+ "accuracy": 0.0,
282
+ "iou": 0.0,
283
+ "support": 0
284
+ },
285
+ "Multiple materials": {
286
+ "accuracy": 0.0,
287
+ "iou": 0.0,
288
+ "support": 0
289
+ },
290
+ "Asphalt": {
291
+ "accuracy": 0.4696969696969697,
292
+ "iou": 0.3345323741007194,
293
+ "support": 198
294
+ }
295
+ }
296
+ }
DMS/dinov3_siglip2_gated_reg/model.pth ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:b3dd5b15372df360a54de3889039b15cced829cbe485bfd4ab07e0e92bc9d340
3
+ size 7959811
DMS/dinov3_siglip2_gated_reg/model.safetensors ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:651edac500aacfb32bec53e14e7b2da4c660eb67acdaa350a8a700f5cf060453
3
+ size 7952748
DMS/dinov3_siglip2_gated_reg/split.json ADDED
The diff for this file is too large to render. See raw diff
 
DMS/dinov3_siglip2_lmf/README.md ADDED
@@ -0,0 +1,52 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # DINOv3-SigLIP2 + Low-rank Multimodal Fusion on Apple Dense Material Segmentation
2
+
3
+ A material-classification **fusion head** from SegObjectMaterial. It classifies the
4
+ material of a masked object from two frozen embeddings:
5
+
6
+ | | |
7
+ |---|---|
8
+ | vision | DINOv3 ViT-L/16 (CLS token, frozen) -> 1024-d |
9
+ | language | SigLIP2 base text encoder over Qwen3-VL-8B captions (frozen) -> 768-d |
10
+ | head | Low-rank Multimodal Fusion (`lmf`, rank=4, hidden_dim=256, modality_dropout=0.0), 1,922,365 parameters |
11
+ | classes | 57 (Apple Dense Material Segmentation) |
12
+
13
+ **This repo holds only the head.** Features must come from the same encoders,
14
+ captioner and prompts as training (see the SegObjectMaterial repository); the
15
+ encoders are downloaded from their own model pages under their own licenses.
16
+
17
+ ## Evaluation
18
+
19
+ Held-out split recorded in `split.json` (source images never seen in training).
20
+ Single training run -- differences under ~0.5 mIoU points between heads are within
21
+ run-to-run noise.
22
+
23
+ | mIoU | mAcc | eval samples |
24
+ |---|---|---|
25
+ | 0.4407 | 0.6181 | 186,231 |
26
+
27
+ ## Training
28
+
29
+ ```json
30
+ {
31
+ "learning_rate": 5e-05,
32
+ "epochs": 50,
33
+ "batch_size": 32,
34
+ "weight_decay": 0.0001,
35
+ "lr_schedule": "constant",
36
+ "early_stopping_patience": 0,
37
+ "checkpoint": "best validation loss"
38
+ }
39
+ ```
40
+
41
+ ## Use
42
+
43
+ ```python
44
+ from utils.hub import load_head_from_hub # SegObjectMaterial repository
45
+ head, info = load_head_from_hub("s0um0r0y/SegObjectMaterial", "DMS/dinov3_siglip2_lmf")
46
+ logits = head(vision_features, language_features) # [B, 1024], [B, 768]
47
+ ```
48
+
49
+ ## Integrity
50
+
51
+ - `model.safetensors` sha256 `ee69c3ea4a8f7ecee29b767287987ec1c19082370b2dad48ae4d4b76f45b386a`
52
+ - source config `config/config_latest_models_lmf.toml`, code commit `1a8130c922267fb0786a33e3854a7e00763cc38f+dirty`
DMS/dinov3_siglip2_lmf/config.toml ADDED
@@ -0,0 +1,77 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # LMF-head twin of config/config.toml.
2
+ # SAME embedding cache -- the head type does not change the cached features, so
3
+ # nothing needs re-serializing. Only the checkpoint, TensorBoard dir and W&B run
4
+ # differ, so this run can never overwrite the gated or mlp checkpoints.
5
+
6
+ # Apple DMS -- LATEST-MODELS pipeline: DINOv3 ViT-L/16 (1024) + Qwen3-VL -> SigLIP2 text (768)
7
+ #
8
+ # Pair this with:
9
+ # src/vision_stream_latest_models.py + src/language_stream_latest_models.py
10
+ # run_serialization_latest_models.py -> train_latest_models.py
11
+ #
12
+ # For the base DINOv2/CLIP pipeline (run_serialization.py -> train.py) use
13
+ # config/config_dinov2_clip.toml instead -- its vision_dim is 768, not 1024.
14
+
15
+ [data]
16
+ dataset_type = "apple_dms"
17
+ image_dir = "<local>/images"
18
+ mask_dir = "<local>/labels"
19
+ # Rebuilt automatically on first run; the index now stores one entry per
20
+ # CONNECTED COMPONENT, so any pre-existing labels.json must be removed first.
21
+ labels_file = "<local>/labels_instances.json"
22
+ # Separate cache: DINOv3 features are 1024-d and must not mix with the
23
+ # 768-d DINOv2 cache written by run_serialization.py.
24
+ tensor_cache_dir = "<local>/tensor_cache_dir_latest_models"
25
+
26
+ # Connected-component filtering (measured on 400 real DMS masks):
27
+ # keeping every component gives 7.5x more samples than the old per-(image,class)
28
+ # scheme -- 2.45M samples / 47 GB / ~7.5x the VLM captioning time -- because 69%
29
+ # of components are under 0.1% of the frame and crop to a few pixels.
30
+ # A component is kept when area >= max(min_instance_area, min_instance_frac * frame).
31
+ min_instance_area = 1000 # absolute pixel floor
32
+ min_instance_frac = 0.001 # and at least 0.1% of the frame
33
+ max_instances_per_class = 0 # 0 = keep all; set e.g. 3 to cap the long tail
34
+
35
+
36
+ [model]
37
+ # fusion head: "lmf" = low-rank multimodal fusion (src/fusion_classifier.py,
38
+ # LowRankFusionHead). Read by train_latest_models.py; a contradicting --fusion
39
+ # flag is an error, so checkpoint_path can't hold the wrong head.
40
+ fusion = "lmf"
41
+ vision_dim = 1024 # DINOv3 ViT-L/16 CLS token
42
+ language_dim = 768 # SigLIP2 base text embedding
43
+ num_classes = 57
44
+
45
+ # LMF hyperparameters. rank 4 x hidden 256 = ~1.84M fusion parameters, close to
46
+ # the gated head (~1.97M), so gated-vs-lmf compares the fusion operator rather
47
+ # than model size. Both are read back from the checkpoint at load time, so
48
+ # evaluate/inference scripts need no extra flags.
49
+ lmf_rank = 4
50
+ lmf_hidden = 256
51
+ # Fraction of training samples with ONE stream zeroed (half vision, half
52
+ # language). 0.0 = plain LMF, as in the paper. Try 0.2 as a second run: it
53
+ # forces the head to work from either stream alone.
54
+ modality_dropout = 0.0
55
+
56
+ [training]
57
+ batch_size = 32
58
+
59
+ # Batch size for the OFFLINE SERIALIZATION pass, which is a completely different
60
+ # memory regime from training: it pushes full-resolution images through the 7B
61
+ # VLM, whereas [training].batch_size only moves cached 768-d vectors through a
62
+ # small MLP. Measured on the 23.6 GiB 4090 -- static weights 16.2 GiB, so only
63
+ # ~7.4 GiB is left: batch 8 peaks at 17.7 GiB, 16 at 19.2 GiB, and 32 OOMs.
64
+ # 8 leaves headroom for a labmate's job to coexist; raise to 16 on a free card.
65
+ serialization_batch_size = 8
66
+ learning_rate = 5e-5
67
+ epochs = 50
68
+ train_ratio = 0.8 # 80% for training
69
+ val_ratio = 0.2 # 20% for validation
70
+ tensorboard_log_dir = "<local>/dms_dinov3_siglip2_lmf"
71
+
72
+ [inference]
73
+ checkpoint_path = "<local>/best_model_dms_latest_lmf.pth"
74
+
75
+ [logging]
76
+ wandb_project = "material-classification"
77
+ wandb_run_name = "dms-dinov3-siglip2-lmf"
DMS/dinov3_siglip2_lmf/head.json ADDED
@@ -0,0 +1,103 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "fusion": "lmf",
3
+ "head": "Low-rank Multimodal Fusion",
4
+ "head_kwargs": {
5
+ "rank": 4,
6
+ "hidden_dim": 256,
7
+ "modality_dropout": 0.0
8
+ },
9
+ "vision_dim": 1024,
10
+ "language_dim": 768,
11
+ "num_classes": 57,
12
+ "classes": [
13
+ "No label",
14
+ "Animal skin",
15
+ "Bone/teeth/horn",
16
+ "Brickwork",
17
+ "Cardboard",
18
+ "Carpet/rug",
19
+ "Ceiling tile",
20
+ "Ceramic",
21
+ "Chalkboard/blackboard",
22
+ "Clutter",
23
+ "Concrete",
24
+ "Cork/corkboard",
25
+ "Engineered stone",
26
+ "Fabric/cloth",
27
+ "Fiberglass wool",
28
+ "Fire",
29
+ "Foliage",
30
+ "Food",
31
+ "Fur",
32
+ "Gemstone/quartz",
33
+ "Glass",
34
+ "Hair",
35
+ "I cannot tell",
36
+ "Ice",
37
+ "Leather",
38
+ "Liquid, non-water",
39
+ "Metal",
40
+ "Mirror",
41
+ "Not on list",
42
+ "Paint/plaster/enamel",
43
+ "Paper",
44
+ "Pearl",
45
+ "Photograph/painting",
46
+ "Plastic, clear",
47
+ "Plastic, non-clear",
48
+ "Rubber/latex",
49
+ "Sand",
50
+ "Skin/lips",
51
+ "Sky",
52
+ "Snow",
53
+ "Soap",
54
+ "Soil/mud",
55
+ "Sponge",
56
+ "Stone, natural",
57
+ "Stone, polished",
58
+ "Styrofoam",
59
+ "Tile",
60
+ "Wallpaper",
61
+ "Water",
62
+ "Wax",
63
+ "Whiteboard",
64
+ "Wicker",
65
+ "Wood",
66
+ "Wood, tree",
67
+ "Bad polygon",
68
+ "Multiple materials",
69
+ "Asphalt"
70
+ ],
71
+ "dataset": "Apple Dense Material Segmentation",
72
+ "dataset_key": "DMS",
73
+ "encoders": {
74
+ "vision": "DINOv3 ViT-L/16 (CLS token, frozen)",
75
+ "language": "SigLIP2 base text encoder over Qwen3-VL-8B captions (frozen)",
76
+ "short": "DINOv3-SigLIP2",
77
+ "slug": "dinov3_siglip2"
78
+ },
79
+ "parameters": 1922365,
80
+ "training": {
81
+ "learning_rate": 5e-05,
82
+ "epochs": 50,
83
+ "batch_size": 32,
84
+ "weight_decay": 0.0001,
85
+ "lr_schedule": "constant",
86
+ "early_stopping_patience": 0,
87
+ "checkpoint": "best validation loss"
88
+ },
89
+ "sha256": {
90
+ "safetensors": "ee69c3ea4a8f7ecee29b767287987ec1c19082370b2dad48ae4d4b76f45b386a",
91
+ "pth": "a5b00ebaeb97a3bb93314ed849bef99d49f222cb4f9f82c5be4d659ed87dca30"
92
+ },
93
+ "source": {
94
+ "config": "config/config_latest_models_lmf.toml",
95
+ "git_commit": "1a8130c922267fb0786a33e3854a7e00763cc38f+dirty",
96
+ "checkpoint_mtime": "2026-10-07T14:53:13"
97
+ },
98
+ "metrics": {
99
+ "mIoU": 0.440722402484214,
100
+ "mAcc": 0.6180633687278619,
101
+ "eval_samples": 186231
102
+ }
103
+ }
DMS/dinov3_siglip2_lmf/metrics.json ADDED
@@ -0,0 +1,296 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "dataset": "DMS",
3
+ "checkpoint": "<local>/best_model_dms_latest_lmf.pth",
4
+ "fusion_type": "lmf",
5
+ "num_eval_samples": 186231,
6
+ "mIoU": 0.440722402484214,
7
+ "mAcc": 0.6180633687278619,
8
+ "per_class": {
9
+ "No label": {
10
+ "accuracy": 0.0,
11
+ "iou": 0.0,
12
+ "support": 0
13
+ },
14
+ "Animal skin": {
15
+ "accuracy": 0.6052631578947368,
16
+ "iou": 0.41566265060240964,
17
+ "support": 114
18
+ },
19
+ "Bone/teeth/horn": {
20
+ "accuracy": 0.6590909090909091,
21
+ "iou": 0.5918367346938775,
22
+ "support": 44
23
+ },
24
+ "Brickwork": {
25
+ "accuracy": 0.7363717605004468,
26
+ "iou": 0.5061425061425061,
27
+ "support": 1119
28
+ },
29
+ "Cardboard": {
30
+ "accuracy": 0.7448680351906158,
31
+ "iou": 0.47270471464019853,
32
+ "support": 1023
33
+ },
34
+ "Carpet/rug": {
35
+ "accuracy": 0.7785207700101318,
36
+ "iou": 0.483757239989927,
37
+ "support": 4935
38
+ },
39
+ "Ceiling tile": {
40
+ "accuracy": 0.7716297786720322,
41
+ "iou": 0.4845230574857865,
42
+ "support": 994
43
+ },
44
+ "Ceramic": {
45
+ "accuracy": 0.8283093053735255,
46
+ "iou": 0.5846438482886216,
47
+ "support": 2289
48
+ },
49
+ "Chalkboard/blackboard": {
50
+ "accuracy": 0.7348837209302326,
51
+ "iou": 0.531986531986532,
52
+ "support": 215
53
+ },
54
+ "Clutter": {
55
+ "accuracy": 0.41509433962264153,
56
+ "iou": 0.3235294117647059,
57
+ "support": 53
58
+ },
59
+ "Concrete": {
60
+ "accuracy": 0.5126964933494559,
61
+ "iou": 0.2663316582914573,
62
+ "support": 1654
63
+ },
64
+ "Cork/corkboard": {
65
+ "accuracy": 0.29411764705882354,
66
+ "iou": 0.18292682926829268,
67
+ "support": 51
68
+ },
69
+ "Engineered stone": {
70
+ "accuracy": 0.19101123595505617,
71
+ "iou": 0.14049586776859505,
72
+ "support": 89
73
+ },
74
+ "Fabric/cloth": {
75
+ "accuracy": 0.7754543850361744,
76
+ "iou": 0.708876073718595,
77
+ "support": 22668
78
+ },
79
+ "Fiberglass wool": {
80
+ "accuracy": 0.25,
81
+ "iou": 0.15625,
82
+ "support": 20
83
+ },
84
+ "Fire": {
85
+ "accuracy": 0.78,
86
+ "iou": 0.47560975609756095,
87
+ "support": 50
88
+ },
89
+ "Foliage": {
90
+ "accuracy": 0.9074290159471023,
91
+ "iou": 0.7656711519527404,
92
+ "support": 5142
93
+ },
94
+ "Food": {
95
+ "accuracy": 0.8670391061452514,
96
+ "iou": 0.6308943089430894,
97
+ "support": 895
98
+ },
99
+ "Fur": {
100
+ "accuracy": 0.8167053364269141,
101
+ "iou": 0.6579439252336449,
102
+ "support": 431
103
+ },
104
+ "Gemstone/quartz": {
105
+ "accuracy": 0.6,
106
+ "iou": 0.21739130434782608,
107
+ "support": 50
108
+ },
109
+ "Glass": {
110
+ "accuracy": 0.753607103218646,
111
+ "iou": 0.6518566875312009,
112
+ "support": 22525
113
+ },
114
+ "Hair": {
115
+ "accuracy": 0.9782991202346041,
116
+ "iou": 0.9080021774632553,
117
+ "support": 6820
118
+ },
119
+ "I cannot tell": {
120
+ "accuracy": 0.0,
121
+ "iou": 0.0,
122
+ "support": 0
123
+ },
124
+ "Ice": {
125
+ "accuracy": 0.4909090909090909,
126
+ "iou": 0.39705882352941174,
127
+ "support": 55
128
+ },
129
+ "Leather": {
130
+ "accuracy": 0.7235238987816307,
131
+ "iou": 0.40450615666754,
132
+ "support": 2134
133
+ },
134
+ "Liquid, non-water": {
135
+ "accuracy": 0.4722222222222222,
136
+ "iou": 0.3148148148148148,
137
+ "support": 36
138
+ },
139
+ "Metal": {
140
+ "accuracy": 0.8027255742389273,
141
+ "iou": 0.5505389311826336,
142
+ "support": 9099
143
+ },
144
+ "Mirror": {
145
+ "accuracy": 0.671267252195734,
146
+ "iou": 0.4080854309687262,
147
+ "support": 797
148
+ },
149
+ "Not on list": {
150
+ "accuracy": 0.0,
151
+ "iou": 0.0,
152
+ "support": 0
153
+ },
154
+ "Paint/plaster/enamel": {
155
+ "accuracy": 0.6058577668835046,
156
+ "iou": 0.5275846970609162,
157
+ "support": 31821
158
+ },
159
+ "Paper": {
160
+ "accuracy": 0.823810366177251,
161
+ "iou": 0.6853064527996469,
162
+ "support": 11306
163
+ },
164
+ "Pearl": {
165
+ "accuracy": 0.0,
166
+ "iou": 0.0,
167
+ "support": 1
168
+ },
169
+ "Photograph/painting": {
170
+ "accuracy": 0.6854403834631516,
171
+ "iou": 0.38209752839011357,
172
+ "support": 1669
173
+ },
174
+ "Plastic, clear": {
175
+ "accuracy": 0.6834890965732088,
176
+ "iou": 0.40735239509840326,
177
+ "support": 1605
178
+ },
179
+ "Plastic, non-clear": {
180
+ "accuracy": 0.6435244161358811,
181
+ "iou": 0.5068844417191594,
182
+ "support": 14130
183
+ },
184
+ "Rubber/latex": {
185
+ "accuracy": 0.5526561043802423,
186
+ "iou": 0.32944444444444443,
187
+ "support": 1073
188
+ },
189
+ "Sand": {
190
+ "accuracy": 0.32954545454545453,
191
+ "iou": 0.25,
192
+ "support": 88
193
+ },
194
+ "Skin/lips": {
195
+ "accuracy": 0.9675099416194264,
196
+ "iou": 0.9362207303094809,
197
+ "support": 11819
198
+ },
199
+ "Sky": {
200
+ "accuracy": 0.9317548746518106,
201
+ "iou": 0.6459607338268426,
202
+ "support": 2154
203
+ },
204
+ "Snow": {
205
+ "accuracy": 0.6788990825688074,
206
+ "iou": 0.4567901234567901,
207
+ "support": 109
208
+ },
209
+ "Soap": {
210
+ "accuracy": 0.0,
211
+ "iou": 0.0,
212
+ "support": 7
213
+ },
214
+ "Soil/mud": {
215
+ "accuracy": 0.6438356164383562,
216
+ "iou": 0.3960674157303371,
217
+ "support": 657
218
+ },
219
+ "Sponge": {
220
+ "accuracy": 0.16666666666666666,
221
+ "iou": 0.13636363636363635,
222
+ "support": 18
223
+ },
224
+ "Stone, natural": {
225
+ "accuracy": 0.6224406224406225,
226
+ "iou": 0.45292014302741357,
227
+ "support": 1221
228
+ },
229
+ "Stone, polished": {
230
+ "accuracy": 0.36828309305373524,
231
+ "iou": 0.2526978417266187,
232
+ "support": 763
233
+ },
234
+ "Styrofoam": {
235
+ "accuracy": 0.03225806451612903,
236
+ "iou": 0.03125,
237
+ "support": 31
238
+ },
239
+ "Tile": {
240
+ "accuracy": 0.6536789006783789,
241
+ "iou": 0.43789326497319975,
242
+ "support": 5749
243
+ },
244
+ "Wallpaper": {
245
+ "accuracy": 0.5744047619047619,
246
+ "iou": 0.3534798534798535,
247
+ "support": 672
248
+ },
249
+ "Water": {
250
+ "accuracy": 0.6515323496027242,
251
+ "iou": 0.49653979238754326,
252
+ "support": 881
253
+ },
254
+ "Wax": {
255
+ "accuracy": 0.8771929824561403,
256
+ "iou": 0.5586592178770949,
257
+ "support": 114
258
+ },
259
+ "Whiteboard": {
260
+ "accuracy": 0.6606606606606606,
261
+ "iou": 0.4365079365079365,
262
+ "support": 333
263
+ },
264
+ "Wicker": {
265
+ "accuracy": 0.7867768595041322,
266
+ "iou": 0.5854858548585485,
267
+ "support": 605
268
+ },
269
+ "Wood": {
270
+ "accuracy": 0.7917999608278383,
271
+ "iou": 0.619122977181071,
272
+ "support": 15317
273
+ },
274
+ "Wood, tree": {
275
+ "accuracy": 0.7108843537414966,
276
+ "iou": 0.46756152125279643,
277
+ "support": 588
278
+ },
279
+ "Bad polygon": {
280
+ "accuracy": 0.0,
281
+ "iou": 0.0,
282
+ "support": 0
283
+ },
284
+ "Multiple materials": {
285
+ "accuracy": 0.0,
286
+ "iou": 0.0,
287
+ "support": 0
288
+ },
289
+ "Asphalt": {
290
+ "accuracy": 0.5353535353535354,
291
+ "iou": 0.3333333333333333,
292
+ "support": 198
293
+ }
294
+ },
295
+ "config": "config/config_latest_models_lmf.toml"
296
+ }
DMS/dinov3_siglip2_lmf/model.pth ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:a5b00ebaeb97a3bb93314ed849bef99d49f222cb4f9f82c5be4d659ed87dca30
3
+ size 7701480
DMS/dinov3_siglip2_lmf/model.safetensors ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:ee69c3ea4a8f7ecee29b767287987ec1c19082370b2dad48ae4d4b76f45b386a
3
+ size 7695412
DMS/dinov3_siglip2_lmf/split.json ADDED
The diff for this file is too large to render. See raw diff
 
DMS/dinov3_siglip2_lmf_reg/README.md ADDED
@@ -0,0 +1,52 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # DINOv3-SigLIP2 + Low-rank Multimodal Fusion on Apple Dense Material Segmentation
2
+
3
+ A material-classification **fusion head** from SegObjectMaterial. It classifies the
4
+ material of a masked object from two frozen embeddings:
5
+
6
+ | | |
7
+ |---|---|
8
+ | vision | DINOv3 ViT-L/16 (CLS token, frozen) -> 1024-d |
9
+ | language | SigLIP2 base text encoder over Qwen3-VL-8B captions (frozen) -> 768-d |
10
+ | head | Low-rank Multimodal Fusion (`lmf`, rank=4, hidden_dim=256, modality_dropout=0.2), 1,922,365 parameters |
11
+ | classes | 57 (Apple Dense Material Segmentation) |
12
+
13
+ **This repo holds only the head.** Features must come from the same encoders,
14
+ captioner and prompts as training (see the SegObjectMaterial repository); the
15
+ encoders are downloaded from their own model pages under their own licenses.
16
+
17
+ ## Evaluation
18
+
19
+ Held-out split recorded in `split.json` (source images never seen in training).
20
+ Single training run -- differences under ~0.5 mIoU points between heads are within
21
+ run-to-run noise.
22
+
23
+ | mIoU | mAcc | eval samples |
24
+ |---|---|---|
25
+ | 0.4453 | 0.6135 | 186,231 |
26
+
27
+ ## Training
28
+
29
+ ```json
30
+ {
31
+ "learning_rate": 5e-05,
32
+ "epochs": 50,
33
+ "batch_size": 32,
34
+ "weight_decay": 0.01,
35
+ "lr_schedule": "cosine",
36
+ "early_stopping_patience": 10,
37
+ "checkpoint": "best validation loss"
38
+ }
39
+ ```
40
+
41
+ ## Use
42
+
43
+ ```python
44
+ from utils.hub import load_head_from_hub # SegObjectMaterial repository
45
+ head, info = load_head_from_hub("s0um0r0y/SegObjectMaterial", "DMS/dinov3_siglip2_lmf_reg")
46
+ logits = head(vision_features, language_features) # [B, 1024], [B, 768]
47
+ ```
48
+
49
+ ## Integrity
50
+
51
+ - `model.safetensors` sha256 `ed2fc3b7ee4dd92b575b199ea2770e3a0e0d702355dfe5f97216e50917c68cab`
52
+ - source config `config/config_latest_models_lmf_reg.toml`, code commit `1a8130c922267fb0786a33e3854a7e00763cc38f+dirty`
DMS/dinov3_siglip2_lmf_reg/config.toml ADDED
@@ -0,0 +1,89 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # REGULARISED LMF run: config_latest_models_lmf.toml + modality dropout 0.2,
2
+ # weight decay 1e-2, cosine LR and early stopping. Same cache; own checkpoint.
3
+ # Compare against config_latest_models_gated_reg.toml (same recipe, gated head).
4
+
5
+ # LMF-head twin of config/config.toml.
6
+ # SAME embedding cache -- the head type does not change the cached features, so
7
+ # nothing needs re-serializing. Only the checkpoint, TensorBoard dir and W&B run
8
+ # differ, so this run can never overwrite the gated or mlp checkpoints.
9
+
10
+ # Apple DMS -- LATEST-MODELS pipeline: DINOv3 ViT-L/16 (1024) + Qwen3-VL -> SigLIP2 text (768)
11
+ #
12
+ # Pair this with:
13
+ # src/vision_stream_latest_models.py + src/language_stream_latest_models.py
14
+ # run_serialization_latest_models.py -> train_latest_models.py
15
+ #
16
+ # For the base DINOv2/CLIP pipeline (run_serialization.py -> train.py) use
17
+ # config/config_dinov2_clip.toml instead -- its vision_dim is 768, not 1024.
18
+
19
+ [data]
20
+ dataset_type = "apple_dms"
21
+ image_dir = "<local>/images"
22
+ mask_dir = "<local>/labels"
23
+ # Rebuilt automatically on first run; the index now stores one entry per
24
+ # CONNECTED COMPONENT, so any pre-existing labels.json must be removed first.
25
+ labels_file = "<local>/labels_instances.json"
26
+ # Separate cache: DINOv3 features are 1024-d and must not mix with the
27
+ # 768-d DINOv2 cache written by run_serialization.py.
28
+ tensor_cache_dir = "<local>/tensor_cache_dir_latest_models"
29
+
30
+ # Connected-component filtering (measured on 400 real DMS masks):
31
+ # keeping every component gives 7.5x more samples than the old per-(image,class)
32
+ # scheme -- 2.45M samples / 47 GB / ~7.5x the VLM captioning time -- because 69%
33
+ # of components are under 0.1% of the frame and crop to a few pixels.
34
+ # A component is kept when area >= max(min_instance_area, min_instance_frac * frame).
35
+ min_instance_area = 1000 # absolute pixel floor
36
+ min_instance_frac = 0.001 # and at least 0.1% of the frame
37
+ max_instances_per_class = 0 # 0 = keep all; set e.g. 3 to cap the long tail
38
+
39
+
40
+ [model]
41
+ # fusion head: "lmf" = low-rank multimodal fusion (src/fusion_classifier.py,
42
+ # LowRankFusionHead). Read by train_latest_models.py; a contradicting --fusion
43
+ # flag is an error, so checkpoint_path can't hold the wrong head.
44
+ fusion = "lmf"
45
+ vision_dim = 1024 # DINOv3 ViT-L/16 CLS token
46
+ language_dim = 768 # SigLIP2 base text embedding
47
+ num_classes = 57
48
+
49
+ # LMF hyperparameters. rank 4 x hidden 256 = ~1.84M fusion parameters, close to
50
+ # the gated head (~1.97M), so gated-vs-lmf compares the fusion operator rather
51
+ # than model size. Both are read back from the checkpoint at load time, so
52
+ # evaluate/inference scripts need no extra flags.
53
+ lmf_rank = 4
54
+ lmf_hidden = 256
55
+ # Fraction of training samples with ONE stream zeroed (half vision, half
56
+ # language). 0.0 = plain LMF, as in the paper. Try 0.2 as a second run: it
57
+ # forces the head to work from either stream alone.
58
+ modality_dropout = 0.2
59
+
60
+ [training]
61
+ batch_size = 32
62
+
63
+ # Batch size for the OFFLINE SERIALIZATION pass, which is a completely different
64
+ # memory regime from training: it pushes full-resolution images through the 7B
65
+ # VLM, whereas [training].batch_size only moves cached 768-d vectors through a
66
+ # small MLP. Measured on the 23.6 GiB 4090 -- static weights 16.2 GiB, so only
67
+ # ~7.4 GiB is left: batch 8 peaks at 17.7 GiB, 16 at 19.2 GiB, and 32 OOMs.
68
+ # 8 leaves headroom for a labmate's job to coexist; raise to 16 on a free card.
69
+ serialization_batch_size = 8
70
+ learning_rate = 5e-5
71
+ epochs = 50
72
+ train_ratio = 0.8 # 80% for training
73
+ val_ratio = 0.2 # 20% for validation
74
+ tensorboard_log_dir = "<local>/dms_dinov3_siglip2_lmf_reg"
75
+
76
+ # ---- regularisation / schedule (train_latest_models.py; all optional) ----
77
+ # The baseline runs (wd 1e-4, constant LR, 50 epochs) overfit on DMS: val loss
78
+ # bottomed at epoch 13-15 and then rose while train accuracy kept climbing.
79
+ weight_decay = 1e-2 # was 1e-4 (the default when this key is absent)
80
+ lr_schedule = "cosine" # "constant" (default) | "cosine", stepped per epoch over `epochs`
81
+ min_lr = 1e-6 # cosine floor
82
+ early_stopping_patience = 10 # stop after 8 epochs without val-loss improvement; 0 = off
83
+
84
+ [inference]
85
+ checkpoint_path = "<local>/best_model_dms_latest_lmf_reg.pth"
86
+
87
+ [logging]
88
+ wandb_project = "material-classification"
89
+ wandb_run_name = "dms-dinov3-siglip2-lmf-reg"
DMS/dinov3_siglip2_lmf_reg/head.json ADDED
@@ -0,0 +1,103 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "fusion": "lmf",
3
+ "head": "Low-rank Multimodal Fusion",
4
+ "head_kwargs": {
5
+ "rank": 4,
6
+ "hidden_dim": 256,
7
+ "modality_dropout": 0.2
8
+ },
9
+ "vision_dim": 1024,
10
+ "language_dim": 768,
11
+ "num_classes": 57,
12
+ "classes": [
13
+ "No label",
14
+ "Animal skin",
15
+ "Bone/teeth/horn",
16
+ "Brickwork",
17
+ "Cardboard",
18
+ "Carpet/rug",
19
+ "Ceiling tile",
20
+ "Ceramic",
21
+ "Chalkboard/blackboard",
22
+ "Clutter",
23
+ "Concrete",
24
+ "Cork/corkboard",
25
+ "Engineered stone",
26
+ "Fabric/cloth",
27
+ "Fiberglass wool",
28
+ "Fire",
29
+ "Foliage",
30
+ "Food",
31
+ "Fur",
32
+ "Gemstone/quartz",
33
+ "Glass",
34
+ "Hair",
35
+ "I cannot tell",
36
+ "Ice",
37
+ "Leather",
38
+ "Liquid, non-water",
39
+ "Metal",
40
+ "Mirror",
41
+ "Not on list",
42
+ "Paint/plaster/enamel",
43
+ "Paper",
44
+ "Pearl",
45
+ "Photograph/painting",
46
+ "Plastic, clear",
47
+ "Plastic, non-clear",
48
+ "Rubber/latex",
49
+ "Sand",
50
+ "Skin/lips",
51
+ "Sky",
52
+ "Snow",
53
+ "Soap",
54
+ "Soil/mud",
55
+ "Sponge",
56
+ "Stone, natural",
57
+ "Stone, polished",
58
+ "Styrofoam",
59
+ "Tile",
60
+ "Wallpaper",
61
+ "Water",
62
+ "Wax",
63
+ "Whiteboard",
64
+ "Wicker",
65
+ "Wood",
66
+ "Wood, tree",
67
+ "Bad polygon",
68
+ "Multiple materials",
69
+ "Asphalt"
70
+ ],
71
+ "dataset": "Apple Dense Material Segmentation",
72
+ "dataset_key": "DMS",
73
+ "encoders": {
74
+ "vision": "DINOv3 ViT-L/16 (CLS token, frozen)",
75
+ "language": "SigLIP2 base text encoder over Qwen3-VL-8B captions (frozen)",
76
+ "short": "DINOv3-SigLIP2",
77
+ "slug": "dinov3_siglip2"
78
+ },
79
+ "parameters": 1922365,
80
+ "training": {
81
+ "learning_rate": 5e-05,
82
+ "epochs": 50,
83
+ "batch_size": 32,
84
+ "weight_decay": 0.01,
85
+ "lr_schedule": "cosine",
86
+ "early_stopping_patience": 10,
87
+ "checkpoint": "best validation loss"
88
+ },
89
+ "sha256": {
90
+ "safetensors": "ed2fc3b7ee4dd92b575b199ea2770e3a0e0d702355dfe5f97216e50917c68cab",
91
+ "pth": "fcbfcb811c95b16bba82f2765cc37aeb0861ea6067e559a36c605bfdc24f1ba0"
92
+ },
93
+ "source": {
94
+ "config": "config/config_latest_models_lmf_reg.toml",
95
+ "git_commit": "1a8130c922267fb0786a33e3854a7e00763cc38f+dirty",
96
+ "checkpoint_mtime": "2026-10-07T17:11:52"
97
+ },
98
+ "metrics": {
99
+ "mIoU": 0.4453273662621192,
100
+ "mAcc": 0.6135327722998756,
101
+ "eval_samples": 186231
102
+ }
103
+ }
DMS/dinov3_siglip2_lmf_reg/metrics.json ADDED
@@ -0,0 +1,296 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "dataset": "DMS",
3
+ "config": "config/config_latest_models_lmf_reg.toml",
4
+ "checkpoint": "<local>/best_model_dms_latest_lmf_reg.pth",
5
+ "fusion_type": "lmf",
6
+ "num_eval_samples": 186231,
7
+ "mIoU": 0.4453273662621192,
8
+ "mAcc": 0.6135327722998756,
9
+ "per_class": {
10
+ "No label": {
11
+ "accuracy": 0.0,
12
+ "iou": 0.0,
13
+ "support": 0
14
+ },
15
+ "Animal skin": {
16
+ "accuracy": 0.5526315789473685,
17
+ "iou": 0.37058823529411766,
18
+ "support": 114
19
+ },
20
+ "Bone/teeth/horn": {
21
+ "accuracy": 0.6818181818181818,
22
+ "iou": 0.6122448979591837,
23
+ "support": 44
24
+ },
25
+ "Brickwork": {
26
+ "accuracy": 0.7462019660411081,
27
+ "iou": 0.4979129397734049,
28
+ "support": 1119
29
+ },
30
+ "Cardboard": {
31
+ "accuracy": 0.7360703812316716,
32
+ "iou": 0.4944189100459619,
33
+ "support": 1023
34
+ },
35
+ "Carpet/rug": {
36
+ "accuracy": 0.7937183383991895,
37
+ "iou": 0.46300236406619383,
38
+ "support": 4935
39
+ },
40
+ "Ceiling tile": {
41
+ "accuracy": 0.7847082494969819,
42
+ "iou": 0.4701627486437613,
43
+ "support": 994
44
+ },
45
+ "Ceramic": {
46
+ "accuracy": 0.8235037134119703,
47
+ "iou": 0.5771586037966931,
48
+ "support": 2289
49
+ },
50
+ "Chalkboard/blackboard": {
51
+ "accuracy": 0.7534883720930232,
52
+ "iou": 0.552901023890785,
53
+ "support": 215
54
+ },
55
+ "Clutter": {
56
+ "accuracy": 0.4339622641509434,
57
+ "iou": 0.359375,
58
+ "support": 53
59
+ },
60
+ "Concrete": {
61
+ "accuracy": 0.5151148730350665,
62
+ "iou": 0.2623152709359606,
63
+ "support": 1654
64
+ },
65
+ "Cork/corkboard": {
66
+ "accuracy": 0.29411764705882354,
67
+ "iou": 0.18518518518518517,
68
+ "support": 51
69
+ },
70
+ "Engineered stone": {
71
+ "accuracy": 0.20224719101123595,
72
+ "iou": 0.15384615384615385,
73
+ "support": 89
74
+ },
75
+ "Fabric/cloth": {
76
+ "accuracy": 0.7728515969648844,
77
+ "iou": 0.7065537406735228,
78
+ "support": 22668
79
+ },
80
+ "Fiberglass wool": {
81
+ "accuracy": 0.3,
82
+ "iou": 0.24,
83
+ "support": 20
84
+ },
85
+ "Fire": {
86
+ "accuracy": 0.76,
87
+ "iou": 0.5757575757575758,
88
+ "support": 50
89
+ },
90
+ "Foliage": {
91
+ "accuracy": 0.8998444185141968,
92
+ "iou": 0.7700116491928773,
93
+ "support": 5142
94
+ },
95
+ "Food": {
96
+ "accuracy": 0.8614525139664805,
97
+ "iou": 0.622778675282714,
98
+ "support": 895
99
+ },
100
+ "Fur": {
101
+ "accuracy": 0.8259860788863109,
102
+ "iou": 0.6819923371647509,
103
+ "support": 431
104
+ },
105
+ "Gemstone/quartz": {
106
+ "accuracy": 0.54,
107
+ "iou": 0.1956521739130435,
108
+ "support": 50
109
+ },
110
+ "Glass": {
111
+ "accuracy": 0.7519200887902331,
112
+ "iou": 0.6554820232981152,
113
+ "support": 22525
114
+ },
115
+ "Hair": {
116
+ "accuracy": 0.975366568914956,
117
+ "iou": 0.9131091283459163,
118
+ "support": 6820
119
+ },
120
+ "I cannot tell": {
121
+ "accuracy": 0.0,
122
+ "iou": 0.0,
123
+ "support": 0
124
+ },
125
+ "Ice": {
126
+ "accuracy": 0.41818181818181815,
127
+ "iou": 0.35384615384615387,
128
+ "support": 55
129
+ },
130
+ "Leather": {
131
+ "accuracy": 0.697282099343955,
132
+ "iou": 0.4206955046649703,
133
+ "support": 2134
134
+ },
135
+ "Liquid, non-water": {
136
+ "accuracy": 0.4166666666666667,
137
+ "iou": 0.26785714285714285,
138
+ "support": 36
139
+ },
140
+ "Metal": {
141
+ "accuracy": 0.8197604132322234,
142
+ "iou": 0.5327476608813656,
143
+ "support": 9099
144
+ },
145
+ "Mirror": {
146
+ "accuracy": 0.6637390213299874,
147
+ "iou": 0.40350877192982454,
148
+ "support": 797
149
+ },
150
+ "Not on list": {
151
+ "accuracy": 0.0,
152
+ "iou": 0.0,
153
+ "support": 0
154
+ },
155
+ "Paint/plaster/enamel": {
156
+ "accuracy": 0.5977813393670847,
157
+ "iou": 0.5230278533916247,
158
+ "support": 31821
159
+ },
160
+ "Paper": {
161
+ "accuracy": 0.8264638245179551,
162
+ "iou": 0.6788724208079047,
163
+ "support": 11306
164
+ },
165
+ "Pearl": {
166
+ "accuracy": 0.0,
167
+ "iou": 0.0,
168
+ "support": 1
169
+ },
170
+ "Photograph/painting": {
171
+ "accuracy": 0.6998202516476932,
172
+ "iou": 0.36671899529042384,
173
+ "support": 1669
174
+ },
175
+ "Plastic, clear": {
176
+ "accuracy": 0.6641744548286604,
177
+ "iou": 0.42554890219560876,
178
+ "support": 1605
179
+ },
180
+ "Plastic, non-clear": {
181
+ "accuracy": 0.6261146496815286,
182
+ "iou": 0.5067590789322947,
183
+ "support": 14130
184
+ },
185
+ "Rubber/latex": {
186
+ "accuracy": 0.581547064305685,
187
+ "iou": 0.31060228969636633,
188
+ "support": 1073
189
+ },
190
+ "Sand": {
191
+ "accuracy": 0.29545454545454547,
192
+ "iou": 0.23853211009174313,
193
+ "support": 88
194
+ },
195
+ "Skin/lips": {
196
+ "accuracy": 0.9690329131060157,
197
+ "iou": 0.9340238134072745,
198
+ "support": 11819
199
+ },
200
+ "Sky": {
201
+ "accuracy": 0.9326833797585887,
202
+ "iou": 0.6621621621621622,
203
+ "support": 2154
204
+ },
205
+ "Snow": {
206
+ "accuracy": 0.6788990825688074,
207
+ "iou": 0.5211267605633803,
208
+ "support": 109
209
+ },
210
+ "Soap": {
211
+ "accuracy": 0.14285714285714285,
212
+ "iou": 0.14285714285714285,
213
+ "support": 7
214
+ },
215
+ "Soil/mud": {
216
+ "accuracy": 0.634703196347032,
217
+ "iou": 0.3926553672316384,
218
+ "support": 657
219
+ },
220
+ "Sponge": {
221
+ "accuracy": 0.1111111111111111,
222
+ "iou": 0.09090909090909091,
223
+ "support": 18
224
+ },
225
+ "Stone, natural": {
226
+ "accuracy": 0.6101556101556102,
227
+ "iou": 0.4328878558977339,
228
+ "support": 1221
229
+ },
230
+ "Stone, polished": {
231
+ "accuracy": 0.41022280471821754,
232
+ "iou": 0.25385239253852393,
233
+ "support": 763
234
+ },
235
+ "Styrofoam": {
236
+ "accuracy": 0.0,
237
+ "iou": 0.0,
238
+ "support": 31
239
+ },
240
+ "Tile": {
241
+ "accuracy": 0.6326317620455731,
242
+ "iou": 0.4346838771363691,
243
+ "support": 5749
244
+ },
245
+ "Wallpaper": {
246
+ "accuracy": 0.5758928571428571,
247
+ "iou": 0.33740191804707936,
248
+ "support": 672
249
+ },
250
+ "Water": {
251
+ "accuracy": 0.6458569807037458,
252
+ "iou": 0.5158658204895739,
253
+ "support": 881
254
+ },
255
+ "Wax": {
256
+ "accuracy": 0.8333333333333334,
257
+ "iou": 0.6129032258064516,
258
+ "support": 114
259
+ },
260
+ "Whiteboard": {
261
+ "accuracy": 0.6366366366366366,
262
+ "iou": 0.4491525423728814,
263
+ "support": 333
264
+ },
265
+ "Wicker": {
266
+ "accuracy": 0.7818181818181819,
267
+ "iou": 0.5789473684210527,
268
+ "support": 605
269
+ },
270
+ "Wood": {
271
+ "accuracy": 0.7983939413723314,
272
+ "iou": 0.6174079870752764,
273
+ "support": 15317
274
+ },
275
+ "Wood, tree": {
276
+ "accuracy": 0.717687074829932,
277
+ "iou": 0.49414519906323184,
278
+ "support": 588
279
+ },
280
+ "Bad polygon": {
281
+ "accuracy": 0.0,
282
+ "iou": 0.0,
283
+ "support": 0
284
+ },
285
+ "Multiple materials": {
286
+ "accuracy": 0.0,
287
+ "iou": 0.0,
288
+ "support": 0
289
+ },
290
+ "Asphalt": {
291
+ "accuracy": 0.4797979797979798,
292
+ "iou": 0.296875,
293
+ "support": 198
294
+ }
295
+ }
296
+ }
DMS/dinov3_siglip2_lmf_reg/model.pth ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:fcbfcb811c95b16bba82f2765cc37aeb0861ea6067e559a36c605bfdc24f1ba0
3
+ size 7701584
DMS/dinov3_siglip2_lmf_reg/model.safetensors ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:ed2fc3b7ee4dd92b575b199ea2770e3a0e0d702355dfe5f97216e50917c68cab
3
+ size 7695412
DMS/dinov3_siglip2_lmf_reg/split.json ADDED
The diff for this file is too large to render. See raw diff
 
DMS/dinov3_siglip2_mlp/README.md ADDED
@@ -0,0 +1,52 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # DINOv3-SigLIP2 + Concat + MLP on Apple Dense Material Segmentation
2
+
3
+ A material-classification **fusion head** from SegObjectMaterial. It classifies the
4
+ material of a masked object from two frozen embeddings:
5
+
6
+ | | |
7
+ |---|---|
8
+ | vision | DINOv3 ViT-L/16 (CLS token, frozen) -> 1024-d |
9
+ | language | SigLIP2 base text encoder over Qwen3-VL-8B captions (frozen) -> 768-d |
10
+ | head | Concat + MLP (`mlp`, defaults), 1,065,529 parameters |
11
+ | classes | 57 (Apple Dense Material Segmentation) |
12
+
13
+ **This repo holds only the head.** Features must come from the same encoders,
14
+ captioner and prompts as training (see the SegObjectMaterial repository); the
15
+ encoders are downloaded from their own model pages under their own licenses.
16
+
17
+ ## Evaluation
18
+
19
+ Held-out split recorded in `split.json` (source images never seen in training).
20
+ Single training run -- differences under ~0.5 mIoU points between heads are within
21
+ run-to-run noise.
22
+
23
+ | mIoU | mAcc | eval samples |
24
+ |---|---|---|
25
+ | 0.4592 | 0.6453 | 186,231 |
26
+
27
+ ## Training
28
+
29
+ ```json
30
+ {
31
+ "learning_rate": 5e-05,
32
+ "epochs": 50,
33
+ "batch_size": 32,
34
+ "weight_decay": 0.0001,
35
+ "lr_schedule": "constant",
36
+ "early_stopping_patience": 0,
37
+ "checkpoint": "best validation loss"
38
+ }
39
+ ```
40
+
41
+ ## Use
42
+
43
+ ```python
44
+ from utils.hub import load_head_from_hub # SegObjectMaterial repository
45
+ head, info = load_head_from_hub("s0um0r0y/SegObjectMaterial", "DMS/dinov3_siglip2_mlp")
46
+ logits = head(vision_features, language_features) # [B, 1024], [B, 768]
47
+ ```
48
+
49
+ ## Integrity
50
+
51
+ - `model.safetensors` sha256 `24b04b492f455d44e9ee3dc13c98bade94181ec60d0ce7363c6e3ff0e9996341`
52
+ - source config `config/config_latest_models_mlp.toml`, code commit `1a8130c922267fb0786a33e3854a7e00763cc38f+dirty`
DMS/dinov3_siglip2_mlp/config.toml ADDED
@@ -0,0 +1,64 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # MLP-head twin of config/config.toml.
2
+ # SAME embedding cache -- the head type does not change the cached features, so
3
+ # nothing needs re-serializing. Only the checkpoint, TensorBoard dir and W&B run
4
+ # differ, so this run can never overwrite the gated checkpoint.
5
+
6
+ # Apple DMS -- LATEST-MODELS pipeline: DINOv3 ViT-L/16 (1024) + Qwen3-VL -> SigLIP2 text (768)
7
+ #
8
+ # Pair this with:
9
+ # src/vision_stream_latest_models.py + src/language_stream_latest_models.py
10
+ # run_serialization_latest_models.py -> train_latest_models.py
11
+ #
12
+ # For the base DINOv2/CLIP pipeline (run_serialization.py -> train.py) use
13
+ # config/config_dinov2_clip.toml instead -- its vision_dim is 768, not 1024.
14
+
15
+ [data]
16
+ dataset_type = "apple_dms"
17
+ image_dir = "<local>/images"
18
+ mask_dir = "<local>/labels"
19
+ # Rebuilt automatically on first run; the index now stores one entry per
20
+ # CONNECTED COMPONENT, so any pre-existing labels.json must be removed first.
21
+ labels_file = "<local>/labels_instances.json"
22
+ # Separate cache: DINOv3 features are 1024-d and must not mix with the
23
+ # 768-d DINOv2 cache written by run_serialization.py.
24
+ tensor_cache_dir = "<local>/tensor_cache_dir_latest_models"
25
+
26
+ # Connected-component filtering (measured on 400 real DMS masks):
27
+ # keeping every component gives 7.5x more samples than the old per-(image,class)
28
+ # scheme -- 2.45M samples / 47 GB / ~7.5x the VLM captioning time -- because 69%
29
+ # of components are under 0.1% of the frame and crop to a few pixels.
30
+ # A component is kept when area >= max(min_instance_area, min_instance_frac * frame).
31
+ min_instance_area = 1000 # absolute pixel floor
32
+ min_instance_frac = 0.001 # and at least 0.1% of the frame
33
+ max_instances_per_class = 0 # 0 = keep all; set e.g. 3 to cap the long tail
34
+
35
+
36
+ [model]
37
+ # fusion head: "gated" (GMU) or "mlp" (concat+MLP). Read by train_latest_models.py; a contradicting --fusion flag is an error, so checkpoint_path can't hold the wrong head.
38
+ fusion = "mlp"
39
+ vision_dim = 1024 # DINOv3 ViT-L/16 CLS token
40
+ language_dim = 768 # SigLIP2 base text embedding
41
+ num_classes = 57
42
+
43
+ [training]
44
+ batch_size = 32
45
+
46
+ # Batch size for the OFFLINE SERIALIZATION pass, which is a completely different
47
+ # memory regime from training: it pushes full-resolution images through the 7B
48
+ # VLM, whereas [training].batch_size only moves cached 768-d vectors through a
49
+ # small MLP. Measured on the 23.6 GiB 4090 -- static weights 16.2 GiB, so only
50
+ # ~7.4 GiB is left: batch 8 peaks at 17.7 GiB, 16 at 19.2 GiB, and 32 OOMs.
51
+ # 8 leaves headroom for a labmate's job to coexist; raise to 16 on a free card.
52
+ serialization_batch_size = 8
53
+ learning_rate = 5e-5
54
+ epochs = 50
55
+ train_ratio = 0.8 # 80% for training
56
+ val_ratio = 0.2 # 20% for validation
57
+ tensorboard_log_dir = "<local>/dms_dinov3_siglip2_mlp"
58
+
59
+ [inference]
60
+ checkpoint_path = "<local>/best_model_dms_latest_mlp.pth"
61
+
62
+ [logging]
63
+ wandb_project = "material-classification"
64
+ wandb_run_name = "dms-dinov3-siglip2-mlp"
DMS/dinov3_siglip2_mlp/head.json ADDED
@@ -0,0 +1,99 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "fusion": "mlp",
3
+ "head": "Concat + MLP",
4
+ "head_kwargs": {},
5
+ "vision_dim": 1024,
6
+ "language_dim": 768,
7
+ "num_classes": 57,
8
+ "classes": [
9
+ "No label",
10
+ "Animal skin",
11
+ "Bone/teeth/horn",
12
+ "Brickwork",
13
+ "Cardboard",
14
+ "Carpet/rug",
15
+ "Ceiling tile",
16
+ "Ceramic",
17
+ "Chalkboard/blackboard",
18
+ "Clutter",
19
+ "Concrete",
20
+ "Cork/corkboard",
21
+ "Engineered stone",
22
+ "Fabric/cloth",
23
+ "Fiberglass wool",
24
+ "Fire",
25
+ "Foliage",
26
+ "Food",
27
+ "Fur",
28
+ "Gemstone/quartz",
29
+ "Glass",
30
+ "Hair",
31
+ "I cannot tell",
32
+ "Ice",
33
+ "Leather",
34
+ "Liquid, non-water",
35
+ "Metal",
36
+ "Mirror",
37
+ "Not on list",
38
+ "Paint/plaster/enamel",
39
+ "Paper",
40
+ "Pearl",
41
+ "Photograph/painting",
42
+ "Plastic, clear",
43
+ "Plastic, non-clear",
44
+ "Rubber/latex",
45
+ "Sand",
46
+ "Skin/lips",
47
+ "Sky",
48
+ "Snow",
49
+ "Soap",
50
+ "Soil/mud",
51
+ "Sponge",
52
+ "Stone, natural",
53
+ "Stone, polished",
54
+ "Styrofoam",
55
+ "Tile",
56
+ "Wallpaper",
57
+ "Water",
58
+ "Wax",
59
+ "Whiteboard",
60
+ "Wicker",
61
+ "Wood",
62
+ "Wood, tree",
63
+ "Bad polygon",
64
+ "Multiple materials",
65
+ "Asphalt"
66
+ ],
67
+ "dataset": "Apple Dense Material Segmentation",
68
+ "dataset_key": "DMS",
69
+ "encoders": {
70
+ "vision": "DINOv3 ViT-L/16 (CLS token, frozen)",
71
+ "language": "SigLIP2 base text encoder over Qwen3-VL-8B captions (frozen)",
72
+ "short": "DINOv3-SigLIP2",
73
+ "slug": "dinov3_siglip2"
74
+ },
75
+ "parameters": 1065529,
76
+ "training": {
77
+ "learning_rate": 5e-05,
78
+ "epochs": 50,
79
+ "batch_size": 32,
80
+ "weight_decay": 0.0001,
81
+ "lr_schedule": "constant",
82
+ "early_stopping_patience": 0,
83
+ "checkpoint": "best validation loss"
84
+ },
85
+ "sha256": {
86
+ "safetensors": "24b04b492f455d44e9ee3dc13c98bade94181ec60d0ce7363c6e3ff0e9996341",
87
+ "pth": "025001457a82b8db2365a08e3691fc9dd6594978b8c8467deb6bbefe77bfdda5"
88
+ },
89
+ "source": {
90
+ "config": "config/config_latest_models_mlp.toml",
91
+ "git_commit": "1a8130c922267fb0786a33e3854a7e00763cc38f+dirty",
92
+ "checkpoint_mtime": "2026-10-05T17:16:25"
93
+ },
94
+ "metrics": {
95
+ "mIoU": 0.45922884101465977,
96
+ "mAcc": 0.6453263039159061,
97
+ "eval_samples": 186231
98
+ }
99
+ }
DMS/dinov3_siglip2_mlp/metrics.json ADDED
@@ -0,0 +1,296 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "dataset": "DMS",
3
+ "checkpoint": "<local>/best_model_dms_latest_mlp.pth",
4
+ "fusion_type": "mlp",
5
+ "num_eval_samples": 186231,
6
+ "mIoU": 0.45922884101465977,
7
+ "mAcc": 0.6453263039159061,
8
+ "per_class": {
9
+ "No label": {
10
+ "accuracy": 0.0,
11
+ "iou": 0.0,
12
+ "support": 0
13
+ },
14
+ "Animal skin": {
15
+ "accuracy": 0.6228070175438597,
16
+ "iou": 0.4303030303030303,
17
+ "support": 114
18
+ },
19
+ "Bone/teeth/horn": {
20
+ "accuracy": 0.7272727272727273,
21
+ "iou": 0.6153846153846154,
22
+ "support": 44
23
+ },
24
+ "Brickwork": {
25
+ "accuracy": 0.743521000893655,
26
+ "iou": 0.5187032418952618,
27
+ "support": 1119
28
+ },
29
+ "Cardboard": {
30
+ "accuracy": 0.7536656891495601,
31
+ "iou": 0.47155963302752296,
32
+ "support": 1023
33
+ },
34
+ "Carpet/rug": {
35
+ "accuracy": 0.8107396149949342,
36
+ "iou": 0.46921543332942417,
37
+ "support": 4935
38
+ },
39
+ "Ceiling tile": {
40
+ "accuracy": 0.8038229376257545,
41
+ "iou": 0.4615829000577701,
42
+ "support": 994
43
+ },
44
+ "Ceramic": {
45
+ "accuracy": 0.8287461773700305,
46
+ "iou": 0.613915857605178,
47
+ "support": 2289
48
+ },
49
+ "Chalkboard/blackboard": {
50
+ "accuracy": 0.7348837209302326,
51
+ "iou": 0.5683453237410072,
52
+ "support": 215
53
+ },
54
+ "Clutter": {
55
+ "accuracy": 0.49056603773584906,
56
+ "iou": 0.3291139240506329,
57
+ "support": 53
58
+ },
59
+ "Concrete": {
60
+ "accuracy": 0.5108827085852479,
61
+ "iou": 0.2779605263157895,
62
+ "support": 1654
63
+ },
64
+ "Cork/corkboard": {
65
+ "accuracy": 0.3333333333333333,
66
+ "iou": 0.2236842105263158,
67
+ "support": 51
68
+ },
69
+ "Engineered stone": {
70
+ "accuracy": 0.20224719101123595,
71
+ "iou": 0.11612903225806452,
72
+ "support": 89
73
+ },
74
+ "Fabric/cloth": {
75
+ "accuracy": 0.7791159343568025,
76
+ "iou": 0.7166741062370653,
77
+ "support": 22668
78
+ },
79
+ "Fiberglass wool": {
80
+ "accuracy": 0.3,
81
+ "iou": 0.17647058823529413,
82
+ "support": 20
83
+ },
84
+ "Fire": {
85
+ "accuracy": 0.86,
86
+ "iou": 0.5657894736842105,
87
+ "support": 50
88
+ },
89
+ "Foliage": {
90
+ "accuracy": 0.91170750680669,
91
+ "iou": 0.7855227882037533,
92
+ "support": 5142
93
+ },
94
+ "Food": {
95
+ "accuracy": 0.8782122905027933,
96
+ "iou": 0.6374695863746959,
97
+ "support": 895
98
+ },
99
+ "Fur": {
100
+ "accuracy": 0.8283062645011601,
101
+ "iou": 0.697265625,
102
+ "support": 431
103
+ },
104
+ "Gemstone/quartz": {
105
+ "accuracy": 0.66,
106
+ "iou": 0.23741007194244604,
107
+ "support": 50
108
+ },
109
+ "Glass": {
110
+ "accuracy": 0.7552497225305217,
111
+ "iou": 0.6632617256033374,
112
+ "support": 22525
113
+ },
114
+ "Hair": {
115
+ "accuracy": 0.976099706744868,
116
+ "iou": 0.9226611226611227,
117
+ "support": 6820
118
+ },
119
+ "I cannot tell": {
120
+ "accuracy": 0.0,
121
+ "iou": 0.0,
122
+ "support": 0
123
+ },
124
+ "Ice": {
125
+ "accuracy": 0.5818181818181818,
126
+ "iou": 0.47058823529411764,
127
+ "support": 55
128
+ },
129
+ "Leather": {
130
+ "accuracy": 0.7282099343955014,
131
+ "iou": 0.4223973905952704,
132
+ "support": 2134
133
+ },
134
+ "Liquid, non-water": {
135
+ "accuracy": 0.4444444444444444,
136
+ "iou": 0.2857142857142857,
137
+ "support": 36
138
+ },
139
+ "Metal": {
140
+ "accuracy": 0.8286624903835587,
141
+ "iou": 0.5417445035206208,
142
+ "support": 9099
143
+ },
144
+ "Mirror": {
145
+ "accuracy": 0.6976160602258469,
146
+ "iou": 0.40942562592047127,
147
+ "support": 797
148
+ },
149
+ "Not on list": {
150
+ "accuracy": 0.0,
151
+ "iou": 0.0,
152
+ "support": 0
153
+ },
154
+ "Paint/plaster/enamel": {
155
+ "accuracy": 0.5956443857829735,
156
+ "iou": 0.5289685197588747,
157
+ "support": 31821
158
+ },
159
+ "Paper": {
160
+ "accuracy": 0.8389350787192641,
161
+ "iou": 0.6866719756750886,
162
+ "support": 11306
163
+ },
164
+ "Pearl": {
165
+ "accuracy": 0.0,
166
+ "iou": 0.0,
167
+ "support": 1
168
+ },
169
+ "Photograph/painting": {
170
+ "accuracy": 0.7231875374475734,
171
+ "iou": 0.37542768273716953,
172
+ "support": 1669
173
+ },
174
+ "Plastic, clear": {
175
+ "accuracy": 0.6890965732087228,
176
+ "iou": 0.41925701288855194,
177
+ "support": 1605
178
+ },
179
+ "Plastic, non-clear": {
180
+ "accuracy": 0.6375796178343949,
181
+ "iou": 0.5135088919288646,
182
+ "support": 14130
183
+ },
184
+ "Rubber/latex": {
185
+ "accuracy": 0.625349487418453,
186
+ "iou": 0.330704780680138,
187
+ "support": 1073
188
+ },
189
+ "Sand": {
190
+ "accuracy": 0.3181818181818182,
191
+ "iou": 0.24561403508771928,
192
+ "support": 88
193
+ },
194
+ "Skin/lips": {
195
+ "accuracy": 0.978847618241814,
196
+ "iou": 0.9362304766529093,
197
+ "support": 11819
198
+ },
199
+ "Sky": {
200
+ "accuracy": 0.9220055710306406,
201
+ "iou": 0.6768916155419223,
202
+ "support": 2154
203
+ },
204
+ "Snow": {
205
+ "accuracy": 0.6972477064220184,
206
+ "iou": 0.4342857142857143,
207
+ "support": 109
208
+ },
209
+ "Soap": {
210
+ "accuracy": 0.14285714285714285,
211
+ "iou": 0.14285714285714285,
212
+ "support": 7
213
+ },
214
+ "Soil/mud": {
215
+ "accuracy": 0.6636225266362252,
216
+ "iou": 0.40671641791044777,
217
+ "support": 657
218
+ },
219
+ "Sponge": {
220
+ "accuracy": 0.3888888888888889,
221
+ "iou": 0.2916666666666667,
222
+ "support": 18
223
+ },
224
+ "Stone, natural": {
225
+ "accuracy": 0.6445536445536445,
226
+ "iou": 0.44040290990486847,
227
+ "support": 1221
228
+ },
229
+ "Stone, polished": {
230
+ "accuracy": 0.4167758846657929,
231
+ "iou": 0.2550120288692863,
232
+ "support": 763
233
+ },
234
+ "Styrofoam": {
235
+ "accuracy": 0.16129032258064516,
236
+ "iou": 0.1111111111111111,
237
+ "support": 31
238
+ },
239
+ "Tile": {
240
+ "accuracy": 0.6460253957209949,
241
+ "iou": 0.43668430335097,
242
+ "support": 5749
243
+ },
244
+ "Wallpaper": {
245
+ "accuracy": 0.5967261904761905,
246
+ "iou": 0.348695652173913,
247
+ "support": 672
248
+ },
249
+ "Water": {
250
+ "accuracy": 0.6730987514188422,
251
+ "iou": 0.5188101487314086,
252
+ "support": 881
253
+ },
254
+ "Wax": {
255
+ "accuracy": 0.8771929824561403,
256
+ "iou": 0.6535947712418301,
257
+ "support": 114
258
+ },
259
+ "Whiteboard": {
260
+ "accuracy": 0.6906906906906907,
261
+ "iou": 0.4536489151873767,
262
+ "support": 333
263
+ },
264
+ "Wicker": {
265
+ "accuracy": 0.8132231404958677,
266
+ "iou": 0.5934861278648975,
267
+ "support": 605
268
+ },
269
+ "Wood": {
270
+ "accuracy": 0.7876215969184566,
271
+ "iou": 0.6349807884625507,
272
+ "support": 15317
273
+ },
274
+ "Wood, tree": {
275
+ "accuracy": 0.7363945578231292,
276
+ "iou": 0.4959908361970218,
277
+ "support": 588
278
+ },
279
+ "Bad polygon": {
280
+ "accuracy": 0.0,
281
+ "iou": 0.0,
282
+ "support": 0
283
+ },
284
+ "Multiple materials": {
285
+ "accuracy": 0.0,
286
+ "iou": 0.0,
287
+ "support": 0
288
+ },
289
+ "Asphalt": {
290
+ "accuracy": 0.5,
291
+ "iou": 0.32038834951456313,
292
+ "support": 198
293
+ }
294
+ },
295
+ "config": "config/config_latest_models_mlp.toml"
296
+ }
DMS/dinov3_siglip2_mlp/model.pth ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:025001457a82b8db2365a08e3691fc9dd6594978b8c8467deb6bbefe77bfdda5
3
+ size 4274254
DMS/dinov3_siglip2_mlp/model.safetensors ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:24b04b492f455d44e9ee3dc13c98bade94181ec60d0ce7363c6e3ff0e9996341
3
+ size 4269548
DMS/dinov3_siglip2_mlp/split.json ADDED
The diff for this file is too large to render. See raw diff
 
FMD/dinov2_clip_gated/README.md ADDED
@@ -0,0 +1,52 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # DINOv2-CLIP + Gated Multimodal Unit on Flickr Material Database
2
+
3
+ A material-classification **fusion head** from SegObjectMaterial. It classifies the
4
+ material of a masked object from two frozen embeddings:
5
+
6
+ | | |
7
+ |---|---|
8
+ | vision | DINOv2 ViT-B/14 (CLS token, frozen) -> 768-d |
9
+ | language | CLIP ViT-L/14 text encoder over Qwen2.5-VL-7B captions (frozen) -> 768-d |
10
+ | head | Gated Multimodal Unit (`gated`, defaults), 1,710,858 parameters |
11
+ | classes | 10 (Flickr Material Database) |
12
+
13
+ **This repo holds only the head.** Features must come from the same encoders,
14
+ captioner and prompts as training (see the SegObjectMaterial repository); the
15
+ encoders are downloaded from their own model pages under their own licenses.
16
+
17
+ ## Evaluation
18
+
19
+ Held-out split recorded in `split.json` (source images never seen in training).
20
+ Single training run -- differences under ~0.5 mIoU points between heads are within
21
+ run-to-run noise.
22
+
23
+ | mIoU | mAcc | eval samples |
24
+ |---|---|---|
25
+ | 0.9234 | 0.9599 | 200 |
26
+
27
+ ## Training
28
+
29
+ ```json
30
+ {
31
+ "learning_rate": 5e-05,
32
+ "epochs": 50,
33
+ "batch_size": 8,
34
+ "weight_decay": 0.0001,
35
+ "lr_schedule": "constant",
36
+ "early_stopping_patience": 0,
37
+ "checkpoint": "best validation loss"
38
+ }
39
+ ```
40
+
41
+ ## Use
42
+
43
+ ```python
44
+ from utils.hub import load_head_from_hub # SegObjectMaterial repository
45
+ head, info = load_head_from_hub("s0um0r0y/SegObjectMaterial", "FMD/dinov2_clip_gated")
46
+ logits = head(vision_features, language_features) # [B, 768], [B, 768]
47
+ ```
48
+
49
+ ## Integrity
50
+
51
+ - `model.safetensors` sha256 `de0b96447b176c5791b4cda3b6121e852bf488943c1a7d6fe5c93aef923fe129`
52
+ - source config `config/fmd_config.toml`, code commit `1a8130c922267fb0786a33e3854a7e00763cc38f+dirty`