| { |
| "model_name": "Pulmo", |
| "description": "Two-stage explainable lung-nodule analysis pipeline on LUNA16/LIDC-IDRI: a 3D detector finds nodule centres, a 2.5D concept-bottleneck model characterises each candidate (detection, malignancy, 8 radiological concepts, segmentation).", |
| "pipeline": ["stage1_detector", "stage2_characteriser"], |
|
|
| "stage1_detector": { |
| "architecture": "HeatmapUNet3D", |
| "weights": "stage1_detector_v2.pth", |
| "role": "Locate nodule centres in a full CT volume (3D sliding window -> centre heatmap -> peaks).", |
| "base_channels": 16, |
| "patch_zyx": [64, 128, 128], |
| "input": "(B, 1, 64, 128, 128) float32 in [0, 1] (native resolution, no downsampling)", |
| "output": "(B, 1, 64, 128, 128) per-voxel nodule-centre probability heatmap", |
| "loss": "CenterNet penalty-reduced focal loss", |
| "metrics_scan_level": { |
| "CPM_at_8FP": 0.629, |
| "sensitivity_at_16FP_per_scan": 0.956, |
| "mean_centre_distance_mm": 1.85, |
| "note": "FROC on held-out internal val split. Operating point is tunable via peak_thresh; Stage 2 filters false positives." |
| } |
| }, |
|
|
| "stage2_characteriser": { |
| "architecture": "Student2p5D", |
| "weights": "student_2p5d_best.pth", |
| "role": "Per-candidate diagnosis + explanation from a 64^3 patch (its 7 central axial slices).", |
| "input": { |
| "n_slices": 7, |
| "slice_size": [64, 64], |
| "tensor_shape": "(B, 7, 64, 64)", |
| "dtype": "float32", |
| "value_range": [0.0, 1.0] |
| }, |
| "backbone": {"type": "UNet2D", "base_channels": 24, "trunk_dim": 384}, |
| "heads": { |
| "detection": "2 (nodule vs non-nodule)", |
| "concepts": "8 (LIDC radiological concepts, regression)", |
| "malignancy": "Linear(8 -> 2), concept bottleneck", |
| "segmentation": "(B, 1, 64, 64), middle axial slice" |
| }, |
| "n_concepts": 8, |
| "concept_names": [ |
| "subtlety", "internalStructure", "calcification", "sphericity", |
| "margin", "lobulation", "spiculation", "texture" |
| ], |
| "test_metrics_patch_level": { |
| "detection_auc": 0.997, |
| "malignancy_auc": 0.986, |
| "segmentation_dice": 0.859, |
| "note": "Held-out internal test split (patient-level split of LUNA16). Not externally validated." |
| }, |
| "teacher_reference_3d": { |
| "detection_auc": 0.998, |
| "malignancy_auc": 0.986, |
| "segmentation_dice": 0.857 |
| } |
| }, |
|
|
| "preprocessing": { |
| "hu_clip": [-1000, 1000], |
| "normalize": "(x - hu_min) / (hu_max - hu_min) -> [0, 1] (identical for both stages)", |
| "stage1_input": "raw (Z, Y, X) HU volume; sliding-window 3D patches of [64, 128, 128]", |
| "stage2_input": "7 central axial slices of a 64^3 patch centred on a Stage-1 candidate", |
| "spacing_order": "[z, y, x] in mm" |
| }, |
|
|
| "training_data": "LUNA16 (subset of LIDC-IDRI), 888 scans, patient-level 80/10/10 split", |
| "license": "cc-by-4.0", |
| "intended_use": "research only; not a medical device" |
| } |
|
|