HalmosiL szabopeter commited on
Commit
2a7d455
·
0 Parent(s):

Duplicate from szabopeter/roi-segresnet-2d

Browse files

Co-authored-by: Werner Peter <szabopeter@users.noreply.huggingface.co>

Files changed (4) hide show
  1. .gitattributes +35 -0
  2. README.md +115 -0
  3. config.yaml +45 -0
  4. model.pth +3 -0
.gitattributes ADDED
@@ -0,0 +1,35 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ *.7z filter=lfs diff=lfs merge=lfs -text
2
+ *.arrow filter=lfs diff=lfs merge=lfs -text
3
+ *.bin filter=lfs diff=lfs merge=lfs -text
4
+ *.bz2 filter=lfs diff=lfs merge=lfs -text
5
+ *.ckpt filter=lfs diff=lfs merge=lfs -text
6
+ *.ftz filter=lfs diff=lfs merge=lfs -text
7
+ *.gz filter=lfs diff=lfs merge=lfs -text
8
+ *.h5 filter=lfs diff=lfs merge=lfs -text
9
+ *.joblib filter=lfs diff=lfs merge=lfs -text
10
+ *.lfs.* filter=lfs diff=lfs merge=lfs -text
11
+ *.mlmodel filter=lfs diff=lfs merge=lfs -text
12
+ *.model filter=lfs diff=lfs merge=lfs -text
13
+ *.msgpack filter=lfs diff=lfs merge=lfs -text
14
+ *.npy filter=lfs diff=lfs merge=lfs -text
15
+ *.npz filter=lfs diff=lfs merge=lfs -text
16
+ *.onnx filter=lfs diff=lfs merge=lfs -text
17
+ *.ot filter=lfs diff=lfs merge=lfs -text
18
+ *.parquet filter=lfs diff=lfs merge=lfs -text
19
+ *.pb filter=lfs diff=lfs merge=lfs -text
20
+ *.pickle filter=lfs diff=lfs merge=lfs -text
21
+ *.pkl filter=lfs diff=lfs merge=lfs -text
22
+ *.pt filter=lfs diff=lfs merge=lfs -text
23
+ *.pth filter=lfs diff=lfs merge=lfs -text
24
+ *.rar filter=lfs diff=lfs merge=lfs -text
25
+ *.safetensors filter=lfs diff=lfs merge=lfs -text
26
+ saved_model/**/* filter=lfs diff=lfs merge=lfs -text
27
+ *.tar.* filter=lfs diff=lfs merge=lfs -text
28
+ *.tar filter=lfs diff=lfs merge=lfs -text
29
+ *.tflite filter=lfs diff=lfs merge=lfs -text
30
+ *.tgz filter=lfs diff=lfs merge=lfs -text
31
+ *.wasm filter=lfs diff=lfs merge=lfs -text
32
+ *.xz filter=lfs diff=lfs merge=lfs -text
33
+ *.zip filter=lfs diff=lfs merge=lfs -text
34
+ *.zst filter=lfs diff=lfs merge=lfs -text
35
+ *tfevents* filter=lfs diff=lfs merge=lfs -text
README.md ADDED
@@ -0,0 +1,115 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ---
2
+ license: apache-2.0
3
+ tags:
4
+ - medical-imaging
5
+ - segmentation
6
+ - image-segmentation
7
+ - ct
8
+ - lung
9
+ - monai
10
+ - pytorch
11
+ library_name: pytorch
12
+ pipeline_tag: image-segmentation
13
+ ---
14
+
15
+ # Lung ROI Segmentation — SegResNet (2D)
16
+
17
+ Per-slice 2D lung foreground (thoracic parenchyma) segmentation for
18
+ chest CT. Used as the ROI stage of a two-stage coarse-to-fine
19
+ pulmonary-nodule segmentation pipeline: its outputs are stacked into a
20
+ 3D lung bounding box that the downstream nodule model crops to.
21
+
22
+ ## Model details
23
+
24
+ - **Architecture**: [MONAI SegResNet](https://docs.monai.io/en/stable/networks.html#segresnet), 2D residual U-Net
25
+ - **Trainable parameters**: 6,904,081
26
+ - **Input**: `(1, 256, 256)` axial CT slice, intensity-normalised to `[0, 1]`
27
+ - **Output**: `(1, 256, 256)` sigmoid map; foreground = lung tissue
28
+ - **Framework**: PyTorch + MONAI
29
+
30
+ ## Data
31
+
32
+ Trained on the `unified` split (patient-grouped, dataset-stratified)
33
+ of a unified corpus assembled from three public sources:
34
+
35
+ - NLST
36
+ - NSCLC-Radiomics
37
+ - LIDC-IDRI
38
+
39
+ Slices per split: **365 014 train / 64 097 val / — test held out**.
40
+
41
+ ## Validation metrics
42
+
43
+ Evaluated on 64 097 val slices (≈ 4.2 × 10⁹ pixels), micro-averaged at
44
+ 0.5 threshold on sigmoid output.
45
+
46
+ | Metric | Value |
47
+ |-------------|-------:|
48
+ | mIoU | 0.9803 |
49
+ | Accuracy | 0.9953 |
50
+ | Precision | 0.9797 |
51
+ | Recall | 0.9857 |
52
+ | Dice (F1) | 0.9827 |
53
+
54
+ ## How to load & run inference
55
+
56
+ ```python
57
+ import yaml, torch
58
+ from monai.networks.nets import SegResNet
59
+
60
+ cfg = yaml.safe_load(open("config.yaml"))["model"]
61
+ model = SegResNet(
62
+ spatial_dims = cfg["spatial_dims"],
63
+ in_channels = cfg["in_channels"],
64
+ out_channels = cfg["out_channels"],
65
+ init_filters = cfg["init_filters"],
66
+ blocks_down = tuple(cfg["blocks_down"]),
67
+ blocks_up = tuple(cfg["blocks_up"]),
68
+ dropout_prob = cfg["dropout_prob"],
69
+ )
70
+ state = torch.load("model.pth", map_location="cpu", weights_only=True)
71
+ model.load_state_dict(state)
72
+ model.eval()
73
+
74
+ with torch.no_grad():
75
+ x = torch.randn(1, 1, 256, 256) # (B, C, H, W) — replace with your CT slice
76
+ prob = torch.sigmoid(model(x))
77
+ lung_mask = (prob > 0.5).to(torch.uint8)
78
+ ```
79
+
80
+ ## Training recipe
81
+
82
+ - **Loss**: `DiceLoss(sigmoid=True, squared_pred=True)`
83
+ - **Optimizer**: Adam (lr = 1e-3, weight decay = 1e-5)
84
+ - **Scheduler**: CosineAnnealingLR (T_max = 100, η_min = 1e-6)
85
+ - **Batch size**: 16
86
+ - **Samples/epoch**: 20 000 (random subsample of ~365 k train slices)
87
+ - **Epochs budget**: 100 | **best checkpoint at epoch 7 / 100**
88
+ - **Mixed precision**: bf16
89
+ - **Seed**: 42
90
+ - **Hardware**: 1 × NVIDIA H100 94 GB
91
+
92
+ Full config is included in this repo as `config.yaml`.
93
+
94
+ ## Reproducing training
95
+
96
+ Training code lives in an accompanying reproduction demo (published
97
+ separately). Once available, reproduce with:
98
+
99
+ ```bash
100
+ export DATA_ROOT=/path/to/unified # dir containing ct_2d/ and roi_sem_seg_2d/
101
+ python train.py --config config.yaml
102
+ ```
103
+
104
+ ## License & intended use
105
+
106
+ Model weights released under Apache 2.0. Training data was public but
107
+ covered by dataset-specific terms (NLST, NSCLC-Radiomics, LIDC-IDRI) —
108
+ users must comply with those separately when using the model on
109
+ comparable data.
110
+
111
+ **Not a medical device.** Not intended for clinical use. Research only.
112
+
113
+ ## Citation
114
+
115
+ Paper in preparation.
config.yaml ADDED
@@ -0,0 +1,45 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # ROI — 2D lung foreground segmentation.
2
+ # Reproduces the bundled checkpoint at checkpoints/roi/best.pth
3
+ # (val Dice = 0.96 on the unified split).
4
+
5
+ task: roi
6
+
7
+ data:
8
+ data_root: ${DATA_ROOT} # contains ct_2d/ and roi_sem_seg_2d/
9
+ split_json: data/splits/unified.json
10
+
11
+ preprocessing:
12
+ target_size: [256, 256]
13
+
14
+ model:
15
+ name: segresnet
16
+ spatial_dims: 2
17
+ in_channels: 1
18
+ out_channels: 1 # sigmoid
19
+ init_filters: 16
20
+ blocks_down: [1, 2, 2, 4, 4]
21
+ blocks_up: [1, 1, 1, 1]
22
+ dropout_prob: 0.1
23
+
24
+ training:
25
+ epochs: 100
26
+ batch_size: 16
27
+ samples_per_epoch: 20000 # subsample ~1/24 of ~475k slices
28
+ lr: 1.0e-3
29
+ weight_decay: 1.0e-5
30
+ val_interval: 1
31
+ device: cuda
32
+ amp: true
33
+ amp_dtype: bfloat16
34
+ seed: 42
35
+
36
+ scheduler:
37
+ T_max: 100
38
+ eta_min: 1.0e-6
39
+
40
+ checkpoints:
41
+ dir: checkpoints/roi
42
+ save_every: 10
43
+
44
+ logging:
45
+ dir: runs/roi
model.pth ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:d0edd572abb3a863f1bf6d71c62da285d7a92998189f0baf98a668660e65d7e3
3
+ size 27732822