{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.12.13","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"},"kaggle":{"accelerator":"none","dataSources":[],"dockerImageVersionId":28755,"isInternetEnabled":false,"language":"python","sourceType":"notebook","isGpuEnabled":false}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"import os\nimport cv2\nimport random\nimport numpy as np\nimport pandas as pd\nimport matplotlib.pyplot as plt\n\nimport torch\nimport torch.nn as nn\nimport torch.nn.functional as F\nimport timm\n\nfrom torch.utils.data import Dataset, DataLoader\n\nfrom sklearn.preprocessing import LabelEncoder\nfrom sklearn.model_selection import StratifiedGroupKFold\n\nfrom sklearn.metrics import (\n    roc_auc_score,\n    roc_curve,\n    confusion_matrix,\n    accuracy_score,\n    precision_score,\n    recall_score,\n    f1_score,\n    average_precision_score,\n    ConfusionMatrixDisplay\n)\n\nimport albumentations as A\nfrom albumentations.pytorch import ToTensorV2\n\nfrom tqdm.auto import tqdm\nimport copy","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true,"execution":{"iopub.status.busy":"2026-06-19T16:17:45.568576Z","iopub.execute_input":"2026-06-19T16:17:45.568867Z","iopub.status.idle":"2026-06-19T16:18:35.177661Z","shell.execute_reply.started":"2026-06-19T16:17:45.568839Z","shell.execute_reply":"2026-06-19T16:18:35.176600Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def seed_everything(seed=42):\n\n    random.seed(seed)\n    np.random.seed(seed)\n\n    torch.manual_seed(seed)\n    torch.cuda.manual_seed(seed)\n\n    torch.backends.cudnn.deterministic = True\n    torch.backends.cudnn.benchmark = False\n\nseed_everything()","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"ISIC2019_IMG = (\n    \"/kaggle/input/datasets/cdeotte/jpeg-isic2019-512x512/train\"\n)\n\nISIC2020_IMG = (\n    \"/kaggle/input/competitions/siim-isic-melanoma-classification/jpeg/train\"\n)\n\nISIC2020_META = (\n    \"/kaggle/input/competitions/siim-isic-melanoma-classification/train.csv\"\n)\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-06-19T16:20:24.060650Z","iopub.execute_input":"2026-06-19T16:20:24.061034Z","iopub.status.idle":"2026-06-19T16:20:24.066335Z","shell.execute_reply.started":"2026-06-19T16:20:24.060999Z","shell.execute_reply":"2026-06-19T16:20:24.065353Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"df2020 = pd.read_csv(ISIC2020_META)\n\ndf2020[\"image_path\"] = df2020[\"image_name\"].apply(\n    lambda x: os.path.join(\n        ISIC2020_IMG,\n        x + \".jpg\"\n    )\n)\n\ndf2020[\"dataset\"] = \"2020\"\n\n# patient-wise grouping\ndf2020[\"group_id\"] = (\n    \"2020_\" +\n    df2020[\"patient_id\"].astype(str)\n)\n\ndf2020 = df2020[\n    [\n        \"image_name\",\n        \"group_id\",\n        \"sex\",\n        \"age_approx\",\n        \"anatom_site_general_challenge\",\n        \"target\",\n        \"image_path\",\n        \"dataset\"\n    ]\n]\n\nprint(df2020.shape)\ndf2020.head()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-06-19T16:20:47.331074Z","iopub.execute_input":"2026-06-19T16:20:47.331434Z","iopub.status.idle":"2026-06-19T16:20:47.503802Z","shell.execute_reply.started":"2026-06-19T16:20:47.331400Z","shell.execute_reply":"2026-06-19T16:20:47.502887Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"df2019 = pd.read_csv(\n    \"/kaggle/input/datasets/cdeotte/jpeg-isic2019-512x512/train.csv\"\n)\n\ndf2019[\"image_path\"] = df2019[\"image_name\"].apply(\n    lambda x: os.path.join(\n        ISIC2019_IMG,\n        x + \".jpg\"\n    )\n)\n\ndf2019[\"dataset\"] = \"2019\"\n\n# image-wise grouping\ndf2019[\"group_id\"] = (\n    \"2019_\" +\n    df2019[\"image_name\"].astype(str)\n)\n\ndf2019 = df2019[\n    [\n        \"image_name\",\n        \"group_id\",\n        \"sex\",\n        \"age_approx\",\n        \"anatom_site_general_challenge\",\n        \"target\",\n        \"image_path\",\n        \"dataset\"\n    ]\n]\n\nprint(df2019.shape)\ndf2019.head()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-06-19T16:21:15.820844Z","iopub.execute_input":"2026-06-19T16:21:15.821192Z","iopub.status.idle":"2026-06-19T16:21:15.936711Z","shell.execute_reply.started":"2026-06-19T16:21:15.821163Z","shell.execute_reply":"2026-06-19T16:21:15.935813Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"df = pd.concat(\n    [df2019, df2020],\n    ignore_index=True\n)\n\nprint(\"ISIC2019:\", len(df2019))\nprint(\"ISIC2020:\", len(df2020))\nprint(\"Merged   :\", len(df))\n\nprint(\"\\nClass Distribution\")\nprint(df[\"target\"].value_counts())\n\ndf.head()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-06-19T16:21:26.682798Z","iopub.execute_input":"2026-06-19T16:21:26.683170Z","iopub.status.idle":"2026-06-19T16:21:26.709483Z","shell.execute_reply.started":"2026-06-19T16:21:26.683137Z","shell.execute_reply":"2026-06-19T16:21:26.708494Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"df[\"age_approx\"] = (\n    df[\"age_approx\"]\n    .fillna(\n        df[\"age_approx\"].median()\n    )\n)\n\ndf[\"sex\"] = df[\"sex\"].map(\n    {\n        \"male\": 1,\n        \"female\": 0\n    }\n)\n\ndf[\"sex\"] = df[\"sex\"].fillna(-1)\n\ndf[\"anatom_site_general_challenge\"] = (\n    df[\"anatom_site_general_challenge\"]\n    .fillna(\"unknown\")\n)\n\nprint(df.isnull().sum())","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-06-19T16:21:41.551780Z","iopub.execute_input":"2026-06-19T16:21:41.552146Z","iopub.status.idle":"2026-06-19T16:21:41.591516Z","shell.execute_reply.started":"2026-06-19T16:21:41.552116Z","shell.execute_reply":"2026-06-19T16:21:41.590247Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"le = LabelEncoder()\n\ndf[\"site_encoded\"] = le.fit_transform(\n    df[\"anatom_site_general_challenge\"]\n)\n\nprint(\n    df[\n        [\n            \"image_path\",\n            \"age_approx\",\n            \"sex\",\n            \"site_encoded\",\n            \"target\"\n        ]\n    ].head()\n)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-06-19T16:21:51.906851Z","iopub.execute_input":"2026-06-19T16:21:51.907206Z","iopub.status.idle":"2026-06-19T16:21:51.933640Z","shell.execute_reply.started":"2026-06-19T16:21:51.907176Z","shell.execute_reply":"2026-06-19T16:21:51.932660Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"from sklearn.model_selection import StratifiedGroupKFold\n\ndf[\"fold\"] = -1\n\nsgkf = StratifiedGroupKFold(\n    n_splits=5,\n    shuffle=True,\n    random_state=42\n)\n\nfor fold, (_, val_idx) in enumerate(\n    sgkf.split(\n        df,\n        y=df[\"target\"],\n        groups=df[\"group_id\"]\n    )\n):\n    df.loc[val_idx, \"fold\"] = fold\n\nprint(df[\"fold\"].value_counts())","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-06-19T16:22:51.182269Z","iopub.execute_input":"2026-06-19T16:22:51.182666Z","iopub.status.idle":"2026-06-19T16:22:58.907014Z","shell.execute_reply.started":"2026-06-19T16:22:51.182633Z","shell.execute_reply":"2026-06-19T16:22:58.905996Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"df.to_csv(\n    \"isic_fold_assignments.csv\",\n    index=False\n)\n\nprint(\"Saved.\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-06-19T16:23:13.737359Z","iopub.execute_input":"2026-06-19T16:23:13.737662Z","iopub.status.idle":"2026-06-19T16:23:14.171303Z","shell.execute_reply.started":"2026-06-19T16:23:13.737635Z","shell.execute_reply":"2026-06-19T16:23:14.170420Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"","metadata":{"trusted":true},"outputs":[],"execution_count":null}]}