{"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":"gpu","dataSources":[{"sourceId":20270,"databundleVersionId":1222630,"sourceType":"competition"},{"sourceId":9797223,"sourceType":"datasetVersion","datasetId":982170},{"sourceId":80230206,"sourceType":"kernelVersion"},{"sourceId":266652527,"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-09-09T06:24:41.144862Z","iopub.execute_input":"2025-09-09T06:24:41.145141Z","iopub.status.idle":"2025-09-09T06:24:41.149338Z","shell.execute_reply.started":"2025-09-09T06:24:41.145122Z","shell.execute_reply":"2025-09-09T06:24:41.148622Z"}},"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-09-09T06:31:24.757576Z","iopub.execute_input":"2025-09-09T06:31:24.758251Z","iopub.status.idle":"2025-09-09T06:31:24.761386Z","shell.execute_reply.started":"2025-09-09T06:31:24.758225Z","shell.execute_reply":"2025-09-09T06:31:24.760629Z"}},"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-09-09T06:24:41.796277Z","iopub.execute_input":"2025-09-09T06:24:41.796642Z","iopub.status.idle":"2025-09-09T06:24:41.80599Z","shell.execute_reply.started":"2025-09-09T06:24:41.796619Z","shell.execute_reply":"2025-09-09T06:24:41.80541Z"}},"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","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-09-09T06:24:42.346696Z","iopub.execute_input":"2025-09-09T06:24:42.347353Z","iopub.status.idle":"2025-09-09T06:24:44.837495Z","shell.execute_reply.started":"2025-09-09T06:24:42.347331Z","shell.execute_reply":"2025-09-09T06:24:44.83689Z"}},"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-09-09T06:24:44.838601Z","iopub.execute_input":"2025-09-09T06:24:44.839062Z","iopub.status.idle":"2025-09-09T06:24:44.842804Z","shell.execute_reply.started":"2025-09-09T06:24:44.839042Z","shell.execute_reply":"2025-09-09T06:24:44.842174Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"class CustomDataset:\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-09-09T06:24:44.843633Z","iopub.execute_input":"2025-09-09T06:24:44.843957Z","iopub.status.idle":"2025-09-09T06:24:44.859207Z","shell.execute_reply.started":"2025-09-09T06:24:44.843932Z","shell.execute_reply":"2025-09-09T06:24:44.858627Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import torch.nn as nn\nfrom sklearn import metrics\nimport torch\n\nclass CustomModel(nn.Module):\n    def __init__(self):\n        super().__init__()        \n        self.model = timm.create_model(\"resnet50\", pretrained=True, in_chans=3)\n\n        \n        self.dropout = nn.Dropout(0.5)\n        self.out = nn.Linear(1000, 1) # Output size remains 1 for binary classification\n        \n        self.step_scheduler_after = \"epoch\"\n\n\n    def monitor_metrics(self, outputs, targets, loss):\n        # Convert logits (outputs) to probabilities (for AUC)\n        probs = torch.sigmoid(outputs).cpu().detach().numpy()\n        # Convert targets to numpy array\n        targets = targets.cpu().detach().numpy()\n        \n        # Calculate ROC AUC\n        try:\n            auc = metrics.roc_auc_score(targets, probs)\n        except ValueError:\n            # Handle case where only one class is present in the batch/validation set\n            auc = 0.5 \n            \n        \n        auc_tensor = torch.tensor(auc, dtype=torch.float) \n            \n        return {\"auc\": auc_tensor}\n\n\n    def optimizer_scheduler(self):\n        opt = torch.optim.AdamW(self.parameters(), lr=2.5e-05, weight_decay=0.01)\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\n        x = self.model(image)\n        x = self.dropout(x)\n        x = self.out(x) # x are now logits\n        \n        if targets is not None:\n            # Using BCEWithLogitsLoss for stable binary classification\n            loss = nn.BCEWithLogitsLoss()(x.view(-1), targets.view(-1))\n            metrics = self.monitor_metrics(x, targets, loss)\n            return x, loss, metrics\n        return x, 0, {}\n","metadata":{"trusted":true},"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)\n","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"df = pd.read_csv(\"/kaggle/input/naga-chaitanya-23bcs10054/train_5folds.csv\")\ndf.head()","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"df['target'].value_counts()","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"i = 0\nprint(f\"[INFO] Training fold: {i} start\")\n\nargs.fold = 0\n\nprint(\"[INFO] Splitting training and validation data...\")\ndf_train = df[df.kfold != args.fold].reset_index(drop=True)\ndf_valid = df[df.kfold == args.fold].reset_index(drop=True)\n\ndense_features = []\n\nprint(f\"[INFO] Training samples: {len(df_train)}, Validation samples: {len(df_valid)}\")\n\ntrain_img_paths = [\n    f\"/kaggle/input/siim-isic-melanoma-classification/jpeg/train/{x}.jpg\"\n    for x in df_train[\"image_name\"].values\n]\nvalid_img_paths = [\n    f\"/kaggle/input/siim-isic-melanoma-classification/jpeg/train/{x}.jpg\"\n    for x in df_valid[\"image_name\"].values\n]\n\nprint(\"[INFO] Initializing datasets...\")\ntrain_dataset = CustomDataset(\n    image_paths=train_img_paths,\n    dense_features=df_train[dense_features].values,\n    targets=df_train.target.values,\n    augmentations=train_aug,\n)\n\nvalid_dataset = CustomDataset(\n    image_paths=valid_img_paths,\n    dense_features=df_valid[dense_features].values,\n    targets=df_valid.target.values,\n    augmentations=valid_aug,\n)\n\nprint(\"[INFO] Building model...\")\nmodel = CustomModel()\nmodel = Tez(model)\n\nconfig = 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    val_steps=900,\n)\n\nes = EarlyStopping(\n    monitor=\"valid_auc\",\n    model_path=f\"model_f{args.fold}.bin\",\n    patience=4,  # 3,\n    mode=\"max\",\n    save_weights_only=True,\n)\n\nprint(\"[INFO] Starting model training...\")\nmodel.fit(\n    train_dataset,\n    valid_dataset=valid_dataset,\n    callbacks=[es],\n    config=config,\n)\n\nprint(f\"[INFO] Training fold: {i} complete\")","metadata":{"trusted":true},"outputs":[],"execution_count":null}]}