Data¶
ISIC 2017 dataset¶
ISIC 2017 is the primary dataset used to train, validate, and test the UNet2D segmentation model in SkiNet. The project uses the official predefined splits and does not re-shuffle them.
Citation: Codella N, Gutman D, Celebi ME, Helba B, Marchetti MA, Dusza S, Kalloo A, Liopyris K, Mishra N, Kittler H, Halpern A. “Skin Lesion Analysis Toward Melanoma Detection: A Challenge at the 2017 International Symposium on Biomedical Imaging (ISBI), Hosted by the International Skin Imaging Collaboration (ISIC)”. arXiv: 1710.05006
Class distribution¶
Three mutually exclusive classes, encoded as binary columns in the metadata CSV:
Class |
|
|
Training count |
|---|---|---|---|
Melanoma |
1 |
0 |
374 |
Seborrheic keratosis |
0 |
1 |
254 |
Nevus |
0 |
0 |
1372 |
Validation: 150 images. Test: 600 images. Class proportions are consistent across splits.
Expected directory structure¶
As generated by the ISIC 2017 challenge download:
<local_data_root>/
├── ISIC-2017_Training_Data/
│ └── ISIC-2017_Training_Data/ # archive extracts a same-named inner folder
│ ├── ISIC_0000000.jpg
│ └── ...
├── ISIC-2017_Training_Part1_GroundTruth/
│ └── ISIC-2017_Training_Part1_GroundTruth/
│ ├── ISIC_0000000_segmentation.png
│ └── ...
├── ISIC-2017_Training_Part3_GroundTruth.csv
├── ISIC-2017_Validation_Data/
├── ISIC-2017_Validation_Part1_GroundTruth/
├── ISIC-2017_Validation_Part3_GroundTruth.csv
├── ISIC-2017_Test_v2_Data/
├── ISIC-2017_Test_v2_Part1_GroundTruth/
└── ISIC-2017_Test_v2_Part3_GroundTruth.csv
Each *_Data/ and *_Part1_GroundTruth/ archive extracts to a same-named inner
folder, so image and mask files sit one level deeper than the top-level split
directories. This is why the glob patterns below contain an extra */ level.
File naming conventions¶
Images:
ISIC_XXXXXXX.jpg(7-digit zero-padded ID), inside the same-named inner folder under*_Data/.Masks:
ISIC_XXXXXXX_segmentation.png, binary PNG, inside the same-named inner folder under*_Part1_GroundTruth/.Diagnosis CSVs: One per split, named
ISIC-2017_{Split}_Part3_GroundTruth.csv, containingimage_id,melanoma, andseborrheic_keratosiscolumns.
The sampleid is the filename stem with _segmentation stripped (e.g. ISIC_0000000).
Preprocessing notes¶
Images are JPEG RGB; masks are binary PNG (values 0 or 255). No format conversion is required.
The metadata CSV generator reads file paths via glob patterns (
ISIC-2017_*_Data/*/*.jpgfor images,ISIC-2017_*_Part1_GroundTruth/*/*_segmentation.pngfor masks) and determines split membership from the parent directory name (Training/Validation/Test).Pre-computed per-channel normalization statistics for the ISIC 2017 training split:
mean = [0.699, 0.556, 0.512],std = [0.158, 0.156, 0.171]. Paste these underTRANSFORM_CONFIGasnormalization_mean/normalization_stdwithnormalization_mode: "standard". To recompute, run compute_dataset_stats.py — it reads the dataset from the YAML config, uses a single-pass pixel-weighted Welford algorithm over raw training images, and printsTRANSFORM_CONFIG-ready values:python -m SkiNet.ML.transformations.compute_dataset_stats --config main_config.yaml
Download: from ISIC website¶
Download the three splits (Training Data, Validation Data, Test Data) and the corresponding Part 1 and Part 3
ground truth archives from https://challenge.isic-archive.com/data/.
Extract all archives into the same <local_data_root>.
Download: from a prepared Kaggle dataset on Lightning Studio¶
pip install --quiet kaggle
Data is downloaded to Lightning Storage:
ISIC_OUT_DIR="${ISIC_OUT_DIR:-/teamspace/lightning_storage/isic2017/ISIC2017DATA_256}"
kaggle datasets download -d johnchfr/isic-2017 -p $ISIC_OUT_DIR --unzip
The ISIC directory is then bind-mounted inside the Docker container at CONTAINER_MOUNT_PATH="${CONTAINER_MOUNT_PATH:-/mnt/data}". When running inside the Docker container via
startup scripts, set local_data_root: "/mnt/data/".
WARNING: Download the data on the host (into Lightning Storage), then bind-mount that directory at /mnt/data — this is what the startup scripts do. If you instead launch a container manually and run kaggle datasets download -p /mnt/data inside it without mounting /mnt/data, the data goes to the container’s ephemeral layer and is lost when the container is removed. See development.md for the explicit --mount …,dst=/mnt/data flag.
Generate metadata CSV¶
Run once after download. Writes isic2017_metadata.csv into <local_data_root>:
python -m SkiNet.ML.datasets.preprocessing.metadata_csv_factory \
--dataset-key-str ISIC2017 \
--local-data-root "PATH_TO_LOCAL_DATA_ROOT_OR_BIND_MOUNT"
Metadata CSV columns¶
Column |
Type |
Description |
|---|---|---|
|
str |
Unique sample ID, e.g. |
|
str |
Path to the image or mask file |
|
str |
|
|
str |
|
|
float |
|
|
float |
|
Row granularity — one row per file, not per sample. Each sample contributes two rows: an
image row and a mask row (distinguished by datatype), sharing the same sampleid. The
diagnosis labels (melanoma, seborrheic_keratosis) are joined onto both rows, so filtering or
counting on the raw CSV without first restricting to datatype == "image" will double every count.
For a complete ISIC 2017 download, the generated isic2017_metadata.csv has:
image rows |
mask rows |
total |
|
|---|---|---|---|
train |
2000 |
2000 |
4000 |
val |
150 |
150 |
300 |
test |
600 |
600 |
1200 |
total |
2750 |
2750 |
5500 |
A row count that is short of 5500 indicates a partial download or an unmatched image/mask pair.
The merge is performed in ISIC2017BaseCSVBuilder.create_merged_isic2017_metadata() (isic2017_csv_builder.py) via DataFrame.merge(..., on="sampleid", how="left"). The path-derived metadata (images + masks rows) is the left frame; the diagnosis CSVs are concatenated across splits and their image_id column is renamed to sampleid before the join.
Config¶
For Docker container runs:
GENERAL_CONFIG:
experiment_type: "segmentation"
model: "UNET2D_MODEL"
dataset: "ISIC2017_DATASET"
DATA_CONFIG:
local_data_root: "/mnt/data/"
azure_data: False
split_random_seed: 100
For runs on e.g. Kaggle or any other machine, specify the path to the data root on that machine:
GENERAL_CONFIG:
experiment_type: "segmentation"
model: "UNET2D_MODEL"
dataset: "ISIC2017_DATASET"
DATA_CONFIG:
local_data_root: "/kaggle/working/isic2017_data_256/"
azure_data: False
split_random_seed: 100
Note: ISIC 2017 is large enough that
cache_in_ram: truemay exhaust available RAM on a Lightning Studio instance. Setcache_in_ram: falseinTRAIN_CONFIGwhen RAM is limited.
Metadata lazy loading¶
BaseDataConfig exposes dataset metadata as a pandas DataFrame through the metadata property.
The mechanism is lazy (no I/O at construction time), validated (required columns checked on
first load), and environment-aware (handles local paths and Azure Blob Storage transparently).
Lazy loading¶
The first call to .metadata triggers a CSV read and column validation. Subsequent calls return the
in-memory cache immediately:
cfg = ISIC2017DatasetConfig(local_data_root="/data/isic2017")
df = cfg.metadata # reads CSV, validates columns, caches
df = cfg.metadata # returns cache — no disk I/O
The cache lives in the private attribute _metadata (PrivateAttr, default None). It is excluded
from Pydantic validation and serialization.
Deepcopy behaviour¶
BaseDataConfig.__deepcopy__ resets _metadata to None in every copy. Config fields (paths, split
parameters) are deep-copied normally; only the transient cache is cleared.
During Optuna sweeps deepcopy(main_config) is called once per trial:
from copy import deepcopy
_ = main_config.dataconfig.metadata # loads once on template config
trial_cfg = deepcopy(main_config)
assert trial_cfg.dataconfig._metadata is None # no DataFrame duplication
df = trial_cfg.dataconfig.metadata # lazy-loads fresh copy per trial
Required subclass configuration¶
class MyDatasetConfig(BaseDataConfig):
METADATA_CSV_NAME: ClassVar[str] = "metadata.csv"
REQUIRED_COLUMNS: ClassVar[frozenset[str]] = frozenset({"sampleid", "datapath", "datatype"})
DATASET_KEY: ClassVar[Optional[DatasetKey]] = DatasetKey.MY_DATASET
A ValueError is raised on first .metadata access if required columns are absent or all empty.
Note:
REQUIRED_COLUMNSvalidates only the join/path columns (sampleid,datapath,datatype). The diagnosis columns (melanoma,seborrheic_keratosis) are not in this set, so missing or empty diagnosis labels pass validation but will break stratified splitting, which relies onsplit_stratify_column.