{"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":"gpu","dataSources":[{"sourceType":"competition","sourceId":20270,"databundleVersionId":1222630},{"sourceType":"datasetVersion","sourceId":9797223,"datasetId":982170,"databundleVersionId":10042021},{"sourceType":"modelInstanceVersion","sourceId":604758,"databundleVersionId":14044948,"modelInstanceId":453536},{"sourceType":"kernelVersion","sourceId":267329574}],"dockerImageVersionId":31090,"isInternetEnabled":false,"language":"python","sourceType":"notebook","isGpuEnabled":true}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"import os, cv2, timm, torch, albumentations\nimport numpy as np, pandas as pd\nfrom torch.utils.data import Dataset, DataLoader\nfrom tqdm import tqdm\nimport torch.nn as nn\n\n# ========= CONFIG =========\nclass args:\n    batch_size = 32\n    image_size = 384\n    fold = 0\n    device = \"cuda\" if torch.cuda.is_available() else \"cpu\"\n    # ↓ change this path to your dataset name containing model_f0.bin\n    checkpoint_path = \"/kaggle/input/23bcs10050-loukik-thatte-melanoma-training/model_f0.bin\"\n    test_csv = \"/kaggle/input/siim-isic-melanoma-classification/test.csv\"\n    test_jpeg_dir = \"/kaggle/input/siim-isic-melanoma-classification/jpeg/test\"\n\n# ========= AUGMENTATION =========\nvalid_aug = albumentations.Compose([\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, p=1.0),\n], p=1.0)\n\n# ========= DATASET =========\nclass TestDataset(Dataset):\n    def __init__(self, image_paths, dense_features, augmentations):\n        self.image_paths = image_paths\n        self.dense_features = dense_features.astype(np.float32)\n        self.augmentations = augmentations\n\n    def __len__(self): return len(self.image_paths)\n\n    def __getitem__(self, idx):\n        img = cv2.imread(self.image_paths[idx])\n        img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)\n        img = self.augmentations(image=img)[\"image\"]\n        img = np.transpose(img, (2, 0, 1)).astype(np.float32)\n        feats = self.dense_features[idx]\n        return {\n            \"image\": torch.tensor(img, dtype=torch.float),\n            \"features\": torch.tensor(feats, dtype=torch.float),\n        }\n\n# ========= MODEL =========\nclass CustomModel(nn.Module):\n    def __init__(self):\n        super().__init__()\n        self.model = timm.create_model(\"resnet50\", pretrained=False, in_chans=3)\n        self.dropout = nn.Dropout(0.5)\n        self.out = nn.Linear(1000, 1)\n    def forward(self, image, features=None):\n        x = self.model(image)\n        x = self.dropout(x)\n        x = self.out(x)\n        return x\n\n# ========= LOAD MODEL =========\nmodel = CustomModel()\nstate = torch.load(args.checkpoint_path, map_location=args.device)\n# remove 'model.' prefix if present\nstate = {k.replace(\"model.\", \"\"): v for k, v in state.items()}\nmodel.load_state_dict(state, strict=False)\nmodel.to(args.device)\nmodel.eval()\nprint(\" Model loaded from:\", args.checkpoint_path)\n\n# ========= LOAD TEST DATA =========\ntest_df = pd.read_csv(args.test_csv)\ntest_img_paths = [os.path.join(args.test_jpeg_dir, f\"{x}.jpg\") for x in test_df[\"image_name\"]]\ndense_features = np.zeros((len(test_df), 1), dtype=np.float32)\n\ntest_dataset = TestDataset(test_img_paths, dense_features, valid_aug)\ntest_loader = DataLoader(test_dataset, batch_size=args.batch_size, shuffle=False)\n\n# ========= INFERENCE =========\npreds = []\nwith torch.no_grad():\n    for batch in tqdm(test_loader, desc=\"Inferencing\"):\n        imgs = batch[\"image\"].to(args.device)\n        feats = batch[\"features\"].to(args.device)\n        logits = model(imgs, feats)\n        probs = torch.sigmoid(logits).squeeze(1).cpu().numpy()\n        preds.extend(probs.tolist())\n\n# ========= SUBMISSION =========\ntest_df[\"target\"] = preds\ntest_df[[\"image_name\", \"target\"]].to_csv(\"submission.csv\", index=False)\nprint(\"Saved submission.csv\")\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-10-11T19:10:29.726280Z","iopub.execute_input":"2025-10-11T19:10:29.726821Z","iopub.status.idle":"2025-10-11T19:26:30.651819Z","shell.execute_reply.started":"2025-10-11T19:10:29.726789Z","shell.execute_reply":"2025-10-11T19:26:30.651203Z"}},"outputs":[],"execution_count":null}]}