grgngl commited on
Commit
0772aa4
Β·
verified Β·
1 Parent(s): de6d18f

Upload README.md with huggingface_hub

Browse files
Files changed (1) hide show
  1. README.md +188 -0
README.md ADDED
@@ -0,0 +1,188 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ---
2
+ license: mit
3
+ pipeline_tag: image-segmentation
4
+ tags:
5
+ - vesuvius
6
+ - herculaneum
7
+ - fibers
8
+ - ink-detection
9
+ - computed-tomography
10
+ - 3d-segmentation
11
+ - self-distillation
12
+ - self-supervised
13
+ - volumetric-imaging
14
+ ---
15
+
16
+ # PHerc. Paris 4 β€” 4-class fiber/ink segmentation, self-distilled (step 29000)
17
+
18
+ Segments **background / vertical fiber / horizontal-angular fiber / ink** β€” 4
19
+ classes, in 3D, directly in micro-CT of **PHerc. Paris 4** β€” trained with **no
20
+ fixed ground truth** via self-distillation from two frozen teacher UNets. This
21
+ is villa's [`scripts/fiber_5class`](https://github.com/ScrollPrize/villa/tree/main/scripts/fiber_5class)
22
+ pipeline (PR [#985](https://github.com/ScrollPrize/villa/pull/985)), and this
23
+ checkpoint is confirmed (via direct inspection of its embedded training config,
24
+ which matches its W&B run exactly) to be the real, finished model that
25
+ pipeline produced.
26
+
27
+ **This model's own training pipeline does not use DINO at all** β€” it is pure
28
+ two-teacher self-distillation (see below). DINO only appears earlier/elsewhere
29
+ in this broader fiber-modeling effort, in a separate checkpoint that may feed
30
+ this run's fiber teacher input β€” see **Related models**.
31
+
32
+ ![debug figure](images/p4_4class_36pykwky_debug_figure_step29899.png)
33
+
34
+ *Training-time debug visualization from this run at step 29899 (image slice,
35
+ teacher probability maps, watershed instances, student prediction). Logged to
36
+ W&B, not an independent evaluation.*
37
+
38
+ ## Model details
39
+
40
+ | | |
41
+ |---|---|
42
+ | Architecture | `vesuvius` `NetworkFromConfig` 3D UNet (`shared_encoder`/`shared_decoder`/`task_heads`) β€” verified directly from the checkpoint: 544 encoder tensors, 60 decoder tensors, single head |
43
+ | Output | **4 channels**, softmax, head named `task_heads.labels` β€” verified shape `(4, 32, 1, 1, 1)` |
44
+ | Classes | `0` background Β· `1` vertical fiber Β· `2` horizontal/angular fiber Β· `3` ink |
45
+ | Input | 1-channel CT, 256Β³ patches |
46
+ | This checkpoint | step **29000** of a 30000-step schedule Β· W&B run [`p4_4class_ddp8_20260526`](https://wandb.ai/vesuvius-challenge/paris4-full-features/runs/36pykwky) (`36pykwky`, project `paris4-full-features`, state **finished**) |
47
+ | Weights | `model` (raw) and `ema` (**EMA β€” recommended for inference**, decay 0.9995) |
48
+ | Optimisation | SGD + Nesterov (lr 0.005, momentum 0.99, weight_decay 3e-5), cosine LR, 2000-step warmup, bf16, CE + multiclass soft Dice (0.1 label smoothing each, Dice over foreground classes only), batch size 2 Γ— 8 GPUs (`ddp8`) |
49
+ | Trained on | PHerc. Paris 4, 2.4 Β΅m scan (`s3://vesuvius-challenge-open-data/PHercParis4/volumes/20260411134726-2.400um-0.2m-78keV-masked.zarr/`) |
50
+
51
+ We verified this checkpoint directly (`torch.load(..., weights_only=False)`):
52
+ its embedded `config.wandb_run_name` is `p4_4class_ddp8_20260526`, its
53
+ `config.out_dir` is `/ephemeral/fiber_5class_ckpts/p4_4class_ddp8_20260526` β€”
54
+ both matching the W&B run's own recorded config exactly, and `step=29000`
55
+ matches the file's provenance exactly. `save_every=1000` with
56
+ `num_iterations=30000` means step 29000 is mathematically the **last**
57
+ checkpoint this run could have saved (the loop exits at step 30000 before
58
+ another save triggers) β€” this is the final checkpoint of a finished run, not
59
+ an arbitrary snapshot.
60
+
61
+ This run was reached after two earlier attempts under the same name failed
62
+ (`5ga68dxv`) or crashed (`q8jmzbiv`), and after an even earlier, broader
63
+ experiment line tagged `5class`/`fiber-ink-papyrus` (`out_channels=5`, adding a
64
+ "papyrus" class) was simplified down to the 4-class scheme published here.
65
+
66
+ ## Training procedure: two-teacher self-distillation (verified against source)
67
+
68
+ Read directly from `label_generator.py` (`FiveClassLabelGenerator`) and
69
+ `train.py` in PR #985 β€” this is a from-source description, not an inference
70
+ from config field names:
71
+
72
+ 1. `fiber_prob = sigmoid(fiber_teacher(image))`, `ink_prob = sigmoid(ink_teacher(image))` β€” two independent frozen teacher UNets, FG channel only.
73
+ 2. `fiber_mask = fiber_prob > fiber_thr` (0.5).
74
+ 3. GPU watershed-from-minima (`cuws`) on the distance transform of `fiber_mask` (`ws_image_mode="distance"`, `ws_h_merge=14000`) β†’ per-instance fiber segmentation.
75
+ 4. **Per-instance PCA** on each instance's ZYX voxel coordinates: `|principal_axis Β· αΊ‘| > pca_cos_threshold` (0.819 = cos 35Β°) β†’ class **1** (vertical), else class **2** (horizontal/angular). Instances below `ws_min_voxels` (400) default to class 2 rather than being dropped.
76
+ 5. **Ink overrides fiber:** `label[ink_prob > ink_thr] = 3` (`ink_thr=0.1`) β€” applied after the fiber/orientation assignment, so ink always wins where the ink teacher is confident.
77
+ 6. **Dark-voxel guard (final step):** `label[raw < dark_voxel_thr] = 0` (`dark_voxel_thr=90`) β€” forces very dark/air voxels to background regardless of any earlier assignment.
78
+
79
+ Loss = cross-entropy (label smoothing 0.1) + multiclass soft Dice (smoothing
80
+ 0.1, foreground classes only). A fresh pseudo-label is generated from the two
81
+ frozen teachers **every step** β€” there is no fixed/static label set at any
82
+ point in training.
83
+
84
+ The two teacher checkpoints for this run were configured as
85
+ `/ephemeral/fiber_5class_inputs/fiber_teacher.pth` and `ink_teacher.pth` β€”
86
+ generic on-disk names that don't self-identify their origin. Per the identical
87
+ `scripts/fiber_5class/train.py` module docstring, the fiber teacher is
88
+ documented as "ihoo3tpl ckpt", i.e. very likely
89
+ [`scrollprize/fiber_dinoguided_2class_step010000`](https://huggingface.co/scrollprize/fiber_dinoguided_2class_step010000)
90
+ (not proven byte-identical β€” it was copied/renamed on the training box). The
91
+ ink teacher is a separate checkpoint we never had; it no longer exists on the
92
+ original training instance and was not found anywhere else we checked, so we
93
+ are treating it **as unrecoverable** and are not able to publish it.
94
+
95
+ ## Metrics
96
+
97
+ Final logged values at step 29999 (run marked **finished**; checkpoint
98
+ published here is step 29000, the last one actually saved):
99
+
100
+ | metric | value |
101
+ |---|---|
102
+ | `loss` (ce + dice) | 1.0055 |
103
+ | `loss_ce` | 0.4513 |
104
+ | `loss_dice` | 0.5542 |
105
+ | `metrics/dice_0_bg` | 0.961 |
106
+ | `metrics/dice_1_vert_fiber` | 0.673 |
107
+ | `metrics/dice_2_horiz_fiber` | 0.705 |
108
+ | `metrics/dice_3_ink` | 0.791 |
109
+ | `metrics/dice_fg_mean` | 0.723 |
110
+ | `pseudo/frac_bg` / `frac_vert` / `frac_horiz` / `frac_ink` | 0.845 / 0.026 / 0.080 / 0.049 |
111
+ | `pseudo/n_instances_mean` | 27.5 |
112
+ | `pseudo/n_vert_mean` | 9 |
113
+
114
+ **Important:** the per-class Dice above is **student-vs-its-own-pseudo-label
115
+ self-consistency**, recomputed each `val_every` steps by re-forwarding the
116
+ student on a clean (non-augmented) training crop and comparing to that crop's
117
+ pseudo-label β€” confirmed directly from `train.py`'s logging code. It is **not**
118
+ accuracy against independent, human-verified ground truth (none exists for
119
+ this pipeline). Treat these numbers as a training-health signal, not a
120
+ benchmark score.
121
+
122
+ ![debug mask](images/p4_4class_36pykwky_debug_mask_step29899.png)
123
+
124
+ *Categorical mask visualization (pseudo-label vs. student prediction) from the
125
+ same step, with the fixed class palette used throughout this pipeline.*
126
+
127
+ ## Relationship to other fiber-effort models β€” please read before conflating pipelines
128
+
129
+ This is the only one of the four related repos published so far whose own
130
+ training loop is DINO-free. The others are separate, earlier, or upstream
131
+ components of the same broader effort:
132
+
133
+ - **[`scrollprize/fiber_dinoguided_2class_step010000`](https://huggingface.co/scrollprize/fiber_dinoguided_2class_step010000)** β€” 2-class (background/fiber) DINO-embedding-guided self-training checkpoint, very likely (not proven byte-identical) the `fiber_teacher` input consumed by this run. Trains completely differently (Otsu + DINO-similarity dynamic pseudo-labels, no watershed, no PCA, no ink).
134
+ - **[`scrollprize/dinovol_v2_ps8_supcon3class_step362500`](https://huggingface.co/scrollprize/dinovol_v2_ps8_supcon3class_step362500)** and **[`scrollprize/fiber_selftrain_teacher_epoch30`](https://huggingface.co/scrollprize/fiber_selftrain_teacher_epoch30)** β€” further upstream still (inputs to producing this run's likely fiber-teacher checkpoint, not direct inputs to this run itself).
135
+ - **[`scrollprize/fiber_hz_vt`](https://huggingface.co/scrollprize/fiber_hz_vt)** β€” an independent, supervised, real-annotation-trained 2-class horizontal/vertical model (villa PR [#825](https://github.com/ScrollPrize/villa/pull/825)). Different pipeline, different training data (WebKnossos skeleton traces vs. self-distillation), not directly comparable.
136
+
137
+ ## Files
138
+
139
+ | File | Size | Role |
140
+ |---|---|---|
141
+ | `p4_4class_ddp8_20260526_step029000.pth` | ~2.1 GB | `model` (raw) + `ema.model_state` (recommended for inference) + `optimizer` + embedded `config`. |
142
+ | `images/p4_4class_36pykwky_debug_figure_step29899.png` | β€” | Training-time debug figure (illustrative only), from this run's W&B logs. |
143
+ | `images/p4_4class_36pykwky_debug_mask_step29899.png` | β€” | Training-time categorical mask visualization (illustrative only), from this run's W&B logs. |
144
+
145
+ ## Usage
146
+
147
+ ```python
148
+ import torch
149
+ from huggingface_hub import hf_hub_download
150
+
151
+ path = hf_hub_download(
152
+ "scrollprize/fiber_ink_4class_selfdistill",
153
+ "p4_4class_ddp8_20260526_step029000.pth",
154
+ )
155
+ ckpt = torch.load(path, map_location="cpu", weights_only=False)
156
+ state = ckpt["ema"]["model_state"] # recommended over ckpt["model"]
157
+ # Build with vesuvius' NetworkFromConfig (target "labels", out_channels=4,
158
+ # in_channels=1, patch_size 256^3) then load_state_dict(state).
159
+ ```
160
+ The `vesuvius` package and the full training pipeline are in
161
+ <https://github.com/ScrollPrize/villa> (`scripts/fiber_5class/`).
162
+
163
+ ## Links
164
+
165
+ - **Code:** <https://github.com/ScrollPrize/villa> β€” PR [#985](https://github.com/ScrollPrize/villa/pull/985) (`scripts/fiber_5class`, this model's exact training code) Β· PR [#825](https://github.com/ScrollPrize/villa/pull/825) (related cross-frame affine infra, separate pipeline)
166
+ - **W&B run:** <https://wandb.ai/vesuvius-challenge/paris4-full-features/runs/36pykwky>
167
+ - **Data:** <https://scrollprize.org/data_browser>
168
+ - **Vesuvius Challenge:** <https://scrollprize.org>
169
+
170
+ ## Caveats
171
+
172
+ - Metrics are self-consistency (student vs. its own pseudo-label), not
173
+ held-out validation against independent ground truth β€” there is none in
174
+ this pipeline.
175
+ - The ink teacher checkpoint used to train this model is not published here
176
+ and is believed unrecoverable (no longer present on the original training
177
+ instance; not found elsewhere in our search).
178
+ - The fiber teacher checkpoint used to train this model is very likely
179
+ [`scrollprize/fiber_dinoguided_2class_step010000`](https://huggingface.co/scrollprize/fiber_dinoguided_2class_step010000)
180
+ based on matching documentation in the training source, but this was not
181
+ proven byte-identical (it was renamed to a generic filename on the training
182
+ box before this run consumed it).
183
+ - Trained on a single scroll (PHerc. Paris 4); generalization to other scrolls
184
+ is untested by us.
185
+
186
+ ## License
187
+
188
+ MIT.