{"metadata":{"kernelspec":{"name":"python3","display_name":"Python 3","language":"python"},"language_info":{"name":"python","version":"3.11.13","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"},"colab":{"machine_shape":"hm","gpuType":"T4"},"accelerator":"GPU","kaggle":{"accelerator":"nvidiaTeslaT4","dataSources":[{"sourceId":20270,"databundleVersionId":1222630,"sourceType":"competition"},{"sourceId":25383,"databundleVersionId":2684322,"sourceType":"competition"},{"sourceId":9797223,"sourceType":"datasetVersion","datasetId":982170},{"sourceId":80230206,"sourceType":"kernelVersion"},{"sourceId":265823575,"sourceType":"kernelVersion"}],"dockerImageVersionId":31090,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":true}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"import sys\nsys.path.append(\"../input/tez-lib/\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-10-06T16:30:34.002396Z","iopub.execute_input":"2025-10-06T16:30:34.002654Z","iopub.status.idle":"2025-10-06T16:30:34.009403Z","shell.execute_reply.started":"2025-10-06T16:30:34.002634Z","shell.execute_reply":"2025-10-06T16:30:34.008717Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# import timm\n# from pprint import pprint\n# model_names = timm.list_models(pretrained=True)\n# pprint(model_names)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-10-06T16:30:34.010646Z","iopub.execute_input":"2025-10-06T16:30:34.010898Z","iopub.status.idle":"2025-10-06T16:30:34.022102Z","shell.execute_reply.started":"2025-10-06T16:30:34.010882Z","shell.execute_reply":"2025-10-06T16:30:34.021560Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import random\nimport numpy as np\nimport torch\nimport os\n\ndef seed_everything(seed):\n    random.seed(seed)\n    os.environ['PYTHONHASHSEED'] = str(seed)\n    np.random.seed(seed)\n    torch.manual_seed(seed)\n    torch.cuda.manual_seed(seed)\n    torch.backends.cudnn.deterministic = True\n    \nseed_everything(42)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-10-06T16:30:34.022805Z","iopub.execute_input":"2025-10-06T16:30:34.023020Z","iopub.status.idle":"2025-10-06T16:30:37.688968Z","shell.execute_reply.started":"2025-10-06T16:30:34.023005Z","shell.execute_reply":"2025-10-06T16:30:37.688187Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import torch.nn as nn\n\nfrom tez import Tez, TezConfig\nimport tez\nimport albumentations\nimport pandas as pd\nimport cv2\nimport numpy as np\nimport timm\nimport torch.nn as nn\nfrom sklearn import metrics\nimport torch\nfrom tez.callbacks import EarlyStopping\nfrom tqdm import tqdm\nfrom sklearn.metrics import roc_auc_score","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-10-06T16:30:37.690226Z","iopub.execute_input":"2025-10-06T16:30:37.690526Z","iopub.status.idle":"2025-10-06T16:30:46.913194Z","shell.execute_reply.started":"2025-10-06T16:30:37.690508Z","shell.execute_reply":"2025-10-06T16:30:46.912418Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"np.Inf = np.inf","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-10-06T16:30:46.913962Z","iopub.execute_input":"2025-10-06T16:30:46.914415Z","iopub.status.idle":"2025-10-06T16:30:46.918037Z","shell.execute_reply.started":"2025-10-06T16:30:46.914394Z","shell.execute_reply":"2025-10-06T16:30:46.917219Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"class args:\n    batch_size = 8 \n    image_size = 384\n    epochs = 10 \n    fold = 0 ","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-10-06T16:30:46.919156Z","iopub.execute_input":"2025-10-06T16:30:46.919437Z","iopub.status.idle":"2025-10-06T16:30:47.020417Z","shell.execute_reply.started":"2025-10-06T16:30:46.919397Z","shell.execute_reply":"2025-10-06T16:30:47.019719Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"MODELS_TO_TRAIN = [\"resnet50\", \"vgg19\", \"inception_v3\"]","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-10-06T16:30:47.021249Z","iopub.execute_input":"2025-10-06T16:30:47.021492Z","iopub.status.idle":"2025-10-06T16:30:47.031285Z","shell.execute_reply.started":"2025-10-06T16:30:47.021470Z","shell.execute_reply":"2025-10-06T16:30:47.030718Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"class targetDataset:\n    def __init__(self, image_paths, dense_features, targets, augmentations):\n        self.image_paths = image_paths\n        self.dense_features = dense_features\n        self.targets = targets\n        self.augmentations = augmentations\n        \n    def __len__(self):\n        return len(self.image_paths)\n    \n    def __getitem__(self, item):\n        image = cv2.imread(self.image_paths[item])\n        image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)\n        \n        if self.augmentations is not None:\n            augmented = self.augmentations(image=image)\n            image = augmented[\"image\"]\n            \n        image = np.transpose(image, (2, 0, 1)).astype(np.float32)\n        \n        features = self.dense_features[item, :]\n        targets = self.targets[item]\n        \n        return {\n            \"image\": torch.tensor(image, dtype=torch.float),\n            \"features\": torch.tensor(features, dtype=torch.float),\n            \"targets\": torch.tensor(targets, dtype=torch.float),\n        }","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-10-06T16:30:47.033553Z","iopub.execute_input":"2025-10-06T16:30:47.034347Z","iopub.status.idle":"2025-10-06T16:30:47.041734Z","shell.execute_reply.started":"2025-10-06T16:30:47.034317Z","shell.execute_reply":"2025-10-06T16:30:47.041120Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"class targetModel(nn.Module):\n    def __init__(self, model_name=\"resnet50\", dense_dim=12, pretrained=True):\n        super().__init__()\n        self.model = timm.create_model(model_name, pretrained=pretrained, in_chans=3)\n        n_features = self.model.get_classifier().in_features\n        self.model.reset_classifier(0)\n        self.out = nn.Linear(n_features + dense_dim, 1)\n\n    # <<< FIX: The 'loss' parameter has been removed from the definition >>>\n    def monitor_metrics(self, outputs, targets):\n        outputs = torch.sigmoid(outputs).cpu().detach().numpy()\n        targets = targets.cpu().detach().numpy()\n        try:\n            auc = roc_auc_score(targets, outputs)\n        except ValueError:\n            auc = 0.5\n        return {\"auc\": torch.tensor(auc)}\n        \n    def optimizer_scheduler(self):\n        opt = torch.optim.AdamW(self.parameters(), lr=1e-4, weight_decay=1e-6)\n        sch = torch.optim.lr_scheduler.CosineAnnealingWarmRestarts(\n            opt, T_0=10, T_mult=1, eta_min=1e-6, last_epoch=-1\n        )\n        return opt, sch\n\n    def forward(self, image, features, targets=None):\n        image_features = self.model(image)\n        x = torch.cat([image_features, features], dim=1)\n        output = self.out(x)\n        \n        if targets is not None:\n            pos_weight = torch.tensor([55.7]).to(image.device)\n            loss_fn = nn.BCEWithLogitsLoss(pos_weight=pos_weight)\n            loss = loss_fn(output, targets.view(-1, 1))\n            \n            # This call now correctly matches the method definition above\n            metrics = self.monitor_metrics(output, targets)\n            \n            return output, loss, metrics\n        return output, 0, {}","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-10-06T16:30:47.042337Z","iopub.execute_input":"2025-10-06T16:30:47.042548Z","iopub.status.idle":"2025-10-06T16:30:47.053693Z","shell.execute_reply.started":"2025-10-06T16:30:47.042532Z","shell.execute_reply":"2025-10-06T16:30:47.053076Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"train_aug = albumentations.Compose(\n    [\n#         albumentations.Resize(args.image_size, args.image_size, p=1),\n        albumentations.LongestMaxSize(args.image_size, p=1),\n        albumentations.PadIfNeeded(args.image_size,args.image_size, p=1,border_mode=0),\n        \n       albumentations.HorizontalFlip(p=0.5),\n       albumentations.VerticalFlip(p=0.1),\n       albumentations.Rotate(limit=180, p=0.5),\n       albumentations.ShiftScaleRotate(\n                shift_limit=0.1, scale_limit=0.1, rotate_limit=45, p=0.5\n            ),\n        \n        albumentations.HueSaturationValue(\n            hue_shift_limit=0.2, sat_shift_limit=0.2, val_shift_limit=0.2, p=0.5\n        ),\n        albumentations.RandomBrightnessContrast(\n            brightness_limit=(-0.1, 0.1), contrast_limit=(-0.1, 0.1), p=0.5\n        ),\n        albumentations.Normalize(\n            mean=[0.485, 0.456, 0.406],\n            std=[0.229, 0.224, 0.225],\n            max_pixel_value=255.0,\n            p=1.0,\n        ),\n    ],\n    p=1.0,\n)\n\nvalid_aug = albumentations.Compose(\n    [\n#         albumentations.Resize(args.image_size, args.image_size, p=1),\n        albumentations.LongestMaxSize(args.image_size, p=1),\n        albumentations.PadIfNeeded(args.image_size,args.image_size, p=1,border_mode=0),\n        albumentations.Normalize(\n            mean=[0.485, 0.456, 0.406],\n            std=[0.229, 0.224, 0.225],\n            max_pixel_value=255.0,\n            p=1.0,\n        ),\n    ],\n    p=1.0,\n)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-10-06T16:30:47.054461Z","iopub.execute_input":"2025-10-06T16:30:47.055112Z","iopub.status.idle":"2025-10-06T16:30:47.076925Z","shell.execute_reply.started":"2025-10-06T16:30:47.055095Z","shell.execute_reply":"2025-10-06T16:30:47.076303Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"df = pd.read_csv(\"/kaggle/input/siim-isic-melanoma-classification/train.csv\")\ndf_folds = pd.read_csv(\"/kaggle/input/ajai-sharan-velmurugan-23bcs10154-k-folds-siim/train_5folds.csv\")\ndf['kfold'] = df_folds['kfold']","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-10-06T16:30:47.077597Z","iopub.execute_input":"2025-10-06T16:30:47.077983Z","iopub.status.idle":"2025-10-06T16:30:47.255389Z","shell.execute_reply.started":"2025-10-06T16:30:47.077965Z","shell.execute_reply":"2025-10-06T16:30:47.254857Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"df.columns","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-10-06T16:30:47.256039Z","iopub.execute_input":"2025-10-06T16:30:47.256241Z","iopub.status.idle":"2025-10-06T16:30:47.262778Z","shell.execute_reply.started":"2025-10-06T16:30:47.256224Z","shell.execute_reply":"2025-10-06T16:30:47.262022Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"categorical_features = ['sex', 'anatom_site_general_challenge']\nnumerical_features = ['age_approx']\nfeatures_to_use = categorical_features + numerical_features","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-10-06T16:30:47.263541Z","iopub.execute_input":"2025-10-06T16:30:47.264001Z","iopub.status.idle":"2025-10-06T16:30:47.272723Z","shell.execute_reply.started":"2025-10-06T16:30:47.263978Z","shell.execute_reply":"2025-10-06T16:30:47.272104Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"print(f\"Original number of columns: {df.shape[1]}\")\ndf = pd.get_dummies(df, columns=categorical_features, dummy_na=False)\nprint(f\"Number of columns after one-hot encoding: {df.shape[1]}\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-10-06T16:30:47.273474Z","iopub.execute_input":"2025-10-06T16:30:47.273716Z","iopub.status.idle":"2025-10-06T16:30:47.298207Z","shell.execute_reply.started":"2025-10-06T16:30:47.273694Z","shell.execute_reply":"2025-10-06T16:30:47.297601Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"one_hot_cols = [col for col in df.columns if any(f\"_{cat}\" in col for cat in categorical_features)]\ndense_features_list = numerical_features + one_hot_cols\nprint(f\"Final dense features being used ({len(dense_features_list)}): {dense_features_list}\")\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-10-06T16:30:47.298847Z","iopub.execute_input":"2025-10-06T16:30:47.299109Z","iopub.status.idle":"2025-10-06T16:30:47.303174Z","shell.execute_reply.started":"2025-10-06T16:30:47.299092Z","shell.execute_reply":"2025-10-06T16:30:47.302577Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"for model_name in MODELS_TO_TRAIN:\n    print(\"\\n\" + \"#\"*50)\n    print(f\"### Training Model: {model_name.upper()} | Fold: {args.fold} ###\")\n    print(\"#\"*50)\n\n    \n    df_train = df[df.kfold != args.fold].reset_index(drop=True)\n    df_valid = df[df.kfold == args.fold].reset_index(drop=True)\n    \n    train_img_paths = [f\"/kaggle/input/siim-isic-melanoma-classification/jpeg/train/{x}.jpg\" for x in df_train['image_name'].values]\n    valid_img_paths = [f\"/kaggle/input/siim-isic-melanoma-classification/jpeg/train/{x}.jpg\" for x in df_valid['image_name'].values]\n    \n    \n    train_dataset = targetDataset(\n        image_paths=train_img_paths,\n        dense_features=df_train[dense_features_list].values,\n        targets=df_train.target.values,\n        augmentations=train_aug,\n    )\n    valid_dataset = targetDataset(\n        image_paths=valid_img_paths,\n        dense_features=df_valid[dense_features_list].values,\n        targets=df_valid.target.values,\n        augmentations=valid_aug,\n    )\n\n    \n    model = targetModel(model_name=model_name, dense_dim=len(dense_features_list))\n    model = Tez(model)\n\n    \n    config = TezConfig(\n        training_batch_size=args.batch_size,\n        validation_batch_size=2 * args.batch_size,\n        epochs=args.epochs,\n        step_scheduler_after=\"epoch\",\n        step_scheduler_metric=\"valid_auc\",\n        fp16=True,\n        val_strategy=\"batch\",\n    )\n\n    \n    es = EarlyStopping(\n        monitor=\"valid_auc\",\n        model_path=f\"model_{model_name}_f{args.fold}.bin\",\n        patience=3,\n        mode=\"max\",\n        save_weights_only=True,\n    )\n\n    \n    model.fit(\n        train_dataset,\n        valid_dataset=valid_dataset,\n        callbacks=[es],\n        config=config,\n    )\n    print(f\"--- Training for {model_name} complete ---\")\n\nprint(\"\\nAll models have been trained and saved.\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-10-06T16:30:47.303952Z","iopub.execute_input":"2025-10-06T16:30:47.304265Z","iopub.status.idle":"2025-10-06T18:07:40.739804Z","shell.execute_reply.started":"2025-10-06T16:30:47.304239Z","shell.execute_reply":"2025-10-06T18:07:40.738839Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"","metadata":{"trusted":true},"outputs":[],"execution_count":null}]}