{ "cells": [ { "cell_type": "markdown", "id": "67cdf9ad", "metadata": {}, "source": [ "# EF — ISIC 2017 UNet2D: held-out test score for the selected E4 checkpoint\n", "\n", "**Scope.** This notebook **runs the already-selected E4 checkpoint once over\n", "the held-out 600-image test split and reports its per-image mean Dice / IoU** (ISIC-2017 official\n", "averaging), then places the result in the context of the official ISIC 2017 challenge leaderboard.\n", "\n", "- **Checkpoint input:** seed 108, `epoch192` (`classical + attention_gate`, `lr = 3e-4`). Set `SELECTED_SEED`\n", " to score a different one.\n", "- **Threshold:** Found on the *validation* set in the E4 threshold-sweep\n", " notebook (`E4_isic2017_unet2d_threshold_sweep_analysis.ipynb`) and pasted here as `TAU_FROM_E4`.\n", "\n", "**Metric.** Per-image mean Dice/IoU via `SkiNet.Utils.analysis.test_scoring` — the same scoring core\n", "`calibrate_threshold.py` uses to batch-score all checkpoints." ] }, { "cell_type": "markdown", "id": "fbeb7cde", "metadata": {}, "source": [ "## 1. Inputs — selected checkpoint + threshold" ] }, { "cell_type": "code", "execution_count": 1, "id": "76d728e6", "metadata": {}, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "/home/zeus/miniconda3/envs/cloudspace/lib/python3.12/site-packages/azureml/dataprep/api/_loggerfactory.py:8: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81.\n", " import pkg_resources\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "Selected checkpoint : seed 108 -> mlruns/E4-isic2017-unet2d-thres-sweep-part2/1/a8cb781b18f64549a0d36ca9e096cee5/artifacts/checkpoints/best/epoch192.ckpt\n", "Thresholds to score : [0.5] (set TAU_FROM_E4 to add the val-found threshold)\n" ] } ], "source": [ "import sys\n", "from pathlib import Path\n", "\n", "import torch\n", "\n", "PROJECT_ROOT = Path('/teamspace/studios/this_studio/repos/SkiNet')\n", "sys.path.insert(0, str(PROJECT_ROOT))\n", "\n", "from SkiNet.ML.configs.load_config_from_yaml import load_config_from_yaml\n", "from SkiNet.ML.dataloaders.create_dataloaders import create_segmentation_dataloaders\n", "from SkiNet.Utils.analysis.test_scoring import build_ckpt_map, load_uncompiled, collect_probs, score_at_thresholds\n", "\n", "# -- inputs (decided upstream, not here) ---------------------------------------\n", "SELECTED_SEED = 108 # production checkpoint, chosen in E4 (epoch192)\n", "TAU_FROM_E4 = None # paste the val-found threshold from E4; None -> score only 0.5\n", "DATA_ROOT = \"/teamspace/lightning_storage/isic2017/ISIC2017DATA_256/\" # e.g. '/teamspace/lightning_storage/isic2017/ISIC2017DATA_256/'; None -> use config\n", "\n", "CONFIG_PATH = PROJECT_ROOT / 'main_config.yaml'\n", "DB1 = PROJECT_ROOT / 'mlruns' / 'E4-isic2017-unet2d-thres-sweep.db' # seeds 100-105\n", "DB2 = PROJECT_ROOT / 'mlruns' / 'E4-isic2017-unet2d-thres-sweep-part2.db' # seeds 106-109\n", "CKPT_GLOB = str(PROJECT_ROOT / 'mlruns' / 'E4-isic2017-unet2d-thres-sweep*' /\n", " '1' / '*' / 'artifacts' / 'checkpoints' / 'best' / '*.ckpt')\n", "\n", "ckpt_map = build_ckpt_map(DB1, DB2, glob_pattern=CKPT_GLOB, project_root=PROJECT_ROOT)\n", "ckpt_path = ckpt_map[SELECTED_SEED]\n", "\n", "thresholds = [0.5] + ([float(TAU_FROM_E4)] if TAU_FROM_E4 is not None else [])\n", "print(f\"Selected checkpoint : seed {SELECTED_SEED} -> {ckpt_path.relative_to(PROJECT_ROOT)}\")\n", "print(f\"Thresholds to score : {thresholds}\"\n", " + (\"\" if TAU_FROM_E4 is not None else \" (set TAU_FROM_E4 to add the val-found threshold)\"))" ] }, { "cell_type": "markdown", "id": "a6030508", "metadata": {}, "source": [ "## 2. Run test inference once\n", "\n", "Build the official test split, load the selected checkpoint uncompiled, and collect per-image\n", "sigmoid probabilities + masks in a single pass. Needs the ISIC-2017 data available (set `DATA_ROOT`\n", "if not on the configured path) and ideally a GPU." ] }, { "cell_type": "code", "execution_count": 2, "id": "576a3f9b", "metadata": {}, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "EarlyStopping monitor is set to default MetricsKey.VAL_MEAN_DICE_PER_IMAGE — make sure your LightningModule logs this exact key.\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ "/home/zeus/miniconda3/envs/cloudspace/lib/python3.12/site-packages/torch/utils/data/dataloader.py:1118: UserWarning: 'pin_memory' argument is set as true but no accelerator is found, then device pinned memory won't be used.\n", " super().__init__(loader)\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "Inference done on 600 test images (device=cpu).\n" ] } ], "source": [ "device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')\n", "\n", "cfg = load_config_from_yaml(CONFIG_PATH)\n", "if DATA_ROOT:\n", " cfg.dataconfig.local_data_root = DATA_ROOT\n", "cfg.trainconfig.test_on_val_split = False\n", "\n", "dl = create_segmentation_dataloaders(cfg)\n", "assert dl.test is not None, \"No test dataloader — check predefined_split / test_on_val_split.\"\n", "\n", "model = load_uncompiled(cfg, ckpt_path)\n", "test_probs, test_masks = collect_probs(model, dl.test, device)\n", "print(f\"Inference done on {test_probs.shape[0]} test images (device={device}).\")" ] }, { "cell_type": "markdown", "id": "a190b492", "metadata": {}, "source": [ "## 3. Held-out test score (per-image mean Dice, ISIC-official)" ] }, { "cell_type": "code", "execution_count": 3, "id": "21d5b133", "metadata": {}, "outputs": [ { "data": { "text/html": [ "\n", "
| threshold | \n", "role | \n", "dice | \n", "iou | \n", "dice_95ci | \n", "
|---|---|---|---|---|
| 0.50 | \n", "deployable default | \n", "0.8356 | \n", "0.7494 | \n", "[0.8208, 0.8494] | \n", "