{"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":25383,"databundleVersionId":2684322,"sourceType":"competition"},{"sourceId":20270,"databundleVersionId":1222630,"sourceType":"competition"},{"sourceId":9797223,"sourceType":"datasetVersion","datasetId":982170},{"sourceId":80230206,"sourceType":"kernelVersion"},{"sourceId":260782976,"sourceType":"kernelVersion"},{"sourceId":266635976,"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-09T10:55:24.685607Z","iopub.execute_input":"2025-09-09T10:55:24.685889Z","iopub.status.idle":"2025-09-09T10:55:24.689667Z","shell.execute_reply.started":"2025-09-09T10:55:24.685869Z","shell.execute_reply":"2025-09-09T10:55:24.688922Z"}},"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-09T10:55:24.691032Z","iopub.execute_input":"2025-09-09T10:55:24.691413Z","iopub.status.idle":"2025-09-09T10:55:24.703940Z","shell.execute_reply.started":"2025-09-09T10:55:24.691389Z","shell.execute_reply":"2025-09-09T10:55:24.703227Z"}},"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-09T10:55:24.704598Z","iopub.execute_input":"2025-09-09T10:55:24.704776Z","iopub.status.idle":"2025-09-09T10:55:24.719632Z","shell.execute_reply.started":"2025-09-09T10:55:24.704762Z","shell.execute_reply":"2025-09-09T10:55:24.718989Z"}},"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-09T10:55:24.720443Z","iopub.execute_input":"2025-09-09T10:55:24.720761Z","iopub.status.idle":"2025-09-09T10:55:24.735088Z","shell.execute_reply.started":"2025-09-09T10:55:24.720738Z","shell.execute_reply":"2025-09-09T10:55:24.734388Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"class args:\n    batch_size = 8\n    image_size = 384\n    epochs = 12 #10\n    fold = 0","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-09-09T10:55:24.736963Z","iopub.execute_input":"2025-09-09T10:55:24.737136Z","iopub.status.idle":"2025-09-09T10:55:24.752476Z","shell.execute_reply.started":"2025-09-09T10:55:24.737122Z","shell.execute_reply":"2025-09-09T10:55:24.751795Z"}},"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_path = self.image_paths[item]\n        image = cv2.imread(image_path)\n\n        # *** START FIX: Check if image was loaded successfully ***\n        if image is None:\n            raise RuntimeError(f\"Failed to load image at path: {image_path}\")\n        # *** END FIX ***\n            \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-09T10:55:24.753044Z","iopub.execute_input":"2025-09-09T10:55:24.753271Z","iopub.status.idle":"2025-09-09T10:55:24.767460Z","shell.execute_reply.started":"2025-09-09T10:55:24.753252Z","shell.execute_reply":"2025-09-09T10:55:24.766920Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"class CustomModel(nn.Module):\n    def __init__(self):\n        super().__init__()        \n        self.model = timm.create_model(\"resnet50\", pretrained=True, in_chans=3)#resnet50#resnet101#eca_nfnet_l1#resnest101e\n\n        \n        self.dropout = nn.Dropout(0.5)# increase dropout\n        # The output layer for binary classification should output 1 logit\n        self.out = nn.Linear(1000, 1)\n        \n        self.step_scheduler_after = \"epoch\"\n\n\n    def monitor_metrics(self, outputs, targets, loss):\n        # outputs are logits. Sigmoid them for probabilities for AUC calculation.\n        probas = torch.sigmoid(outputs)\n        \n        # We need to perform AUC calculation on CPU/NumPy\n        targets_np = targets.cpu().detach().numpy()\n        probas_np = probas.cpu().detach().numpy()\n        \n        # Calculate AUC (ROC-AUC)\n        try:\n            auc = metrics.roc_auc_score(targets_np, probas_np)\n        except ValueError:\n            # Handle the case where only one class is present in the batch\n            auc = 0.5 \n            \n        # *** FIX: Convert Python floats (loss.item() and auc) back to single-element PyTorch tensors\n        #           to satisfy the requirements of the Tez/accelerate framework's metric aggregation. ***\n        \n        # Return loss.item() as a tensor (loss itself is already a tensor, but loss.item() is a float)\n        # Using loss.detach() instead of loss.item() is safer if aggregation is done by the driver.\n        # But since we are creating a new dictionary, let's explicitly create the tensors on the correct device.\n        \n        device = outputs.device\n        \n        return {\n            \"loss\": loss.detach().to(device),\n            \"auc\": torch.tensor(auc, dtype=torch.float, device=device)\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        logits = self.out(x) \n\n        if targets is not None:\n            # BCEWithLogitsLoss is the standard for binary classification\n            loss = nn.BCEWithLogitsLoss()(logits, targets.view(-1, 1)) \n            metrics = self.monitor_metrics(logits, targets, loss)\n            return logits, loss, metrics\n            \n        return logits, 0, {}","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-09-09T10:55:24.768141Z","iopub.execute_input":"2025-09-09T10:55:24.768391Z","iopub.status.idle":"2025-09-09T10:55:24.782833Z","shell.execute_reply.started":"2025-09-09T10:55:24.768366Z","shell.execute_reply":"2025-09-09T10:55:24.782170Z"}},"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-09-09T10:55:24.783488Z","iopub.execute_input":"2025-09-09T10:55:24.783723Z","iopub.status.idle":"2025-09-09T10:55:24.807894Z","shell.execute_reply.started":"2025-09-09T10:55:24.783707Z","shell.execute_reply":"2025-09-09T10:55:24.807390Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"df = pd.read_csv(\"/kaggle/input/vinayak-paka-10118-k-folds-1/train_5folds.csv\")\ndf.head()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-09-09T10:55:24.808590Z","iopub.execute_input":"2025-09-09T10:55:24.808811Z","iopub.status.idle":"2025-09-09T10:55:24.869520Z","shell.execute_reply.started":"2025-09-09T10:55:24.808795Z","shell.execute_reply":"2025-09-09T10:55:24.868910Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"i=0\nprint(f'training fold: {i} start')\nargs.fold = 0\ndf_train = df[df.kfold != args.fold].reset_index(drop=True)\ndf_valid = df[df.kfold == args.fold].reset_index(drop=True)\ndense_features = [\n    \n]\ntrain_img_paths = [f\"/kaggle/input/siim-isic-melanoma-classification/jpeg/train/{x}.jpg\" for x in df_train[\"image_name\"].values]\nvalid_img_paths = [f\"/kaggle/input/siim-isic-melanoma-classification/jpeg/train/{x}.jpg\" for x in df_valid[\"image_name\"].values]\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\nmodel = CustomModel()\nmodel = Tez(model)\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    # Set step_scheduler_metric to monitor 'auc' for maximization\n    step_scheduler_metric=\"valid_auc\", \n    fp16=True,\n    val_strategy=\"batch\",\n    val_steps=900,\n)\n\nes = EarlyStopping(\n    # Monitor AUC and set mode to 'max'\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\nmodel.fit(\n    train_dataset,\n    valid_dataset=valid_dataset,\n    callbacks=[es],\n    config=config,\n)\nprint(f'training fold: {i} complete')\n   ","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-09-09T10:55:24.871051Z","iopub.execute_input":"2025-09-09T10:55:24.871427Z","iopub.status.idle":"2025-09-09T10:58:18.394709Z","shell.execute_reply.started":"2025-09-09T10:55:24.871398Z","shell.execute_reply":"2025-09-09T10:58:18.393831Z"}},"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},{"cell_type":"code","source":"","metadata":{"trusted":true},"outputs":[],"execution_count":null}]}