{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"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"},"kaggle":{"accelerator":"nvidiaTeslaT4","dataSources":[{"sourceId":20270,"databundleVersionId":1222630,"isSourceIdPinned":false,"sourceType":"competition"},{"sourceId":9797223,"sourceType":"datasetVersion","datasetId":982170},{"sourceId":261002435,"sourceType":"kernelVersion"},{"sourceId":265636816,"sourceType":"kernelVersion"},{"sourceId":267308241,"sourceType":"kernelVersion"},{"sourceId":574351,"sourceType":"modelInstanceVersion","isSourceIdPinned":false,"modelInstanceId":429902,"modelId":446851},{"sourceId":574363,"sourceType":"modelInstanceVersion","isSourceIdPinned":false,"modelInstanceId":429911,"modelId":446860}],"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":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true,"execution":{"iopub.status.busy":"2025-10-11T16:32:05.087126Z","iopub.execute_input":"2025-10-11T16:32:05.087370Z","iopub.status.idle":"2025-10-11T16:32:05.094662Z","shell.execute_reply.started":"2025-10-11T16:32:05.087349Z","shell.execute_reply":"2025-10-11T16:32:05.094082Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import math\nimport cv2\nimport numpy as np\nimport pandas as pd\nimport torch\nimport torch.nn as nn\nfrom sklearn import metrics\nfrom tqdm import tqdm\nimport albumentations\nimport timm\nimport tez\nfrom tez import Tez, TezConfig\nfrom tez.callbacks import EarlyStopping\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-10-11T16:32:05.095752Z","iopub.execute_input":"2025-10-11T16:32:05.095931Z","iopub.status.idle":"2025-10-11T16:32:24.307156Z","shell.execute_reply.started":"2025-10-11T16:32:05.095916Z","shell.execute_reply":"2025-10-11T16:32:24.306565Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"class args:\n    batch_size = 64#16\n    image_size = 384 #64","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-10-11T16:32:24.307829Z","iopub.execute_input":"2025-10-11T16:32:24.308192Z","iopub.status.idle":"2025-10-11T16:32:24.311991Z","shell.execute_reply.started":"2025-10-11T16:32:24.308175Z","shell.execute_reply":"2025-10-11T16:32:24.311101Z"}},"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-10-11T16:32:24.312687Z","iopub.execute_input":"2025-10-11T16:32:24.312857Z","iopub.status.idle":"2025-10-11T16:32:24.344039Z","shell.execute_reply.started":"2025-10-11T16:32:24.312843Z","shell.execute_reply":"2025-10-11T16:32:24.343459Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"class CustomDataset:\n    def __init__(self, image_paths, dense_features, targets, augmentations):\n        # Initialize dataset with image paths, dense features, targets, and 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 total number of samples\n        return len(self.image_paths)\n    \n    def __getitem__(self, item):\n        # Read image from file\n        image = cv2.imread(self.image_paths[item])\n        image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)\n        \n        # Apply augmentations if provided\n        if self.augmentations is not None:\n            augmented = self.augmentations(image=image)\n            image = augmented[\"image\"]\n            \n        # Convert image to channel-first format and float32\n        image = np.transpose(image, (2, 0, 1)).astype(np.float32)\n        \n        # Get dense features and target for this item\n        features = self.dense_features[item, :]\n        targets = self.targets[item]\n        \n        # Return dictionary of tensors\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        }\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-10-11T16:32:24.345654Z","iopub.execute_input":"2025-10-11T16:32:24.345846Z","iopub.status.idle":"2025-10-11T16:32:24.359237Z","shell.execute_reply.started":"2025-10-11T16:32:24.345831Z","shell.execute_reply":"2025-10-11T16:32:24.358738Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"class CustomModel(nn.Module):\n    def __init__(self):\n        super().__init__()\n        # Base model (can switch architectures by changing model name)\n        self.model = timm.create_model(\"resnet50\", pretrained=False, in_chans=3)  # resnet50#resnet101#eca_nfnet_l1#resnest101e\n        \n        # Dropout for regularization\n        self.dropout = nn.Dropout(0.5)\n        \n        # Final output layer (binary classification)\n        self.out = nn.Linear(1000, 1)\n        # self.out = nn.Linear(1280+12, 1)\n        # self.out_final = nn.Linear(512, 1)\n        \n        # Scheduler step frequency\n        self.step_scheduler_after = \"epoch\"\n\n    def monitor_metrics(self, outputs, targets, loss):\n        # Monitor binary cross-entropy loss\n        bce = loss\n        if str(bce) == 'nan':\n            rmse = float('inf')\n        return {\"bce\": bce}\n\n    def optimizer_scheduler(self):\n        # Define optimizer and learning rate scheduler\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        # Forward pass through base model\n        x = self.model(image)\n        x = self.dropout(x)\n\n        # Optionally concatenate dense features\n        # x = torch.cat([x, features], dim=1)\n        # x = self.dropout(x)\n\n        # Output prediction\n        x = self.out(x)\n        # x = self.dropout(x)\n        # x = self.out_final(x)\n\n        # Compute loss and metrics if targets provided\n        if targets is not None:\n            loss = nn.BCEWithLogitsLoss()(x, targets.view(-1, 1).float())\n            metrics = self.monitor_metrics(x, targets, loss)\n            return x, loss, metrics\n\n        # During inference, only return predictions\n        return x, 0, {}\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-10-11T16:32:24.359993Z","iopub.execute_input":"2025-10-11T16:32:24.360223Z","iopub.status.idle":"2025-10-11T16:32:24.378862Z","shell.execute_reply.started":"2025-10-11T16:32:24.360196Z","shell.execute_reply":"2025-10-11T16:32:24.378195Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Test-time image augmentation pipeline\ntest_aug = albumentations.Compose(\n    [\n        # Resize image to the desired input size\n        albumentations.Resize(args.image_size, args.image_size, p=1),\n        \n        # Normalize image using ImageNet mean and std values\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,"execution":{"iopub.status.busy":"2025-10-11T16:32:24.379563Z","iopub.execute_input":"2025-10-11T16:32:24.379729Z","iopub.status.idle":"2025-10-11T16:32:24.399569Z","shell.execute_reply.started":"2025-10-11T16:32:24.379716Z","shell.execute_reply":"2025-10-11T16:32:24.399040Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Initialize list to store final predictions\nsuper_final_predictions = []\ni = 0\n\n# Load trained model\nmodel = CustomModel()\nmodel = Tez(model)\nmodel.load(\"/kaggle/input/10179-sarthakpandey-training-siim/model_f0.bin\", weights_only=True)\n\n# Read test data and prepare image paths\ndf_test = pd.read_csv(\"/kaggle/input/siim-isic-melanoma-classification/test.csv\")\ntest_img_paths = [f\"/kaggle/input/siim-isic-melanoma-classification/jpeg/test/{x}.jpg\" for x in df_test[\"image_name\"].values]\n\n# Define dense features (if any)\ndense_features = []\n\n# Create test dataset\ntest_dataset = CustomDataset(\n    image_paths=test_img_paths,\n    dense_features=df_test[dense_features].values,\n    targets=np.ones(len(test_img_paths)),  # dummy targets\n    augmentations=test_aug,\n)\n\n# Generate predictions\ntest_predictions = model.predict(test_dataset, batch_size=2 * args.batch_size, n_jobs=-1)\n\n# Flatten prediction outputs\nfinal_test_predictions = []\nfor preds in tqdm(test_predictions):\n    final_test_predictions.extend(preds.ravel().tolist())\n\n# Apply sigmoid to convert logits to probabilities\nsuper_final_predictions = torch.sigmoid(torch.tensor(final_test_predictions)).numpy()\n\n# Prepare submission file\ndf_test[\"target\"] = super_final_predictions\ndf_test = df_test[[\"image_name\", \"target\"]]\ndf_test.to_csv(\"submission.csv\", index=False)\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-10-11T16:32:24.400310Z","iopub.execute_input":"2025-10-11T16:32:24.400583Z","iopub.status.idle":"2025-10-11T16:40:12.247754Z","shell.execute_reply.started":"2025-10-11T16:32:24.400560Z","shell.execute_reply":"2025-10-11T16:40:12.247015Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"df_test.head()\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-10-11T16:40:12.248861Z","iopub.execute_input":"2025-10-11T16:40:12.249187Z","iopub.status.idle":"2025-10-11T16:40:12.270296Z","shell.execute_reply.started":"2025-10-11T16:40:12.249143Z","shell.execute_reply":"2025-10-11T16:40:12.269724Z"}},"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}]}