Pulmo / config.json
ariyul's picture
Add two-stage pipeline: 3D nodule-centre detector (HeatmapUNet3D, CPM 0.629) alongside the existing 2.5D concept-bottleneck characteriser (Student2p5D) with end-to-end inference wrapper.
745873a verified
Raw
History Blame Contribute Delete
2.92 kB
{
"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"
}