tidy up dnn-roi description; add .json for l1sp
Browse files- dnn-roi/pdhd/20260615/README.md +0 -120
- dnn-roi/pdhd/20260615/README.pipe_distill_transformer_6ch.md +0 -65
- dnn-roi/pdhd/20260615/pipe_distill_transformer_6ch.md +123 -0
- dnn-roi/pdvd/20260615/README.md +0 -214
- dnn-roi/pdvd/20260615/README.pipe_distill_transformer_6ch.md +0 -58
- dnn-roi/pdvd/20260615/pipe_distill_transformer_6ch.md +157 -0
- l1sp/pdhd/20260615/l1sp_dnn_pdhd_v1.meta.json +112 -0
- l1sp/pdvd/20260615/l1sp_dnn_pdvd_v1.meta.json +112 -0
dnn-roi/pdhd/20260615/README.md
DELETED
|
@@ -1,120 +0,0 @@
|
|
| 1 |
-
# PDHD DNN-ROI TorchScript models
|
| 2 |
-
|
| 3 |
-
TorchScript (`.ts`) models loaded by the wire-cell-toolkit DNN-ROI nodes
|
| 4 |
-
(`DNNROIFinding` / `DNNROIFindingMultiPlane`). All are exported with
|
| 5 |
-
`DNN_ROI_SP/scripts/to_torchscript.py` and output `sigmoid` probabilities
|
| 6 |
-
in `[0, 1]` (no extra sigmoid needed in Wire-Cell).
|
| 7 |
-
|
| 8 |
-
| file | input ch | precision | size | run with |
|
| 9 |
-
|---|---|---|---|---|
|
| 10 |
-
| `CP43.ts` | 3 | FP32 | 20.4 MB | `run_nf_sp_dnnroi_evt.sh -n 3` (default) |
|
| 11 |
-
| `kd_mbv3_transformer_bnKD_6ch.ts` | 6 | FP32 | 20.4 MB | `run_nf_sp_dnnroi_evt.sh -n 6` |
|
| 12 |
-
| `qat_mbv3_transformer_bnKD_6ch_int8.ts` | 6 | INT8 (QAT) | 10.8 MB | `run_nf_sp_dnnroi_evt.sh -n 6 -D cpu` |
|
| 13 |
-
| `pipe_base_mbv3_6ch.ts` | 6 | FP32 | 20.4 MB | `run_nf_sp_dnnroi_evt.sh -n 6` |
|
| 14 |
-
| `pipe_distill_transformer_6ch.ts` | 6 | FP32 | 20.4 MB | `run_nf_sp_dnnroi_evt.sh -n 6` |
|
| 15 |
-
| `pipe_qat_transformer_6ch_int8.ts` | 6 | INT8 (QAT) | 10.8 MB | `run_nf_sp_dnnroi_evt.sh -n 6 -D cpu` |
|
| 16 |
-
|
| 17 |
-
## Provenance
|
| 18 |
-
|
| 19 |
-
| field | `CP43.ts` | `kd_..._6ch.ts` | `qat_..._6ch_int8.ts` |
|
| 20 |
-
|---|---|---|---|
|
| 21 |
-
| Architecture | MobileNetV3-large UNet | MobileNetV3-large UNet | QuantizableMobileNetV3-UNet, INT8 |
|
| 22 |
-
| Source repo | `DNN_ROI_SP/` | `DNN_ROI_SP/` | `DNN_ROI_SP/` |
|
| 23 |
-
| Run-id | `bs1_20260511-210525` | `distill_mbv3_transformer_bnKD_6ch_th150_ep100_l40s_ddp2` | `qat_distill_mbv3_transformer_bnKD_6ch_th150_ep20_l40s_ddp2` |
|
| 24 |
-
| Checkpoint | `CP43.pth` | `CP70.pth` | `qat_int8_state.pth` |
|
| 25 |
-
| Training | 3-ch baseline | Transformer teacher + bottleneck-feature KD | QAT-KD-C, warm-started from `CP70.pth` |
|
| 26 |
-
| TorchScript mode | trace | trace | trace |
|
| 27 |
-
| Held-out test Dice / ROI-eff | — | 0.9118 / 0.7609 | 0.8932 / 0.7274 |
|
| 28 |
-
|
| 29 |
-
`to_torchscript.py` falls back to `torch.jit.trace` because `torch.jit.script`
|
| 30 |
-
hits the `break` in the encoder loop; the INT8 quantized graph also cannot be
|
| 31 |
-
scripted. The traced UNets are fully convolutional and run at both the
|
| 32 |
-
per-plane (`800`) and stacked (`1600`) channel heights.
|
| 33 |
-
|
| 34 |
-
### Pipeline-reproduced models (2026-05-16)
|
| 35 |
-
|
| 36 |
-
`pipe_base_mbv3_6ch.ts`, `pipe_distill_transformer_6ch.ts`, and
|
| 37 |
-
`pipe_qat_transformer_6ch_int8.ts` are the three models deployed by the
|
| 38 |
-
end-to-end run documented in `DNN_ROI_SP/docs/full_pipeline.md` — a baseline,
|
| 39 |
-
the best distillation, and its QAT INT8 model, all 6-channel and trained on the
|
| 40 |
-
same corpus and split.
|
| 41 |
-
|
| 42 |
-
| field | `pipe_base_mbv3_6ch.ts` | `pipe_distill_transformer_6ch.ts` | `pipe_qat_transformer_6ch_int8.ts` |
|
| 43 |
-
|---|---|---|---|
|
| 44 |
-
| Architecture | MobileNetV3-large UNet | MobileNetV3-large UNet | QuantizableMobileNetV3-UNet, INT8 |
|
| 45 |
-
| Run-id | `pipe_base_mbv3_6ch` | `pipe_distill_transformer_6ch` | `pipe_qat_transformer_6ch` |
|
| 46 |
-
| Training | 6-ch baseline, no KD | Transformer teacher + bottleneck-feature KD | QAT-KD, warm-started from the distillation |
|
| 47 |
-
| Held-out test Dice / ROI-eff | 0.9120 / 0.7474 | 0.9107 / 0.7454 | 0.8900 / 0.7305 |
|
| 48 |
-
|
| 49 |
-
All three pass the toolkit-vs-standalone replay validation (max abs diff
|
| 50 |
-
< 1.4e-6; the INT8 model bit-exact) — see `full_pipeline.md` §4.3.
|
| 51 |
-
|
| 52 |
-
## Input layout
|
| 53 |
-
|
| 54 |
-
C++ tensor order is `(batch=1, ntags, nchannels, nticks)`:
|
| 55 |
-
|
| 56 |
-
- `nchannels` = `800` per plane in per-plane (`pp`) mode, or `1600`
|
| 57 |
-
(U+V stacked) in stacked (`mp`) mode. The W collection plane is not consumed.
|
| 58 |
-
- `nticks` = `1500`, from PDHD's raw `6000` after `tick_per_slice=4`
|
| 59 |
-
downsampling inside the C++ node.
|
| 60 |
-
|
| 61 |
-
**3-channel model** (`CP43.ts`) — `ntags=3`, in order:
|
| 62 |
-
|
| 63 |
-
```
|
| 64 |
-
loose_lf{APA}, mp2_roi{APA}, mp3_roi{APA}
|
| 65 |
-
```
|
| 66 |
-
|
| 67 |
-
**6-channel models** — `ntags=6`, in order:
|
| 68 |
-
|
| 69 |
-
```
|
| 70 |
-
loose_lf{APA}, mp2_roi{APA}, mp3_roi{APA}, tight_lf{APA}, decon_charge{APA}, gauss{APA}
|
| 71 |
-
```
|
| 72 |
-
|
| 73 |
-
All six tags are emitted by the standard PDHD `OmnibusSigProc` chain
|
| 74 |
-
(debug + multi-plane-protection mode) and require no SP-config change.
|
| 75 |
-
|
| 76 |
-
## Per-channel normalization (6-ch models)
|
| 77 |
-
|
| 78 |
-
The 6-ch models are trained on inputs divided by **per-channel** z-scales:
|
| 79 |
-
|
| 80 |
-
```
|
| 81 |
-
[944.6256, 4000.0, 4000.0, 803.7348, 1927.6997, 530.75]
|
| 82 |
-
```
|
| 83 |
-
|
| 84 |
-
Wire-Cell's `DNNROIFinding` can only apply one **scalar** `input_scale` to all
|
| 85 |
-
channels, so the per-channel division is **baked into the `.ts` module** as a
|
| 86 |
-
fixed normalization layer. Consequently the 6-ch models must run with
|
| 87 |
-
`input_scale = 1.0` — the `run_nf_sp_dnnroi_evt.sh -n 6` path sets this
|
| 88 |
-
automatically (`dnnroi_pp.jsonnet`). `CP43.ts` keeps the C++ default
|
| 89 |
-
`input_scale = 1/4000`.
|
| 90 |
-
|
| 91 |
-
## Tick padding
|
| 92 |
-
|
| 93 |
-
The C++ node rebins the time axis by `tick_per_slice=4` before inference and
|
| 94 |
-
needs the input tick count to be a multiple of the model's stride alignment.
|
| 95 |
-
For the PDHD MobileNetV3-large UNet (no deep stride-2 cascade in the tick
|
| 96 |
-
axis: post-rebin width 1500 = 4·375 is not divisible by 8 or higher powers
|
| 97 |
-
of 2), the alignment requirement is just `nticks % tick_per_slice == 0`,
|
| 98 |
-
i.e. **`nticks` must be a multiple of 4**. PDHD's standard `nticks=6000`
|
| 99 |
-
satisfies this with no padding.
|
| 100 |
-
|
| 101 |
-
The `dnnroi_pp.jsonnet` for PDHD leaves `tick_pad_multiple` unset (defaults
|
| 102 |
-
to `tick_per_slice=4`). The C++ node pads to the next 4-multiple before
|
| 103 |
-
inference, then crops back to `input_ticks` — a no-op for any
|
| 104 |
-
`nticks % 4 == 0` (including 6000, 6400, 8000).
|
| 105 |
-
|
| 106 |
-
## Consumer
|
| 107 |
-
|
| 108 |
-
Loaded by the toolkit C++ node `DNNROIFinding` (per-plane sequential: U
|
| 109 |
-
and V each run their own forward call sharing one TorchService). Wired by
|
| 110 |
-
`cfg/pgrapher/experiment/pdhd/dnnroi_pp.jsonnet`; driven by
|
| 111 |
-
`wcp-porting-img/pdhd/run_nf_sp_dnnroi_evt.sh` (`-n 3|6` selects the
|
| 112 |
-
input-channel set, `-M <model>` selects the `.ts`).
|
| 113 |
-
|
| 114 |
-
## Limitations
|
| 115 |
-
|
| 116 |
-
- Trained on **APA0 only**. Inference on APAs 1–3 is out-of-domain.
|
| 117 |
-
- W plane is not processed; downstream jsonnet routes it through a
|
| 118 |
-
`PlaneSelector` passthrough.
|
| 119 |
-
- The INT8 QAT model runs on **CPU only** (x86/fbgemm quantized backend);
|
| 120 |
-
it cannot be placed on a GPU device.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
dnn-roi/pdhd/20260615/README.pipe_distill_transformer_6ch.md
DELETED
|
@@ -1,65 +0,0 @@
|
|
| 1 |
-
# `pipe_distill_transformer_6ch.ts` — PDHD DNN-ROI (FP32, KD-Transformer)
|
| 2 |
-
|
| 3 |
-
Single-file companion to the directory-level [`README.md`](README.md), which is
|
| 4 |
-
the authoritative source for the full PDHD DNN-ROI model set, input layout,
|
| 5 |
-
normalization, and tick-padding rules. This note documents only this one file.
|
| 6 |
-
|
| 7 |
-
| field | value |
|
| 8 |
-
|---|---|
|
| 9 |
-
| file | `dnnroi/pdhd/pipe_distill_transformer_6ch.ts` |
|
| 10 |
-
| size | 21,410,681 bytes (≈20.4 MB) |
|
| 11 |
-
| architecture | MobileNetV3-large UNet |
|
| 12 |
-
| precision | FP32 |
|
| 13 |
-
| input channels | 6 |
|
| 14 |
-
| output | per-pixel `sigmoid` probability in `[0, 1]` (no extra sigmoid in Wire-Cell) |
|
| 15 |
-
| TorchScript mode | `torch.jit.trace` |
|
| 16 |
-
| role | pipeline-reproduced FP32 distillation model |
|
| 17 |
-
|
| 18 |
-
## What it is
|
| 19 |
-
|
| 20 |
-
The FP32 knowledge-distillation **Transformer-teacher** student for PDHD — the
|
| 21 |
-
"best distillation" leg of the end-to-end run documented in
|
| 22 |
-
`DNN_ROI_SP/docs/full_pipeline.md`. Trained 6-channel on the same corpus and
|
| 23 |
-
split as its sibling baseline (`pipe_base_mbv3_6ch.ts`) and its QAT INT8 model
|
| 24 |
-
(`pipe_qat_transformer_6ch_int8.ts`).
|
| 25 |
-
|
| 26 |
-
| metric (held-out test) | value |
|
| 27 |
-
|---|---|
|
| 28 |
-
| Dice / ROI-eff | 0.9107 / 0.7454 |
|
| 29 |
-
| run-id | `pipe_distill_transformer_6ch` |
|
| 30 |
-
| training | Transformer teacher + bottleneck-feature KD |
|
| 31 |
-
|
| 32 |
-
Passes the toolkit-vs-standalone replay validation (max abs diff < 1.4e-6) —
|
| 33 |
-
see `full_pipeline.md` §4.3.
|
| 34 |
-
|
| 35 |
-
## Input / output
|
| 36 |
-
|
| 37 |
-
C++ tensor order `(batch=1, ntags=6, nchannels, nticks)`. `nchannels = 800`
|
| 38 |
-
per-plane (`pp` mode) or `1600` (U+V stacked, `mp` mode); the traced UNet is
|
| 39 |
-
fully convolutional and runs at both heights. `nticks = 1500` (PDHD raw 6000
|
| 40 |
-
after `tick_per_slice=4`). The 6 trace tags, in order:
|
| 41 |
-
|
| 42 |
-
```
|
| 43 |
-
loose_lf, mp2_roi, mp3_roi, tight_lf, decon_charge, gauss
|
| 44 |
-
```
|
| 45 |
-
|
| 46 |
-
All six tags come from the standard PDHD `OmnibusSigProc` chain (debug +
|
| 47 |
-
multi-plane-protection mode) — no SP-config change needed. Per-channel z-scale
|
| 48 |
-
normalization is **baked into the `.ts`**; run with `input_scale = 1.0`. Tick
|
| 49 |
-
padding for PDHD only requires `nticks % 4 == 0`. Full details in the directory
|
| 50 |
-
[`README.md`](README.md).
|
| 51 |
-
|
| 52 |
-
## Run with
|
| 53 |
-
|
| 54 |
-
```
|
| 55 |
-
run_nf_sp_dnnroi_evt.sh -n 6
|
| 56 |
-
```
|
| 57 |
-
|
| 58 |
-
(then `-M dnnroi/pdhd/pipe_distill_transformer_6ch.ts` to select this `.ts`).
|
| 59 |
-
Wired by `cfg/pgrapher/experiment/pdhd/dnnroi_pp.jsonnet`; loaded by the toolkit
|
| 60 |
-
C++ node `DNNROIFinding`.
|
| 61 |
-
|
| 62 |
-
## Limitations
|
| 63 |
-
|
| 64 |
-
Trained on **APA0 only** — inference on APAs 1–3 is out-of-domain. The W plane
|
| 65 |
-
is not processed (routed through a `PlaneSelector` passthrough).
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
dnn-roi/pdhd/20260615/pipe_distill_transformer_6ch.md
ADDED
|
@@ -0,0 +1,123 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# PDHD DNN-ROI — `pipe_distill_transformer_6ch.ts`
|
| 2 |
+
|
| 3 |
+
TorchScript (`.ts`) DNN-ROI model for ProtoDUNE-HD (PDHD), loaded by the
|
| 4 |
+
wire-cell-toolkit DNN-ROI node `DNNROIFinding`. It produces a per-pixel
|
| 5 |
+
region-of-interest (ROI) probability map used to gate signal-processing output.
|
| 6 |
+
|
| 7 |
+
| field | value |
|
| 8 |
+
|---|---|
|
| 9 |
+
| file | `dnnroi/pdhd/pipe_distill_transformer_6ch.ts` |
|
| 10 |
+
| architecture | MobileNetV3-large UNet |
|
| 11 |
+
| precision | FP32 |
|
| 12 |
+
| input channels (tags) | 6 |
|
| 13 |
+
| output | per-pixel `sigmoid` probability in `[0, 1]` (no extra sigmoid needed in Wire-Cell) |
|
| 14 |
+
| TorchScript mode | `torch.jit.trace` |
|
| 15 |
+
| size | ≈20.4 MB (21,410,681 bytes) |
|
| 16 |
+
|
| 17 |
+
## 1. How the model was trained
|
| 18 |
+
|
| 19 |
+
- **Architecture:** MobileNetV3-large UNet, exported to TorchScript with
|
| 20 |
+
`torch.jit.trace`. (`torch.jit.script` is not used because the encoder loop
|
| 21 |
+
contains a `break` that the scripter cannot handle.) The traced network is
|
| 22 |
+
fully convolutional and runs at both the per-plane (`800`) and stacked
|
| 23 |
+
(`1600`) channel heights.
|
| 24 |
+
- **Method:** knowledge distillation from a **Transformer teacher** using
|
| 25 |
+
bottleneck-feature KD. This is the "best distillation" leg of a matched
|
| 26 |
+
three-model set (a plain 6-ch baseline, this distilled model, and a QAT INT8
|
| 27 |
+
version), all 6-channel and trained on the same corpus and split.
|
| 28 |
+
- **Training data:** PDHD signal-processing frames, **APA0 only** (see
|
| 29 |
+
Limitations).
|
| 30 |
+
- **Held-out test metrics:** Dice **0.9107** / ROI-efficiency **0.7454**.
|
| 31 |
+
- **Validation:** passes toolkit-vs-standalone replay validation
|
| 32 |
+
(max absolute difference < 1.4e-6).
|
| 33 |
+
- **Hyperparameters** (epochs, thresholds, optimizer, dataset size/split
|
| 34 |
+
details): _W.I.P._
|
| 35 |
+
|
| 36 |
+
## 2. Input / output
|
| 37 |
+
|
| 38 |
+
### Input tensor
|
| 39 |
+
|
| 40 |
+
C++ tensor order `(batch=1, ntags=6, nchannels, nticks)`:
|
| 41 |
+
|
| 42 |
+
- **`ntags = 6`** — the 6 input trace tags, in this exact order:
|
| 43 |
+
|
| 44 |
+
```
|
| 45 |
+
loose_lf, mp2_roi, mp3_roi, tight_lf, decon_charge, gauss
|
| 46 |
+
```
|
| 47 |
+
|
| 48 |
+
All six tags are emitted by the standard PDHD `OmnibusSigProc` chain
|
| 49 |
+
(debug + multi-plane-protection mode) and require no signal-processing
|
| 50 |
+
config change.
|
| 51 |
+
|
| 52 |
+
- **`nchannels`** — `800` per plane in per-plane (`pp`) mode, or `1600`
|
| 53 |
+
(U+V stacked) in stacked (`mp`) mode. The W (collection) plane is not
|
| 54 |
+
consumed.
|
| 55 |
+
|
| 56 |
+
- **`nticks`** — `1500`, obtained from PDHD's raw `6000` ticks after
|
| 57 |
+
`tick_per_slice = 4` downsampling inside the C++ node.
|
| 58 |
+
|
| 59 |
+
### Normalization (baked in)
|
| 60 |
+
|
| 61 |
+
The model was trained on inputs divided by **per-channel** z-scales:
|
| 62 |
+
|
| 63 |
+
```
|
| 64 |
+
[944.6256, 4000.0, 4000.0, 803.7348, 1927.6997, 530.75]
|
| 65 |
+
```
|
| 66 |
+
|
| 67 |
+
Because `DNNROIFinding` can apply only a single **scalar** `input_scale` to all
|
| 68 |
+
channels, this per-channel division is **baked into the `.ts` module** as a
|
| 69 |
+
fixed normalization layer. Therefore run this model with **`input_scale = 1.0`**.
|
| 70 |
+
|
| 71 |
+
### Tick padding
|
| 72 |
+
|
| 73 |
+
The C++ node rebins the time axis by `tick_per_slice = 4` before inference and
|
| 74 |
+
requires the tick count to be a multiple of the model's stride alignment. For
|
| 75 |
+
this network the requirement is simply **`nticks % 4 == 0`**. PDHD's standard
|
| 76 |
+
`nticks = 6000` satisfies this with no padding (`tick_pad_multiple` may be left
|
| 77 |
+
unset, defaulting to `tick_per_slice = 4`). The node pads to the next
|
| 78 |
+
4-multiple, runs inference, then crops back to `input_ticks` — a no-op for any
|
| 79 |
+
`nticks % 4 == 0` (e.g. 6000, 6400, 8000).
|
| 80 |
+
|
| 81 |
+
### Output tensor
|
| 82 |
+
|
| 83 |
+
Per-pixel ROI probability in `[0, 1]` (`sigmoid` already applied inside the
|
| 84 |
+
model). No additional sigmoid should be applied in Wire-Cell.
|
| 85 |
+
|
| 86 |
+
## 3. How to use
|
| 87 |
+
|
| 88 |
+
The model is loaded via a `TorchService` and consumed by the `DNNROIFinding`
|
| 89 |
+
node. Example wiring (from
|
| 90 |
+
[`dunereco/.../pdhd/wcls-rawdigit-dnnsp.jsonnet`](https://github.com/DUNE/dunereco/blob/25641a94aca58900c5e87f8e592f3d3aba166e6a/dunereco/DUNEWireCell/pdhd/wcls-rawdigit-dnnsp.jsonnet#L284)):
|
| 91 |
+
|
| 92 |
+
```jsonnet
|
| 93 |
+
// TorchService pointing at this model
|
| 94 |
+
local ts = {
|
| 95 |
+
type: "TorchService",
|
| 96 |
+
name: "dnnroi",
|
| 97 |
+
data: {
|
| 98 |
+
model: "dnnroi/pdhd/pipe_distill_transformer_6ch.ts",
|
| 99 |
+
device: "cpu", // or "gpu"
|
| 100 |
+
concurrency: 1,
|
| 101 |
+
},
|
| 102 |
+
};
|
| 103 |
+
|
| 104 |
+
// DNN-ROI node, wired per anode; input_scale=1.0 because normalization
|
| 105 |
+
// is baked into the .ts (see §2). The dnnroi helper is imported from
|
| 106 |
+
// pgrapher/experiment/pdhd/dnnroi_pp.jsonnet.
|
| 107 |
+
local dnnroi = import 'pgrapher/experiment/pdhd/dnnroi_pp.jsonnet';
|
| 108 |
+
|
| 109 |
+
dnnroi(tools.anodes[n], ts, output_scale=1.0,
|
| 110 |
+
nticks=params.daq.nticks, nchunks=1),
|
| 111 |
+
```
|
| 112 |
+
|
| 113 |
+
Notes:
|
| 114 |
+
- Run with **`input_scale = 1.0`** (normalization is baked in — see §2).
|
| 115 |
+
- Loaded by the toolkit C++ node `DNNROIFinding`, which processes U and V
|
| 116 |
+
planes sequentially (each plane runs its own forward call, sharing one
|
| 117 |
+
`TorchService`).
|
| 118 |
+
|
| 119 |
+
## 4. Limitations
|
| 120 |
+
|
| 121 |
+
- Trained on **APA0 only** — inference on APAs 1–3 is out-of-domain.
|
| 122 |
+
- The **W (collection) plane is not processed**; downstream jsonnet routes it
|
| 123 |
+
through a `PlaneSelector` passthrough.
|
dnn-roi/pdvd/20260615/README.md
DELETED
|
@@ -1,214 +0,0 @@
|
|
| 1 |
-
# PDVD DNN-ROI TorchScript models
|
| 2 |
-
|
| 3 |
-
TorchScript (`.ts`) models loaded by the wire-cell-toolkit DNN-ROI node
|
| 4 |
-
`DNNROIFinding` (single-plane, per-plane sequential) for ProtoDUNE Vertical
|
| 5 |
-
Drift. All are exported with `DNN_ROI_SP/scripts/to_torchscript.py` from the
|
| 6 |
-
full-corpus 6-channel SDCC training campaign (DAGMan 287, 2026-05-20/21) and
|
| 7 |
-
output `sigmoid` probabilities in `[0, 1]` (no extra sigmoid needed in
|
| 8 |
-
Wire-Cell).
|
| 9 |
-
|
| 10 |
-
> **2026-05-23 retrace.** The shipped `.ts` files were originally traced at
|
| 11 |
-
> the stacked-plane shape `(1, 6, 952, 1600)` and crashed when fed the
|
| 12 |
-
> per-plane shape `(1, 6, 476, 1600)` that the deployed `DNNROIFinding`
|
| 13 |
-
> chain actually produces (119-vs-120 cat mismatch in `mobilenetv3_unet`'s
|
| 14 |
-
> decoder skip at H=476). All five `.ts` files have been re-traced from
|
| 15 |
-
> the same canonical checkpoints at the per-plane input shape; the trace
|
| 16 |
-
> now records the model's runtime `F.interpolate` size-fixup at the
|
| 17 |
-
> failing decoder layer (an aligned 120→119 bilinear, identity on
|
| 18 |
-
> matched layers). Standalone replay through the re-traced
|
| 19 |
-
> `pipe_distill_nestedunet_6ch.ts` reproduces the toolkit output to
|
| 20 |
-
> max-abs `~5×10⁻⁷` on all 8 anodes × 2 induction planes for run 039324
|
| 21 |
-
> evt 0 (`DNN_ROI_SP/scripts/verify_wirecell_dnn.py`).
|
| 22 |
-
|
| 23 |
-
## Production deployables
|
| 24 |
-
|
| 25 |
-
The three files actively wired by the toolkit. The current default in
|
| 26 |
-
`simulation/toolkit/pdvd/wct-nf-sp-dnnroi.jsonnet` is the INT8 primary
|
| 27 |
-
(`pipe_qat_nestedunet_6ch_ep0_int8.ts`); flip `dnnroi_model` to a different
|
| 28 |
-
row to swap.
|
| 29 |
-
|
| 30 |
-
| file | input ch | precision | size | role | run with |
|
| 31 |
-
|---|---|---|---|---|---|
|
| 32 |
-
| `pipe_base_mbv3_6ch.ts` | 6 | FP32 | 20.4 MB | FP32 baseline (no KD) | `run_nf_sp_dnnroi_evt.sh -M dnnroi/pdvd/pipe_base_mbv3_6ch.ts` |
|
| 33 |
-
| `pipe_distill_nestedunet_6ch.ts` | 6 | FP32 | 20.4 MB | FP32 best KD | `run_nf_sp_dnnroi_evt.sh -M dnnroi/pdvd/pipe_distill_nestedunet_6ch.ts` |
|
| 34 |
-
| `pipe_qat_nestedunet_6ch_ep0_int8.ts`| 6 | INT8 (QAT) | 10.8 MB | **INT8 primary (default)** | `run_nf_sp_dnnroi_evt.sh -D cpu -M dnnroi/pdvd/pipe_qat_nestedunet_6ch_ep0_int8.ts` |
|
| 35 |
-
|
| 36 |
-
## Staged / diagnostic
|
| 37 |
-
|
| 38 |
-
Not wired by default; kept so the user can re-run the §11 / §12.4
|
| 39 |
-
comparisons without re-exporting from checkpoints. Both originate from the
|
| 40 |
-
Transformer-teacher chain of DAGMan 287 — kept as a reference companion to
|
| 41 |
-
the production NestedUNet-teacher chain above.
|
| 42 |
-
|
| 43 |
-
| file | input ch | precision | size | role |
|
| 44 |
-
|---|---|---|---|---|
|
| 45 |
-
| `pipe_distill_transformer_6ch.ts` | 6 | FP32 | 20.4 MB | FP32 KD-Tx, used in §11 as a same-architecture FP32 reference for INT8-Tx |
|
| 46 |
-
| `pipe_qat_transformer_6ch_ep3_int8.ts` | 6 | INT8 (QAT) | 10.8 MB | Tx INT8 candidate at epoch 3; narrows the §11 top-CRP regression but did not clear the strict §12.4 ≤10 % nzpx gate (an5 12.57 %). Held back from production pending an explicit decision; not the canonical Tx INT8. |
|
| 47 |
-
|
| 48 |
-
(The previous canonical Tx INT8, `pipe_qat_transformer_6ch_int8.ts`, was
|
| 49 |
-
derived from epoch 19 — the last-epoch fakequant that the un-patched
|
| 50 |
-
`scripts/qat_kd_finetune.py` shipped by default. Per
|
| 51 |
-
`DNN_ROI_SP/docs/qat_deployable_diagnostic_2026-05-21.md`, that ep19 ckpt
|
| 52 |
-
was strictly dominated by ep3 on labeled Dice (0.7550 vs 0.7772) **and** on
|
| 53 |
-
top-CRP over-emission. The ep19 `.ts` was removed in the 2026-05-21
|
| 54 |
-
cleanup; if the user ever wants it back for a controlled comparison,
|
| 55 |
-
re-export from `checkpoints/pdvd_qat_transformer_6ch/qat_int8_state.pth.ep19`
|
| 56 |
-
on wcgpu1.)
|
| 57 |
-
|
| 58 |
-
## Provenance
|
| 59 |
-
|
| 60 |
-
All exports trace back to DAGMan cluster **287** on SDCC
|
| 61 |
-
(`sgpu0004`, 2× L40S, 2026-05-20 22:12 → 2026-05-21 06:51 EDT,
|
| 62 |
-
~8 h 40 min wall total). The training corpus is the 6-channel PDVD
|
| 63 |
-
mix (1 000 train + 200 val + 400 held-out test, 125/25/50 events per
|
| 64 |
-
anode × 8 anodes, `pdvd_anode{0..7}_6ch_th150_pad3.h5`).
|
| 65 |
-
|
| 66 |
-
### Production deployables
|
| 67 |
-
|
| 68 |
-
| field | `pipe_base_mbv3_6ch` | `pipe_distill_nestedunet_6ch` | `pipe_qat_nestedunet_6ch_ep0_int8` |
|
| 69 |
-
|---|---|---|---|
|
| 70 |
-
| Architecture | MobileNetV3-large UNet | MobileNetV3-large UNet | QuantizableMobileNetV3-UNet, INT8 |
|
| 71 |
-
| Run-id | `pdvd_mobilenetv3_all_6ch` | `pdvd_distill_nestedunet_6ch` | `pdvd_qat_nestedunet_6ch` |
|
| 72 |
-
| Checkpoint | `CP97.pth` (best-val ep 97) | `CP35.pth` (best-val ep 35) | `qat_int8_state.pth.ep0` (best-by-post-convert) |
|
| 73 |
-
| Training | 6-ch baseline, no KD, 100 ep | NestedUNet teacher + feature-map KD, 100 ep | QAT-KD INT8, 20 ep, warm-started from KD-NU (`pdvd_distill_nestedunet_6ch`) |
|
| 74 |
-
| TorchScript mode | trace | trace | trace |
|
| 75 |
-
| Held-out test (400 ev) Dice | 0.7538 | **0.7816** | 0.7797 |
|
| 76 |
-
| Held-out test eff_roi / pur_roi | 0.7135 / 0.8594 | 0.7520 / 0.8537 | 0.7533 / 0.8490 |
|
| 77 |
-
|
| 78 |
-
The KD-NestedUNet student (`pdvd_distill_nestedunet_6ch`) is the strongest
|
| 79 |
-
FP32 model on test (Dice 0.7816, eff_roi 0.7520 — both #1 of the 5 FP32
|
| 80 |
-
runs). The INT8 primary (`pdvd_qat_nestedunet_6ch` epoch 0) keeps 99.7 % of
|
| 81 |
-
that FP32 Dice (0.7797 = −0.27 % vs FP32 KD parent) and clears the toolkit
|
| 82 |
-
§12.4 ≤10 % nzpx gate on all 8 anodes (worst case 9.34 % on anode 5). The
|
| 83 |
-
direct-MBV3 baseline is shipped as the no-KD reference.
|
| 84 |
-
|
| 85 |
-
The INT8 primary's epoch choice (ep 0) is governed by post-convert dice
|
| 86 |
-
peaking early in QAT, not the trainer's fakequant `val_dice`. See
|
| 87 |
-
`DNN_ROI_SP/docs/qat_deployable_diagnostic_2026-05-21.md` for the full
|
| 88 |
-
diagnostic and `DNN_ROI_SP/scripts/qat_kd_finetune.py`'s
|
| 89 |
-
best-by-post-convert tracking that lands canonically going forward.
|
| 90 |
-
|
| 91 |
-
### Staged / diagnostic
|
| 92 |
-
|
| 93 |
-
| field | `pipe_distill_transformer_6ch` | `pipe_qat_transformer_6ch_ep3_int8` |
|
| 94 |
-
|---|---|---|
|
| 95 |
-
| Architecture | MobileNetV3-large UNet | QuantizableMobileNetV3-UNet, INT8 |
|
| 96 |
-
| Run-id | `pdvd_distill_transformer_6ch` | `pdvd_qat_transformer_6ch` |
|
| 97 |
-
| Checkpoint | `CP99.pth` (best-val ep 99) | `qat_int8_state.pth.ep3` |
|
| 98 |
-
| Held-out test Dice | 0.7680 | 0.7772 |
|
| 99 |
-
| Notes | Diagnostic FP32 anchor for §11 / §12.4 same-arch INT8 comparison. Not the shipped FP32 deployable. | Tx-chain INT8 candidate. +1.20 % vs FP32 KD-Tx parent on labeled test Dice. Narrows the §11 top-CRP regression (an4 11.27 %→7.60 %, an5 17.63 %→12.57 %) but an5 still exceeds the §12.4 10 % strict gate; ep19 was deleted as superseded but no Tx INT8 .ts is wired as canonical until the residual is resolved (see `DNN_ROI_SP/memory/pdvd_int8_top_crp_oversegmentation.md`). |
|
| 100 |
-
|
| 101 |
-
`to_torchscript.py` falls back to `torch.jit.trace` (the encoder `break`
|
| 102 |
-
and the INT8 graph cannot be scripted); each export is verified by an
|
| 103 |
-
eager-vs-TorchScript `allclose` (max abs diff 0.00e+00 for all five files).
|
| 104 |
-
|
| 105 |
-
## Input layout
|
| 106 |
-
|
| 107 |
-
C++ tensor order is `(batch=1, ntags, nchannels, nticks)`:
|
| 108 |
-
|
| 109 |
-
- `ntags` = **6**.
|
| 110 |
-
- `nchannels` = **476** per plane. The two induction planes U and V are
|
| 111 |
-
processed sequentially by two `DNNROIFinding` nodes per anode (sharing a
|
| 112 |
-
single TorchService); the W collection plane is not consumed (passed
|
| 113 |
-
through from standard SP gauss). See
|
| 114 |
-
`cfg/pgrapher/experiment/protodunevd/dnnroi_pp.jsonnet`.
|
| 115 |
-
- `nticks` = **1600**, from PDVD's raw `6400` ticks after `tick_per_slice=4`
|
| 116 |
-
downsampling inside the C++ node.
|
| 117 |
-
|
| 118 |
-
The toolkit input per call is `(1, 6, 476, 1600)`. The PDVD students were
|
| 119 |
-
trained on **stacked U+V at (1, 6, 952, 1600)**; per-plane deployment is
|
| 120 |
-
structurally compatible (MobileNetV3-large is fully convolutional on the
|
| 121 |
-
channel axis), and the re-traced `.ts` files include the runtime
|
| 122 |
-
size-fixup the U-Net needs at this shape (see top-of-file note).
|
| 123 |
-
|
| 124 |
-
**6-channel input** — `ntags=6`, trace tags in order:
|
| 125 |
-
|
| 126 |
-
```
|
| 127 |
-
loose_lf{A}, mp2_roi{A}, mp3_roi{A}, tight_lf{A}, decon_charge{A}, gauss{A}
|
| 128 |
-
```
|
| 129 |
-
|
| 130 |
-
The two new tags relative to the previous 4-ch deployment (`tight_lf` and
|
| 131 |
-
`decon_charge`) must be emitted by PDVD's `OmnibusSigProc` chain in debug +
|
| 132 |
-
multi-plane-protection mode — the same way PDHD 6-ch deployment works. The
|
| 133 |
-
order matches the PDHD 6-ch sibling exactly.
|
| 134 |
-
|
| 135 |
-
## Per-channel normalization
|
| 136 |
-
|
| 137 |
-
The 6-ch models are trained on inputs divided by **per-channel** z-scales.
|
| 138 |
-
Wire-Cell's `DNNROIFinding` applies one scalar `input_scale`, so the
|
| 139 |
-
per-channel division is baked into each `.ts` as a fixed normalization layer;
|
| 140 |
-
the models run with `input_scale = 1.0` (set by
|
| 141 |
-
`protodunevd/dnnroi_pp.jsonnet`).
|
| 142 |
-
|
| 143 |
-
A single set is baked into all `.ts` files — the **cross-anode mean**:
|
| 144 |
-
|
| 145 |
-
```
|
| 146 |
-
[766.1332, 4000.0, 4000.0, 762.4834, 1679.252, 11827.907]
|
| 147 |
-
(loose_lf, mp2_roi, mp3_roi, tight_lf, decon_charge, gauss)
|
| 148 |
-
```
|
| 149 |
-
|
| 150 |
-
The per-anode z-scales differ — z[0] runs ~50 % higher on the top CRP
|
| 151 |
-
(anodes 4-7) than the bottom CRP (anodes 0-3). The cross-anode mean is an
|
| 152 |
-
approximation; the unified vs split study
|
| 153 |
-
(`DNN_ROI_SP/docs/pdvd_unified_vs_split_study.md`) shows one mixed model
|
| 154 |
-
matches the per-half specialists, so a single set is shipped.
|
| 155 |
-
|
| 156 |
-
## Tick padding
|
| 157 |
-
|
| 158 |
-
The C++ node rebins the time axis by `tick_per_slice=4` before inference;
|
| 159 |
-
the PDVD MobileNetV3-large UNet was trained at post-rebin width
|
| 160 |
-
**1600** (= `6400/4`), and 1600 = 64·25 has five spare factors of 2, so
|
| 161 |
-
the deployed `.ts` has **5 stride-2 down/up levels** in the tick axis
|
| 162 |
-
post-rebin. To survive that cascade the post-rebin width must be
|
| 163 |
-
divisible by 2⁵ = 32, i.e. the input `nticks` must be a multiple of
|
| 164 |
-
`tick_per_slice · 32 = 4·32 = 128`.
|
| 165 |
-
|
| 166 |
-
`cfg/pgrapher/experiment/protodunevd/dnnroi_pp.jsonnet` sets
|
| 167 |
-
`tick_pad_multiple=128` by default; the C++ `DNNROIFinding` node then
|
| 168 |
-
pads the input ticks up to the next 128-multiple before inference and
|
| 169 |
-
crops the output back to the original `input_ticks`.
|
| 170 |
-
|
| 171 |
-
| input `nticks` | padded `model_ticks` | output cropped to |
|
| 172 |
-
|---|---|---|
|
| 173 |
-
| 6000 | 6016 (= 47·128) | 6000 |
|
| 174 |
-
| 6400 | 6400 (already 50·128) | 6400 |
|
| 175 |
-
| 8000 | 8064 (= 63·128) | 8000 |
|
| 176 |
-
|
| 177 |
-
A mismatch surfaces as a tensor-shape error inside the model at runtime,
|
| 178 |
-
not as a toolkit-side check, so do not lower `tick_pad_multiple` for
|
| 179 |
-
these models.
|
| 180 |
-
|
| 181 |
-
## Consumer
|
| 182 |
-
|
| 183 |
-
Loaded by the toolkit C++ node `DNNROIFinding` (per-plane sequential:
|
| 184 |
-
U and V each run their own forward call sharing one TorchService —
|
| 185 |
-
analogous to the PDHD pp wiring). Wired by
|
| 186 |
-
`cfg/pgrapher/experiment/protodunevd/dnnroi_pp.jsonnet`; driven by
|
| 187 |
-
`toolkit/pdvd/run_nf_sp_dnnroi_evt.sh` and
|
| 188 |
-
`wcp-porting-img/pdvd/run_nf_sp_dnnroi_evt.sh` (`-M <model>` selects the
|
| 189 |
-
`.ts`).
|
| 190 |
-
|
| 191 |
-
The C++ `DNNROIFinding` node honors `debugfile` (set via the chain's
|
| 192 |
-
`-X <basename>` flag) and writes one `{basename}_anode{N}_{plane}_call0.pt`
|
| 193 |
-
per call containing `(input, output, meta)` — loadable with
|
| 194 |
-
`DNN_ROI_SP/scripts/verify_wirecell_dnn.py` for offline 1:1 replay
|
| 195 |
-
against the same `.ts`.
|
| 196 |
-
|
| 197 |
-
## Limitations
|
| 198 |
-
|
| 199 |
-
- Trained on **all 8 PDVD anodes** (bottom CRP = anodes 0-3, top CRP =
|
| 200 |
-
anodes 4-7) — the previous 4-channel deployment's "anodes 4-7
|
| 201 |
-
out-of-domain" caveat no longer applies. See
|
| 202 |
-
`DNN_ROI_SP/docs/pdvd_unified_vs_split_study.md` for evidence one model
|
| 203 |
-
handles both halves.
|
| 204 |
-
- The W collection plane is not processed; the toolkit jsonnet routes it
|
| 205 |
-
through a `PlaneSelector` passthrough of standard SP gauss.
|
| 206 |
-
- INT8 QAT models run on **CPU only** (x86 quantized backend); they cannot
|
| 207 |
-
be placed on a GPU device.
|
| 208 |
-
- The INT8 primary (NU ep0) is the result of a deployable-selection patch
|
| 209 |
-
(best-by-post-convert dice). For runs that pre-date the patch, the
|
| 210 |
-
trainer's last-epoch `qat_int8_state.pth` should not be assumed to be
|
| 211 |
-
the best post-convert deployable — see the §12.6 follow-up in
|
| 212 |
-
`DNN_ROI_SP/docs/sdcc_full_training_campaign.md` for details.
|
| 213 |
-
- Cross-anode-mean z-scales are an approximation — see
|
| 214 |
-
*Per-channel normalization* above.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
dnn-roi/pdvd/20260615/README.pipe_distill_transformer_6ch.md
DELETED
|
@@ -1,58 +0,0 @@
|
|
| 1 |
-
# `pipe_distill_transformer_6ch.ts` — PDVD DNN-ROI (FP32, KD-Transformer)
|
| 2 |
-
|
| 3 |
-
Single-file companion to the directory-level [`README.md`](README.md), which is
|
| 4 |
-
the authoritative source for the full PDVD DNN-ROI model set, input layout,
|
| 5 |
-
normalization, and tick-padding rules. This note documents only this one file.
|
| 6 |
-
|
| 7 |
-
| field | value |
|
| 8 |
-
|---|---|
|
| 9 |
-
| file | `dnnroi/pdvd/pipe_distill_transformer_6ch.ts` |
|
| 10 |
-
| size | 21,407,103 bytes (≈20.4 MB) |
|
| 11 |
-
| architecture | MobileNetV3-large UNet |
|
| 12 |
-
| precision | FP32 |
|
| 13 |
-
| input channels | 6 |
|
| 14 |
-
| output | per-pixel `sigmoid` probability in `[0, 1]` (no extra sigmoid in Wire-Cell) |
|
| 15 |
-
| TorchScript mode | `torch.jit.trace` (re-traced 2026-05-23 at per-plane shape) |
|
| 16 |
-
| role | **staged / diagnostic — not wired by default** |
|
| 17 |
-
|
| 18 |
-
## What it is
|
| 19 |
-
|
| 20 |
-
The FP32 knowledge-distillation **Transformer-teacher** student for PDVD,
|
| 21 |
-
exported from DAGMan cluster 287 (SDCC, 2026-05-20/21). It is the
|
| 22 |
-
same-architecture FP32 reference used in the §11 / §12.4 INT8-vs-FP32
|
| 23 |
-
comparisons against the Transformer INT8 candidate
|
| 24 |
-
(`pipe_qat_transformer_6ch_ep3_int8.ts`). It is **not** the shipped FP32
|
| 25 |
-
deployable — that is `pipe_distill_nestedunet_6ch.ts` (NestedUNet teacher,
|
| 26 |
-
stronger on held-out test). See the directory README's *Staged / diagnostic*
|
| 27 |
-
and *Provenance* sections.
|
| 28 |
-
|
| 29 |
-
| metric (400-event held-out test) | value |
|
| 30 |
-
|---|---|
|
| 31 |
-
| Dice | 0.7680 |
|
| 32 |
-
| run-id | `pdvd_distill_transformer_6ch` |
|
| 33 |
-
| checkpoint | `CP99.pth` (best-val ep 99) |
|
| 34 |
-
|
| 35 |
-
## Input / output
|
| 36 |
-
|
| 37 |
-
C++ tensor order `(batch=1, ntags=6, nchannels=476, nticks=1600)`, processed
|
| 38 |
-
per-plane (U then V) by `DNNROIFinding`. The 6 trace tags, in order:
|
| 39 |
-
|
| 40 |
-
```
|
| 41 |
-
loose_lf, mp2_roi, mp3_roi, tight_lf, decon_charge, gauss
|
| 42 |
-
```
|
| 43 |
-
|
| 44 |
-
Per-channel z-scale normalization is **baked into the `.ts`**; run with
|
| 45 |
-
`input_scale = 1.0`. Tick padding must use a multiple of
|
| 46 |
-
`tick_per_slice·32 = 128`. Full details (the 5-level stride-2 cascade, the
|
| 47 |
-
cross-anode-mean z-scales, the 2026-05-23 per-plane re-trace) are in the
|
| 48 |
-
directory [`README.md`](README.md).
|
| 49 |
-
|
| 50 |
-
## Run with
|
| 51 |
-
|
| 52 |
-
```
|
| 53 |
-
run_nf_sp_dnnroi_evt.sh -M dnnroi/pdvd/pipe_distill_transformer_6ch.ts
|
| 54 |
-
```
|
| 55 |
-
|
| 56 |
-
Wired (when selected) by
|
| 57 |
-
`cfg/pgrapher/experiment/protodunevd/dnnroi_pp.jsonnet`. Loaded by the toolkit
|
| 58 |
-
C++ node `DNNROIFinding`.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
dnn-roi/pdvd/20260615/pipe_distill_transformer_6ch.md
ADDED
|
@@ -0,0 +1,157 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# PDVD DNN-ROI — `pipe_distill_transformer_6ch.ts`
|
| 2 |
+
|
| 3 |
+
TorchScript (`.ts`) DNN-ROI model for ProtoDUNE Vertical Drift (PDVD), loaded
|
| 4 |
+
by the wire-cell-toolkit DNN-ROI node `DNNROIFinding`. It produces a per-pixel
|
| 5 |
+
region-of-interest (ROI) probability map used to gate signal-processing output.
|
| 6 |
+
|
| 7 |
+
| field | value |
|
| 8 |
+
|---|---|
|
| 9 |
+
| file | `dnnroi/pdvd/pipe_distill_transformer_6ch.ts` |
|
| 10 |
+
| architecture | MobileNetV3-large UNet |
|
| 11 |
+
| precision | FP32 |
|
| 12 |
+
| input channels (tags) | 6 |
|
| 13 |
+
| output | per-pixel `sigmoid` probability in `[0, 1]` (no extra sigmoid needed in Wire-Cell) |
|
| 14 |
+
| TorchScript mode | `torch.jit.trace` (traced at the per-plane input shape) |
|
| 15 |
+
| size | ≈20.4 MB (21,407,103 bytes) |
|
| 16 |
+
| role | **diagnostic / reference — not the default production FP32 model** |
|
| 17 |
+
|
| 18 |
+
> **Which FP32 model should I use?** For production PDVD signal processing the
|
| 19 |
+
> recommended FP32 model is the NestedUNet-teacher student
|
| 20 |
+
> (`pipe_distill_nestedunet_6ch.ts`), which scores higher on the held-out test.
|
| 21 |
+
> This Transformer-teacher model is kept as a same-architecture FP32 reference
|
| 22 |
+
> for INT8-vs-FP32 comparisons.
|
| 23 |
+
|
| 24 |
+
## 1. How the model was trained
|
| 25 |
+
|
| 26 |
+
- **Architecture:** MobileNetV3-large UNet, exported to TorchScript with
|
| 27 |
+
`torch.jit.trace`. (`torch.jit.script` is not used because the encoder loop
|
| 28 |
+
contains a `break` that the scripter cannot handle.) MobileNetV3-large is
|
| 29 |
+
fully convolutional on the channel axis; the model was trained on **stacked
|
| 30 |
+
U+V** input `(1, 6, 952, 1600)` but is deployed **per-plane** at
|
| 31 |
+
`(1, 6, 476, 1600)`. The traced `.ts` records the U-Net's runtime
|
| 32 |
+
size-fixup (an aligned bilinear interpolate at the decoder skip that would
|
| 33 |
+
otherwise mismatch at H=476), so it runs correctly at the per-plane shape.
|
| 34 |
+
- **Method:** knowledge distillation from a **Transformer teacher**.
|
| 35 |
+
- **Training data:** 6-channel PDVD corpus — 1,000 train + 200 val + 400
|
| 36 |
+
held-out test events (125/25/50 events per anode across **all 8 anodes**),
|
| 37 |
+
from the SDCC full-corpus 6-channel training campaign.
|
| 38 |
+
- **Checkpoint:** `CP99.pth` (best-val, epoch 99); run-id
|
| 39 |
+
`pdvd_distill_transformer_6ch`.
|
| 40 |
+
- **Held-out test metric:** Dice **0.7680** (400-event test set).
|
| 41 |
+
- **Validation:** standalone replay reproduces the toolkit output to
|
| 42 |
+
max absolute difference ≈ 5×10⁻⁷ (eager-vs-TorchScript `allclose` max abs
|
| 43 |
+
diff 0.00 at export).
|
| 44 |
+
- **Hyperparameters** (optimizer, learning rate, exact epoch count/schedule):
|
| 45 |
+
_W.I.P._
|
| 46 |
+
|
| 47 |
+
## 2. Input / output
|
| 48 |
+
|
| 49 |
+
### Input tensor
|
| 50 |
+
|
| 51 |
+
C++ tensor order `(batch=1, ntags=6, nchannels=476, nticks=1600)`, processed
|
| 52 |
+
per-plane (U then V):
|
| 53 |
+
|
| 54 |
+
- **`ntags = 6`** — the 6 input trace tags, in this exact order:
|
| 55 |
+
|
| 56 |
+
```
|
| 57 |
+
loose_lf, mp2_roi, mp3_roi, tight_lf, decon_charge, gauss
|
| 58 |
+
```
|
| 59 |
+
|
| 60 |
+
All six tags are emitted by PDVD's `OmnibusSigProc` chain (debug +
|
| 61 |
+
multi-plane-protection mode). Relative to the older 4-channel deployment,
|
| 62 |
+
the two additional tags are `tight_lf` and `decon_charge`; the order matches
|
| 63 |
+
the PDHD 6-channel model exactly.
|
| 64 |
+
|
| 65 |
+
- **`nchannels = 476`** per plane. The two induction planes U and V are
|
| 66 |
+
processed sequentially by two `DNNROIFinding` nodes per anode (sharing one
|
| 67 |
+
`TorchService`). The W (collection) plane is not consumed.
|
| 68 |
+
|
| 69 |
+
- **`nticks = 1600`**, from PDVD's raw `6400` ticks after `tick_per_slice = 4`
|
| 70 |
+
downsampling inside the C++ node.
|
| 71 |
+
|
| 72 |
+
### Normalization (baked in)
|
| 73 |
+
|
| 74 |
+
The model was trained on inputs divided by **per-channel** z-scales. Because
|
| 75 |
+
`DNNROIFinding` can apply only a single **scalar** `input_scale`, the
|
| 76 |
+
per-channel division is **baked into the `.ts` module** as a fixed
|
| 77 |
+
normalization layer. Therefore run this model with **`input_scale = 1.0`**.
|
| 78 |
+
|
| 79 |
+
The baked-in z-scales are the **cross-anode mean**:
|
| 80 |
+
|
| 81 |
+
```
|
| 82 |
+
[766.1332, 4000.0, 4000.0, 762.4834, 1679.252, 11827.907]
|
| 83 |
+
(loose_lf, mp2_roi, mp3_roi, tight_lf, decon_charge, gauss)
|
| 84 |
+
```
|
| 85 |
+
|
| 86 |
+
Per-anode z-scales differ (channel 0 runs ~50% higher on the top CRP,
|
| 87 |
+
anodes 4–7, than the bottom CRP, anodes 0–3); a single cross-anode-mean set is
|
| 88 |
+
shipped as an approximation validated to match per-half specialists.
|
| 89 |
+
|
| 90 |
+
### Tick padding
|
| 91 |
+
|
| 92 |
+
The C++ node rebins the time axis by `tick_per_slice = 4` before inference.
|
| 93 |
+
This network has **5 stride-2 down/up levels** in the (post-rebin) tick axis,
|
| 94 |
+
so the post-rebin width must be divisible by 2⁵ = 32 — i.e. the input
|
| 95 |
+
`nticks` must be a **multiple of `tick_per_slice · 32 = 128`**. Set
|
| 96 |
+
`tick_pad_multiple = 128`; the node pads up to the next 128-multiple before
|
| 97 |
+
inference and crops the output back to the original `input_ticks`:
|
| 98 |
+
|
| 99 |
+
| input `nticks` | padded `model_ticks` | output cropped to |
|
| 100 |
+
|---|---|---|
|
| 101 |
+
| 6000 | 6016 (= 47·128) | 6000 |
|
| 102 |
+
| 6400 | 6400 (already 50·128) | 6400 |
|
| 103 |
+
| 8000 | 8064 (= 63·128) | 8000 |
|
| 104 |
+
|
| 105 |
+
Do **not** lower `tick_pad_multiple` for this model — a mismatch surfaces as a
|
| 106 |
+
tensor-shape error inside the model at runtime, not as a toolkit-side check.
|
| 107 |
+
|
| 108 |
+
### Output tensor
|
| 109 |
+
|
| 110 |
+
Per-pixel ROI probability in `[0, 1]` (`sigmoid` already applied inside the
|
| 111 |
+
model). No additional sigmoid should be applied in Wire-Cell.
|
| 112 |
+
|
| 113 |
+
## 3. How to use
|
| 114 |
+
|
| 115 |
+
The model is loaded via a `TorchService` and consumed by the `DNNROIFinding`
|
| 116 |
+
node. Example wiring (analogous to the PDHD
|
| 117 |
+
[`wcls-rawdigit-dnnsp.jsonnet`](https://github.com/DUNE/dunereco/blob/25641a94aca58900c5e87f8e592f3d3aba166e6a/dunereco/DUNEWireCell/pdhd/wcls-rawdigit-dnnsp.jsonnet#L284)
|
| 118 |
+
pattern):
|
| 119 |
+
|
| 120 |
+
```jsonnet
|
| 121 |
+
// TorchService pointing at this model
|
| 122 |
+
local ts = {
|
| 123 |
+
type: "TorchService",
|
| 124 |
+
name: "dnnroi",
|
| 125 |
+
data: {
|
| 126 |
+
model: "dnnroi/pdvd/pipe_distill_transformer_6ch.ts",
|
| 127 |
+
device: "cpu", // or "gpu"
|
| 128 |
+
concurrency: 1,
|
| 129 |
+
},
|
| 130 |
+
};
|
| 131 |
+
|
| 132 |
+
// DNN-ROI node, wired per anode; input_scale=1.0 because normalization
|
| 133 |
+
// is baked into the .ts (see §2), and tick_pad_multiple=128 (see §2).
|
| 134 |
+
// The dnnroi helper is imported from
|
| 135 |
+
// pgrapher/experiment/protodunevd/dnnroi_pp.jsonnet.
|
| 136 |
+
local dnnroi = import 'pgrapher/experiment/protodunevd/dnnroi_pp.jsonnet';
|
| 137 |
+
|
| 138 |
+
dnnroi(tools.anodes[n], ts, output_scale=1.0,
|
| 139 |
+
nticks=params.daq.nticks, nchunks=1),
|
| 140 |
+
```
|
| 141 |
+
|
| 142 |
+
Notes:
|
| 143 |
+
- Run with **`input_scale = 1.0`** and **`tick_pad_multiple = 128`**
|
| 144 |
+
(both set by `protodunevd/dnnroi_pp.jsonnet`).
|
| 145 |
+
- Loaded by the toolkit C++ node `DNNROIFinding`, which processes the U and V
|
| 146 |
+
induction planes sequentially (each plane runs its own forward call, sharing
|
| 147 |
+
one `TorchService`). The W plane is routed through a `PlaneSelector`
|
| 148 |
+
passthrough of standard SP gauss.
|
| 149 |
+
|
| 150 |
+
## 4. Limitations
|
| 151 |
+
|
| 152 |
+
- The **W (collection) plane is not processed**; downstream jsonnet routes it
|
| 153 |
+
through a `PlaneSelector` passthrough.
|
| 154 |
+
- The baked-in cross-anode-mean z-scales are an approximation (per-anode
|
| 155 |
+
z-scales differ, especially top vs bottom CRP — see §2).
|
| 156 |
+
- This is a **diagnostic / reference** model, not the recommended production
|
| 157 |
+
FP32 deployable (see the note at the top).
|
l1sp/pdhd/20260615/l1sp_dnn_pdhd_v1.meta.json
ADDED
|
@@ -0,0 +1,112 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"experiment_dir": "/nfs/data/1/xqian/toolkit-dev/l1sp_dl_tagger/experiments/stage_a_pu_round4",
|
| 3 |
+
"vae_ckpt": "/nfs/data/1/xqian/toolkit-dev/l1sp_dl_tagger/experiments/stage_b_vae/model_n16.pt",
|
| 4 |
+
"vae_n_lat": 16,
|
| 5 |
+
"git_sha": "708b942b199e2cc7395e9e3468b926b8146e171b",
|
| 6 |
+
"nbin": 256,
|
| 7 |
+
"amp_floor": 1.0,
|
| 8 |
+
"n_features": 30,
|
| 9 |
+
"feature_order": [
|
| 10 |
+
"nbin_fit",
|
| 11 |
+
"temp_sum",
|
| 12 |
+
"temp1_sum",
|
| 13 |
+
"temp2_sum",
|
| 14 |
+
"max_val",
|
| 15 |
+
"min_val",
|
| 16 |
+
"prev_gap",
|
| 17 |
+
"next_gap",
|
| 18 |
+
"flag",
|
| 19 |
+
"ratio",
|
| 20 |
+
"temp_sum_pos",
|
| 21 |
+
"temp_sum_neg",
|
| 22 |
+
"n_above_pos",
|
| 23 |
+
"n_above_neg",
|
| 24 |
+
"argmax_tick",
|
| 25 |
+
"argmin_tick",
|
| 26 |
+
"sig_peak",
|
| 27 |
+
"sig_integral",
|
| 28 |
+
"gmax",
|
| 29 |
+
"gauss_fill",
|
| 30 |
+
"gauss_fwhm_frac",
|
| 31 |
+
"roi_energy_frac",
|
| 32 |
+
"raw_asym_wide",
|
| 33 |
+
"core_lo",
|
| 34 |
+
"core_hi",
|
| 35 |
+
"core_length",
|
| 36 |
+
"core_fill",
|
| 37 |
+
"core_fwhm_frac",
|
| 38 |
+
"core_raw_asym_wide",
|
| 39 |
+
"vae_kl"
|
| 40 |
+
],
|
| 41 |
+
"scalar_feature_order": [
|
| 42 |
+
"nbin_fit",
|
| 43 |
+
"temp_sum",
|
| 44 |
+
"temp1_sum",
|
| 45 |
+
"temp2_sum",
|
| 46 |
+
"max_val",
|
| 47 |
+
"min_val",
|
| 48 |
+
"prev_gap",
|
| 49 |
+
"next_gap",
|
| 50 |
+
"flag",
|
| 51 |
+
"ratio",
|
| 52 |
+
"temp_sum_pos",
|
| 53 |
+
"temp_sum_neg",
|
| 54 |
+
"n_above_pos",
|
| 55 |
+
"n_above_neg",
|
| 56 |
+
"argmax_tick",
|
| 57 |
+
"argmin_tick",
|
| 58 |
+
"sig_peak",
|
| 59 |
+
"sig_integral",
|
| 60 |
+
"gmax",
|
| 61 |
+
"gauss_fill",
|
| 62 |
+
"gauss_fwhm_frac",
|
| 63 |
+
"roi_energy_frac",
|
| 64 |
+
"raw_asym_wide",
|
| 65 |
+
"core_lo",
|
| 66 |
+
"core_hi",
|
| 67 |
+
"core_length",
|
| 68 |
+
"core_fill",
|
| 69 |
+
"core_fwhm_frac",
|
| 70 |
+
"core_raw_asym_wide"
|
| 71 |
+
],
|
| 72 |
+
"kl_index": 29,
|
| 73 |
+
"default_threshold": 0.9945,
|
| 74 |
+
"threshold_notes": "default_threshold=0.9945 \u2014 set by --default-threshold at export time. Convention is to use the p99.9 of the data-corpus score distribution from the training run; see the experiment dir's notes.md for the value that was promoted.",
|
| 75 |
+
"model_io": {
|
| 76 |
+
"forward.inputs": [
|
| 77 |
+
{
|
| 78 |
+
"name": "waveform",
|
| 79 |
+
"shape": [
|
| 80 |
+
"B",
|
| 81 |
+
1,
|
| 82 |
+
2,
|
| 83 |
+
256
|
| 84 |
+
],
|
| 85 |
+
"dtype": "float32",
|
| 86 |
+
"notes": "channel 0 = raw/scale, channel 1 = decon/scale, where scale = max(|raw|.max, |decon|.max, 1.0); window = full ROI right-padded to 256, OR \u00b1128 ticks centered on argmax(|decon|) clamped to ROI bounds. The dim-1 axis is a dummy to satisfy WCT's Pytorch::from_itensor 4-D requirement."
|
| 87 |
+
},
|
| 88 |
+
{
|
| 89 |
+
"name": "scalars",
|
| 90 |
+
"shape": [
|
| 91 |
+
"B",
|
| 92 |
+
1,
|
| 93 |
+
1,
|
| 94 |
+
29
|
| 95 |
+
],
|
| 96 |
+
"dtype": "float32",
|
| 97 |
+
"notes": "29 scalars in scalar_feature_order"
|
| 98 |
+
}
|
| 99 |
+
],
|
| 100 |
+
"forward.output": {
|
| 101 |
+
"name": "score",
|
| 102 |
+
"shape": [
|
| 103 |
+
"B",
|
| 104 |
+
1,
|
| 105 |
+
1,
|
| 106 |
+
1
|
| 107 |
+
],
|
| 108 |
+
"dtype": "float32",
|
| 109 |
+
"notes": "sigmoid in [0, 1]; cut at default_threshold"
|
| 110 |
+
}
|
| 111 |
+
}
|
| 112 |
+
}
|
l1sp/pdvd/20260615/l1sp_dnn_pdvd_v1.meta.json
ADDED
|
@@ -0,0 +1,112 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"experiment_dir": "/nfs/data/1/xqian/toolkit-dev/l1sp_dl_tagger/experiments/stage_a_pu_round2_pdvd",
|
| 3 |
+
"vae_ckpt": "/nfs/data/1/xqian/toolkit-dev/l1sp_dl_tagger/experiments/stage_b_vae/model_n16.pt",
|
| 4 |
+
"vae_n_lat": 16,
|
| 5 |
+
"git_sha": "cd038ae0da106fd215a54a061824daa835f05fc6",
|
| 6 |
+
"nbin": 256,
|
| 7 |
+
"amp_floor": 1.0,
|
| 8 |
+
"n_features": 30,
|
| 9 |
+
"feature_order": [
|
| 10 |
+
"nbin_fit",
|
| 11 |
+
"temp_sum",
|
| 12 |
+
"temp1_sum",
|
| 13 |
+
"temp2_sum",
|
| 14 |
+
"max_val",
|
| 15 |
+
"min_val",
|
| 16 |
+
"prev_gap",
|
| 17 |
+
"next_gap",
|
| 18 |
+
"flag",
|
| 19 |
+
"ratio",
|
| 20 |
+
"temp_sum_pos",
|
| 21 |
+
"temp_sum_neg",
|
| 22 |
+
"n_above_pos",
|
| 23 |
+
"n_above_neg",
|
| 24 |
+
"argmax_tick",
|
| 25 |
+
"argmin_tick",
|
| 26 |
+
"sig_peak",
|
| 27 |
+
"sig_integral",
|
| 28 |
+
"gmax",
|
| 29 |
+
"gauss_fill",
|
| 30 |
+
"gauss_fwhm_frac",
|
| 31 |
+
"roi_energy_frac",
|
| 32 |
+
"raw_asym_wide",
|
| 33 |
+
"core_lo",
|
| 34 |
+
"core_hi",
|
| 35 |
+
"core_length",
|
| 36 |
+
"core_fill",
|
| 37 |
+
"core_fwhm_frac",
|
| 38 |
+
"core_raw_asym_wide",
|
| 39 |
+
"vae_kl"
|
| 40 |
+
],
|
| 41 |
+
"scalar_feature_order": [
|
| 42 |
+
"nbin_fit",
|
| 43 |
+
"temp_sum",
|
| 44 |
+
"temp1_sum",
|
| 45 |
+
"temp2_sum",
|
| 46 |
+
"max_val",
|
| 47 |
+
"min_val",
|
| 48 |
+
"prev_gap",
|
| 49 |
+
"next_gap",
|
| 50 |
+
"flag",
|
| 51 |
+
"ratio",
|
| 52 |
+
"temp_sum_pos",
|
| 53 |
+
"temp_sum_neg",
|
| 54 |
+
"n_above_pos",
|
| 55 |
+
"n_above_neg",
|
| 56 |
+
"argmax_tick",
|
| 57 |
+
"argmin_tick",
|
| 58 |
+
"sig_peak",
|
| 59 |
+
"sig_integral",
|
| 60 |
+
"gmax",
|
| 61 |
+
"gauss_fill",
|
| 62 |
+
"gauss_fwhm_frac",
|
| 63 |
+
"roi_energy_frac",
|
| 64 |
+
"raw_asym_wide",
|
| 65 |
+
"core_lo",
|
| 66 |
+
"core_hi",
|
| 67 |
+
"core_length",
|
| 68 |
+
"core_fill",
|
| 69 |
+
"core_fwhm_frac",
|
| 70 |
+
"core_raw_asym_wide"
|
| 71 |
+
],
|
| 72 |
+
"kl_index": 29,
|
| 73 |
+
"default_threshold": 0.16,
|
| 74 |
+
"threshold_notes": "default_threshold=0.16 \u2014 set by --default-threshold at export time. Convention is to use the p99.9 of the data-corpus score distribution from the training run; see the experiment dir's notes.md for the value that was promoted.",
|
| 75 |
+
"model_io": {
|
| 76 |
+
"forward.inputs": [
|
| 77 |
+
{
|
| 78 |
+
"name": "waveform",
|
| 79 |
+
"shape": [
|
| 80 |
+
"B",
|
| 81 |
+
1,
|
| 82 |
+
2,
|
| 83 |
+
256
|
| 84 |
+
],
|
| 85 |
+
"dtype": "float32",
|
| 86 |
+
"notes": "channel 0 = raw/scale, channel 1 = decon/scale, where scale = max(|raw|.max, |decon|.max, 1.0); window = full ROI right-padded to 256, OR \u00b1128 ticks centered on argmax(|decon|) clamped to ROI bounds. The dim-1 axis is a dummy to satisfy WCT's Pytorch::from_itensor 4-D requirement."
|
| 87 |
+
},
|
| 88 |
+
{
|
| 89 |
+
"name": "scalars",
|
| 90 |
+
"shape": [
|
| 91 |
+
"B",
|
| 92 |
+
1,
|
| 93 |
+
1,
|
| 94 |
+
29
|
| 95 |
+
],
|
| 96 |
+
"dtype": "float32",
|
| 97 |
+
"notes": "29 scalars in scalar_feature_order"
|
| 98 |
+
}
|
| 99 |
+
],
|
| 100 |
+
"forward.output": {
|
| 101 |
+
"name": "score",
|
| 102 |
+
"shape": [
|
| 103 |
+
"B",
|
| 104 |
+
1,
|
| 105 |
+
1,
|
| 106 |
+
1
|
| 107 |
+
],
|
| 108 |
+
"dtype": "float32",
|
| 109 |
+
"notes": "sigmoid in [0, 1]; cut at default_threshold"
|
| 110 |
+
}
|
| 111 |
+
}
|
| 112 |
+
}
|