{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.12.13","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"},"kaggle":{"accelerator":"none","dataSources":[],"dockerImageVersionId":28755,"isInternetEnabled":false,"language":"python","sourceType":"notebook","isGpuEnabled":false}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"# This Python 3 environment comes with many helpful analytics libraries installed\n# It is defined by the kaggle/python Docker image: https://github.com/kaggle/docker-python\n# For example, here's several helpful packages to load\n\nimport numpy as np # linear algebra\nimport pandas as pd # data processing, CSV file I/O (e.g. pd.read_csv)\n\n# Input data files are available in the read-only \"../input/\" directory\n# For example, running this (by clicking run or pressing Shift+Enter) will list all files under the input directory\n\nimport os\nfor dirname, _, filenames in os.walk('/kaggle/input'):\n    for filename in filenames:\n        print(os.path.join(dirname, filename))\n\n# You can write up to 20GB to the current directory (/kaggle/working/) that gets preserved as output when you create a version using \"Save & Run All\" \n# You can also write temporary files to /kaggle/temp/, but they won't be saved outside of the current session\n\n# Use the kagglehub client library to attach Kaggle resources like competitions, datasets, and models to your session\n# Learn more about kagglehub: https://github.com/Kaggle/kagglehub/blob/main/README.md\n\nimport kagglehub\n# kagglehub.dataset_download('<owner>/<dataset-slug>')","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# import os\n# import cv2\n# import numpy as np\n# import pandas as pd\n\n# # --- Kaggle Paths ---\n# # Check the exact folder names in your Kaggle 'Data' pane.\n# # Usually, datasets have subfolders like 'train/masks' or just 'masks'.\n# # Update 'images' and 'masks' below if the dataset structure is different.\n# BASE_DIR = '/kaggle/input/wound-segmentation-images'\n# IMAGE_DIR = os.path.join(BASE_DIR, 'images') \n# MASK_DIR = os.path.join(BASE_DIR, 'masks')\n\n# def generate_severity_labels(mask_dir):\n#     data = []\n#     print(f\"Reading masks from: {mask_dir}\")\n    \n#     if not os.path.exists(mask_dir):\n#         print(\"Error: Mask directory not found. Please double-check the folder path in the Data pane!\")\n#         return None\n        \n#     valid_extensions = ('.png', '.jpg', '.jpeg')\n#     mask_files = [f for f in os.listdir(mask_dir) if f.lower().endswith(valid_extensions)]\n    \n#     print(f\"Found {len(mask_files)} mask files. Generating Surrogate Severity Labels...\")\n    \n#     for filename in mask_files:\n#         mask_path = os.path.join(mask_dir, filename)\n#         # Read in grayscale to ensure binary/single-channel processing\n#         mask = cv2.imread(mask_path, cv2.IMREAD_GRAYSCALE)\n        \n#         if mask is None:\n#             continue\n            \n#         total_pixels = mask.shape[0] * mask.shape[1]\n#         wound_pixels = np.count_nonzero(mask)\n#         area_percentage = (wound_pixels / total_pixels) * 100\n        \n#         # Area-threshold scheme for Severity\n#         if area_percentage < 5.0:\n#             severity, class_id = 'Mild', 0\n#         elif 5.0 <= area_percentage <= 15.0:\n#             severity, class_id = 'Moderate', 1\n#         else:\n#             severity, class_id = 'Severe', 2\n            \n#         data.append({\n#             'image_id': filename,\n#             'area_percentage': round(area_percentage, 2),\n#             'severity_class_id': class_id,\n#             'severity_label': severity\n#         })\n            \n#     df = pd.DataFrame(data)\n#     df.to_csv('severity_labels.csv', index=False)\n    \n#     print(\"\\n--- Process Complete ---\")\n#     print(f\"Saved {len(df)} labels to 'severity_labels.csv'.\")\n#     print(\"\\nClass Distribution:\")\n#     print(df['severity_label'].value_counts())\n    \n#     return df\n\n# # Execute the generation\n# df_labels = generate_severity_labels(MASK_DIR)\n# if df_labels is not None:\n#     print(\"\\nFirst 5 rows of the generated labels:\")\n#     print(df_labels.head())","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# import os\n\n# print(\"Inspecting Kaggle input directory...\\n\")\n# for dirname, _, filenames in os.walk('/kaggle/input'):\n#     print(f\"Folder: {dirname}\")\n#     if filenames:\n#          print(f\"  -> Contains {len(filenames)} files (e.g., {filenames[0]})\")","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# import os\n# import cv2\n# import numpy as np\n# import pandas as pd\n\n# # --- EXACT KAGGLE PATHS ---\n# BASE_DIR = '/kaggle/input/datasets/leoscode/wound-segmentation-images/data_wound_seg'\n\n# TRAIN_MASK_DIR = os.path.join(BASE_DIR, 'train_masks')\n# TEST_MASK_DIR = os.path.join(BASE_DIR, 'test_masks')\n\n# def generate_severity_labels():\n#     data = []\n    \n#     # Process both train and test mask folders\n#     for split, mask_dir in [('train', TRAIN_MASK_DIR), ('test', TEST_MASK_DIR)]:\n#         print(f\"Reading {split} masks from: {mask_dir}\")\n        \n#         mask_files = [f for f in os.listdir(mask_dir) if f.lower().endswith(('.png', '.jpg', '.jpeg'))]\n        \n#         for filename in mask_files:\n#             mask_path = os.path.join(mask_dir, filename)\n#             mask = cv2.imread(mask_path, cv2.IMREAD_GRAYSCALE)\n            \n#             if mask is None:\n#                 continue\n                \n#             total_pixels = mask.shape[0] * mask.shape[1]\n#             wound_pixels = np.count_nonzero(mask)\n#             area_percentage = (wound_pixels / total_pixels) * 100\n            \n#             # Area-threshold scheme for Surrogate Severity\n#             if area_percentage < 5.0:\n#                 severity, class_id = 'Mild', 0\n#             elif 5.0 <= area_percentage <= 15.0:\n#                 severity, class_id = 'Moderate', 1\n#             else:\n#                 severity, class_id = 'Severe', 2\n                \n#             data.append({\n#                 'image_id': filename,\n#                 'split': split,\n#                 'area_percentage': round(area_percentage, 2),\n#                 'severity_class_id': class_id,\n#                 'severity_label': severity\n#             })\n            \n#     df = pd.DataFrame(data)\n#     df.to_csv('severity_labels.csv', index=False)\n    \n#     print(\"\\n--- Process Complete ---\")\n#     print(f\"Saved {len(df)} labels to 'severity_labels.csv'.\")\n#     print(\"\\nOverall Class Distribution:\")\n#     print(df['severity_label'].value_counts())\n    \n#     print(\"\\nSplit Distribution:\")\n#     print(df['split'].value_counts())\n    \n#     return df\n\n# # Execute the generation\n# df_labels = generate_severity_labels()\n# if df_labels is not None:\n#     print(\"\\nFirst 5 rows of the generated labels:\")\n#     print(df_labels.head())","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# import os\n# import torch\n# import torch.nn as nn\n# import pandas as pd\n# from torch.utils.data import Dataset, DataLoader\n# from torchvision import transforms\n# from PIL import Image\n\n# # --- EXACT KAGGLE PATHS ---\n# BASE_DIR = '/kaggle/input/datasets/leoscode/wound-segmentation-images/data_wound_seg'\n# TRAIN_IMG_DIR = os.path.join(BASE_DIR, 'train_images')\n# TRAIN_MASK_DIR = os.path.join(BASE_DIR, 'train_masks')\n\n# # 1. CUSTOM DATASET CLASS\n# class WoundDataset(Dataset):\n#     def __init__(self, image_dir, mask_dir, labels_df, split='train', img_transform=None, mask_transform=None):\n#         self.image_dir = image_dir\n#         self.mask_dir = mask_dir\n#         # Filter dataframe by split (train/test)\n#         self.labels_df = labels_df[labels_df['split'] == split].reset_index(drop=True)\n#         self.img_transform = img_transform\n#         self.mask_transform = mask_transform\n\n#     def __len__(self):\n#         return len(self.labels_df)\n\n#     def __getitem__(self, idx):\n#         img_name = self.labels_df.iloc[idx]['image_id']\n#         img_path = os.path.join(self.image_dir, img_name)\n#         mask_path = os.path.join(self.mask_dir, img_name)\n\n#         image = Image.open(img_path).convert(\"RGB\")\n#         mask = Image.open(mask_path).convert(\"L\")\n\n#         if self.img_transform:\n#             image = self.img_transform(image)\n#         if self.mask_transform:\n#             mask = self.mask_transform(mask)\n#             mask = (mask > 0.5).float() # Ensure purely binary mask (0.0 or 1.0)\n\n#         return image, mask\n\n# # 2. U-NET BASELINE ARCHITECTURE\n# class DoubleConv(nn.Module):\n#     def __init__(self, in_channels, out_channels):\n#         super().__init__()\n#         self.conv = nn.Sequential(\n#             nn.Conv2d(in_channels, out_channels, 3, padding=1, bias=False),\n#             nn.BatchNorm2d(out_channels),\n#             nn.ReLU(inplace=True),\n#             nn.Conv2d(out_channels, out_channels, 3, padding=1, bias=False),\n#             nn.BatchNorm2d(out_channels),\n#             nn.ReLU(inplace=True)\n#         )\n#     def forward(self, x):\n#         return self.conv(x)\n\n# class UNet(nn.Module):\n#     def __init__(self, in_channels=3, out_channels=1):\n#         super().__init__()\n#         self.pool = nn.MaxPool2d(2)\n#         self.down1 = DoubleConv(in_channels, 64)\n#         self.down2 = DoubleConv(64, 128)\n#         self.down3 = DoubleConv(128, 256)\n#         self.down4 = DoubleConv(256, 512)\n\n#         self.up1 = nn.ConvTranspose2d(512, 256, 2, stride=2)\n#         self.conv1 = DoubleConv(512, 256)\n#         self.up2 = nn.ConvTranspose2d(256, 128, 2, stride=2)\n#         self.conv2 = DoubleConv(256, 128)\n#         self.up3 = nn.ConvTranspose2d(128, 64, 2, stride=2)\n#         self.conv3 = DoubleConv(128, 64)\n\n#         self.out_conv = nn.Conv2d(64, out_channels, 1)\n\n#     def forward(self, x):\n#         x1 = self.down1(x)\n#         x2 = self.down2(self.pool(x1))\n#         x3 = self.down3(self.pool(x2))\n#         x4 = self.down4(self.pool(x3))\n\n#         x = self.up1(x4)\n#         x = torch.cat([x, x3], dim=1)\n#         x = self.conv1(x)\n\n#         x = self.up2(x)\n#         x = torch.cat([x, x2], dim=1)\n#         x = self.conv2(x)\n\n#         x = self.up3(x)\n#         x = torch.cat([x, x1], dim=1)\n#         x = self.conv3(x)\n\n#         return torch.sigmoid(self.out_conv(x)) # Sigmoid for binary segmentation\n\n# # --- EXECUTION & TESTING ---\n# if __name__ == \"__main__\":\n#     # Define Transforms (Resizing to 512x512)\n#     img_transform = transforms.Compose([\n#         transforms.Resize((512, 512)),\n#         transforms.ToTensor(),\n#         transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])\n#     ])\n\n#     mask_transform = transforms.Compose([\n#         transforms.Resize((512, 512)),\n#         transforms.ToTensor()\n#     ])\n\n#     # Load Labels\n#     df = pd.read_csv('severity_labels.csv')\n    \n#     # Initialize Dataset and DataLoader\n#     train_dataset = WoundDataset(TRAIN_IMG_DIR, TRAIN_MASK_DIR, df, split='train', \n#                                  img_transform=img_transform, mask_transform=mask_transform)\n    \n#     train_loader = DataLoader(train_dataset, batch_size=4, shuffle=True)\n\n#     # Initialize Model\n#     device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')\n#     model = UNet().to(device)\n\n#     # Fetch one batch to verify shapes\n#     print(\"Fetching a batch of data...\")\n#     images, masks = next(iter(train_loader))\n#     images = images.to(device)\n\n#     # Forward pass\n#     print(\"Running forward pass through U-Net...\")\n#     outputs = model(images)\n\n#     print(f\"\\n--- Shape Verification ---\")\n#     print(f\"Hardware Device: {device}\")\n#     print(f\"Images Batch Shape: {images.shape}\")\n#     print(f\"Masks Batch Shape:  {masks.shape}\")\n#     print(f\"Model Output Shape: {outputs.shape}\")","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# import os\n# import cv2\n# import numpy as np\n# import pandas as pd\n# import torch\n# import torch.nn as nn\n# import torch.nn.functional as F\n# import torch.optim as optim\n# from torch.utils.data import Dataset, DataLoader\n# from torchvision import transforms\n# from PIL import Image\n# from transformers import SegformerForSemanticSegmentation\n# from tqdm import tqdm\n\n# # ==========================================\n# # 1. SETUP & PATHS\n# # ==========================================\n# BASE_DIR = '/kaggle/input/datasets/leoscode/wound-segmentation-images/data_wound_seg'\n# TRAIN_IMG_DIR = os.path.join(BASE_DIR, 'train_images')\n# TRAIN_MASK_DIR = os.path.join(BASE_DIR, 'train_masks')\n# TEST_IMG_DIR = os.path.join(BASE_DIR, 'test_images')\n# TEST_MASK_DIR = os.path.join(BASE_DIR, 'test_masks')\n\n# # ==========================================\n# # 2. GENERATE CSV (Auto-Recovery)\n# # ==========================================\n# def generate_severity_labels():\n#     print(\"Generating 'severity_labels.csv' from masks...\")\n#     data = []\n#     for split, mask_dir in [('train', TRAIN_MASK_DIR), ('test', TEST_MASK_DIR)]:\n#         if not os.path.exists(mask_dir): continue\n#         mask_files = [f for f in os.listdir(mask_dir) if f.lower().endswith(('.png', '.jpg', '.jpeg'))]\n#         for filename in mask_files:\n#             mask_path = os.path.join(mask_dir, filename)\n#             mask = cv2.imread(mask_path, cv2.IMREAD_GRAYSCALE)\n#             if mask is None: continue\n#             total_pixels = mask.shape[0] * mask.shape[1]\n#             wound_pixels = np.count_nonzero(mask)\n#             area_percentage = (wound_pixels / total_pixels) * 100\n            \n#             if area_percentage < 5.0: class_id = 0\n#             elif 5.0 <= area_percentage <= 15.0: class_id = 1\n#             else: class_id = 2\n                \n#             data.append({'image_id': filename, 'split': split, 'severity_class_id': class_id})\n#     df = pd.DataFrame(data)\n#     df.to_csv('severity_labels.csv', index=False)\n#     print(f\"Generated {len(df)} labels successfully.\\n\")\n#     return df\n\n# if not os.path.exists('severity_labels.csv'):\n#     df = generate_severity_labels()\n# else:\n#     df = pd.read_csv('severity_labels.csv')\n\n# # ==========================================\n# # 3. METRICS & LOSS FUNCTIONS\n# # ==========================================\n# class DiceLoss(nn.Module):\n#     def __init__(self, smooth=1e-6):\n#         super(DiceLoss, self).__init__()\n#         self.smooth = smooth\n#     def forward(self, inputs, targets):\n#         inputs = inputs.view(-1)\n#         targets = targets.view(-1)\n#         intersection = (inputs * targets).sum()                            \n#         dice = (2. * intersection + self.smooth) / (inputs.sum() + targets.sum() + self.smooth)  \n#         return 1 - dice\n\n# def calculate_iou(preds, labels, threshold=0.5):\n#     preds = (preds > threshold).float()\n#     intersection = (preds * labels).sum()\n#     union = preds.sum() + labels.sum() - intersection\n#     iou = (intersection + 1e-6) / (union + 1e-6)\n#     return iou.item()\n\n# # ==========================================\n# # 4. DATASET & DATALOADERS\n# # ==========================================\n# class WoundMultiTaskDataset(Dataset):\n#     def __init__(self, image_dir, mask_dir, labels_df, split='train', img_transform=None, mask_transform=None):\n#         self.image_dir = image_dir\n#         self.mask_dir = mask_dir\n#         self.labels_df = labels_df[labels_df['split'] == split].reset_index(drop=True)\n#         self.img_transform = img_transform\n#         self.mask_transform = mask_transform\n\n#     def __len__(self):\n#         return len(self.labels_df)\n\n#     def __getitem__(self, idx):\n#         row = self.labels_df.iloc[idx]\n#         img_name = row['image_id']\n#         severity_label = row['severity_class_id']\n        \n#         img_path = os.path.join(self.image_dir, img_name)\n#         mask_path = os.path.join(self.mask_dir, img_name)\n\n#         image = Image.open(img_path).convert(\"RGB\")\n#         mask = Image.open(mask_path).convert(\"L\")\n\n#         if self.img_transform:\n#             image = self.img_transform(image)\n#         if self.mask_transform:\n#             mask = self.mask_transform(mask)\n#             mask = (mask > 0.5).float() \n\n#         return image, mask, torch.tensor(severity_label, dtype=torch.long)\n\n# img_transform = transforms.Compose([\n#     transforms.Resize((512, 512)),\n#     transforms.ToTensor(),\n#     transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])\n# ])\n# mask_transform = transforms.Compose([\n#     transforms.Resize((512, 512)),\n#     transforms.ToTensor()\n# ])\n\n# train_dataset = WoundMultiTaskDataset(TRAIN_IMG_DIR, TRAIN_MASK_DIR, df, split='train', img_transform=img_transform, mask_transform=mask_transform)\n# test_dataset = WoundMultiTaskDataset(TEST_IMG_DIR, TEST_MASK_DIR, df, split='test', img_transform=img_transform, mask_transform=mask_transform)\n\n# # Using a batch size of 2 as per SegFormer requirements\n# train_loader = DataLoader(train_dataset, batch_size=2, shuffle=True)\n# test_loader = DataLoader(test_dataset, batch_size=2, shuffle=False)\n\n# # ==========================================\n# # 5. MULTI-TASK ARCHITECTURE\n# # ==========================================\n# class MultiTaskWoundModel(nn.Module):\n#     def __init__(self, base_model):\n#         super().__init__()\n#         self.base_model = base_model \n#         self.severity_head = nn.Sequential(\n#             nn.AdaptiveAvgPool2d(1),\n#             nn.Flatten(),\n#             nn.Linear(512, 128),  \n#             nn.ReLU(),\n#             nn.Dropout(0.3),\n#             nn.Linear(128, 3) \n#         )\n        \n#     def forward(self, pixel_values):\n#         outputs = self.base_model(pixel_values=pixel_values, output_hidden_states=True)\n#         encoder_features = outputs.hidden_states[-1] \n#         seg_logits = outputs.logits\n#         sev_logits = self.severity_head(encoder_features)\n#         return seg_logits, sev_logits\n\n# device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')\n# print(\"Initializing Model on Device:\", device)\n\n# # Load base SegFormer and ignore mismatched sizes for our custom binary segmentation head\n# base_model = SegformerForSemanticSegmentation.from_pretrained('nvidia/segformer-b2-finetuned-ade-512-512', num_labels=1, ignore_mismatched_sizes=True)\n# multi_task_model = MultiTaskWoundModel(base_model).to(device)\n\n# # ==========================================\n# # 6. TRAINING SETUP & LOOP (20 EPOCHS)\n# # ==========================================\n# bce_loss_fn = nn.BCEWithLogitsLoss()\n# dice_loss_fn = DiceLoss()\n\n# # Weights to handle class imbalance\n# weights = torch.tensor([1.0, 4.0, 13.0]).to(device) \n# severity_loss_fn = nn.CrossEntropyLoss(weight=weights)\n\n# optimizer = optim.AdamW(multi_task_model.parameters(), lr=5e-5) \n# num_epochs = 20 \n# lambda_bce = 0.5\n# alpha = 0.5 \n\n# print(f\"\\n--- Starting Full Multi-Task Training ({num_epochs} Epochs) ---\")\n\n# for epoch in range(num_epochs):\n#     # --- TRAINING PHASE ---\n#     multi_task_model.train()\n#     train_loss, train_iou, train_dice = 0, 0, 0\n    \n#     loop = tqdm(train_loader, desc=f'Epoch {epoch+1}/{num_epochs} [Train]')\n#     for images, masks, sev_labels in loop:\n#         images, masks, sev_labels = images.to(device), masks.to(device), sev_labels.to(device)\n        \n#         optimizer.zero_grad()\n#         seg_logits, sev_logits = multi_task_model(images)\n#         seg_logits = nn.functional.interpolate(seg_logits, size=masks.shape[-2:], mode=\"bilinear\", align_corners=False)\n        \n#         loss_seg_bce = bce_loss_fn(seg_logits, masks)\n#         seg_probs = torch.sigmoid(seg_logits)\n#         loss_seg_dice = dice_loss_fn(seg_probs, masks)\n        \n#         loss_seg = loss_seg_dice + (lambda_bce * loss_seg_bce)\n#         loss_sev = severity_loss_fn(sev_logits, sev_labels)\n        \n#         loss = loss_seg + (alpha * loss_sev)\n#         loss.backward()\n#         optimizer.step()\n        \n#         train_loss += loss.item()\n#         train_iou += calculate_iou(seg_probs, masks)\n#         train_dice += (1 - loss_seg_dice.item())\n#         loop.set_postfix(loss=loss.item())\n\n#     # --- VALIDATION PHASE ---\n#     multi_task_model.eval()\n#     val_loss, val_iou, val_dice = 0, 0, 0\n#     with torch.no_grad():\n#         val_loop = tqdm(test_loader, desc=f'Epoch {epoch+1}/{num_epochs} [Val]')\n#         for images, masks, sev_labels in val_loop:\n#             images, masks, sev_labels = images.to(device), masks.to(device), sev_labels.to(device)\n            \n#             seg_logits, sev_logits = multi_task_model(images)\n#             seg_logits = nn.functional.interpolate(seg_logits, size=masks.shape[-2:], mode=\"bilinear\", align_corners=False)\n            \n#             loss_seg_bce = bce_loss_fn(seg_logits, masks)\n#             seg_probs = torch.sigmoid(seg_logits)\n#             loss_seg_dice = dice_loss_fn(seg_probs, masks)\n            \n#             loss_seg = loss_seg_dice + (lambda_bce * loss_seg_bce)\n#             loss_sev = severity_loss_fn(sev_logits, sev_labels)\n            \n#             loss = loss_seg + (alpha * loss_sev)\n            \n#             val_loss += loss.item()\n#             val_iou += calculate_iou(seg_probs, masks)\n#             val_dice += (1 - loss_seg_dice.item())\n\n#     print(f\"Train - Loss: {train_loss/len(train_loader):.4f}, Dice: {train_dice/len(train_loader):.4f}, IoU: {train_iou/len(train_loader):.4f}\")\n#     print(f\"Val   - Loss: {val_loss/len(test_loader):.4f}, Dice: {val_dice/len(test_loader):.4f}, IoU: {val_iou/len(test_loader):.4f}\\n\")\n\n# torch.save(multi_task_model.state_dict(), 'multi_task_segformer_final.pth')\n# print(\"Training Complete! Final model saved as 'multi_task_segformer_final.pth'\")","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"!pip install -q transformers","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# import os\n# import torch\n# import torch.nn as nn\n# import pandas as pd\n# from torch.utils.data import Dataset, DataLoader\n# from torchvision import transforms\n# from PIL import Image\n# from transformers import SegformerForSemanticSegmentation\n# import torch.optim as optim\n# from tqdm import tqdm\n\n# # --- EXACT KAGGLE PATHS ---\n# BASE_DIR = '/kaggle/input/datasets/leoscode/wound-segmentation-images/data_wound_seg'\n# TRAIN_IMG_DIR = os.path.join(BASE_DIR, 'train_images')\n# TRAIN_MASK_DIR = os.path.join(BASE_DIR, 'train_masks')\n# TEST_IMG_DIR = os.path.join(BASE_DIR, 'test_images')\n# TEST_MASK_DIR = os.path.join(BASE_DIR, 'test_masks')\n\n# # 1. DATASET CLASS\n# class WoundDataset(Dataset):\n#     def __init__(self, image_dir, mask_dir, labels_df, split='train', img_transform=None, mask_transform=None):\n#         self.image_dir = image_dir\n#         self.mask_dir = mask_dir\n#         self.labels_df = labels_df[labels_df['split'] == split].reset_index(drop=True)\n#         self.img_transform = img_transform\n#         self.mask_transform = mask_transform\n\n#     def __len__(self):\n#         return len(self.labels_df)\n\n#     def __getitem__(self, idx):\n#         img_name = self.labels_df.iloc[idx]['image_id']\n#         img_path = os.path.join(self.image_dir, img_name)\n#         mask_path = os.path.join(self.mask_dir, img_name)\n\n#         image = Image.open(img_path).convert(\"RGB\")\n#         mask = Image.open(mask_path).convert(\"L\")\n\n#         if self.img_transform:\n#             image = self.img_transform(image)\n#         if self.mask_transform:\n#             mask = self.mask_transform(mask)\n#             mask = (mask > 0.5).float() \n\n#         return image, mask\n\n# # 2. METRICS & LOSS\n# class DiceLoss(nn.Module):\n#     def __init__(self, smooth=1e-6):\n#         super(DiceLoss, self).__init__()\n#         self.smooth = smooth\n\n#     def forward(self, inputs, targets):\n#         inputs = inputs.view(-1)\n#         targets = targets.view(-1)\n#         intersection = (inputs * targets).sum()                            \n#         dice = (2. * intersection + self.smooth) / (inputs.sum() + targets.sum() + self.smooth)  \n#         return 1 - dice\n\n# def calculate_iou(preds, labels, threshold=0.5):\n#     preds = (preds > threshold).float()\n#     intersection = (preds * labels).sum()\n#     union = preds.sum() + labels.sum() - intersection\n#     iou = (intersection + 1e-6) / (union + 1e-6)\n#     return iou.item()\n\n# # --- EXECUTION ---\n# if __name__ == \"__main__\":\n#     # Load labels generated in Step 1\n#     df = pd.read_csv('severity_labels.csv')\n\n#     # Transforms\n#     img_transform = transforms.Compose([\n#         transforms.Resize((512, 512)),\n#         transforms.ToTensor(),\n#         transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])\n#     ])\n#     mask_transform = transforms.Compose([\n#         transforms.Resize((512, 512)),\n#         transforms.ToTensor()\n#     ])\n    \n#     # Dataloaders\n#     train_dataset = WoundDataset(TRAIN_IMG_DIR, TRAIN_MASK_DIR, df, split='train', img_transform=img_transform, mask_transform=mask_transform)\n#     test_dataset = WoundDataset(TEST_IMG_DIR, TEST_MASK_DIR, df, split='test', img_transform=img_transform, mask_transform=mask_transform)\n\n#     train_loader = DataLoader(train_dataset, batch_size=2, shuffle=True)\n#     test_loader = DataLoader(test_dataset, batch_size=2, shuffle=False)\n\n#     device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')\n    \n#     # 3. LOAD CORRECT PRE-TRAINED SEGFORMER\n#     print(\"Loading Pre-trained SegFormer-B2 model...\")\n#     model = SegformerForSemanticSegmentation.from_pretrained(\n#         'nvidia/segformer-b2-finetuned-ade-512-512',\n#         num_labels=1,\n#         ignore_mismatched_sizes=True\n#     ).to(device)\n\n#     # 4. TRAINING SETUP\n#     bce_loss_fn = nn.BCEWithLogitsLoss()\n#     dice_loss_fn = DiceLoss()\n#     optimizer = optim.AdamW(model.parameters(), lr=5e-5) \n#     num_epochs = 5 \n#     lambda_bce = 0.5\n\n#     print(\"\\nStarting SegFormer Training (Exp 2)...\\n\")\n\n#     for epoch in range(num_epochs):\n#         # Training Phase\n#         model.train()\n#         train_loss, train_iou, train_dice = 0, 0, 0\n        \n#         loop = tqdm(train_loader, desc=f'Epoch {epoch+1}/{num_epochs} [Train]')\n#         for images, masks in loop:\n#             images = images.to(device)\n#             masks = masks.to(device)\n            \n#             optimizer.zero_grad()\n            \n#             outputs = model(pixel_values=images).logits\n#             outputs = nn.functional.interpolate(outputs, size=masks.shape[-2:], mode=\"bilinear\", align_corners=False)\n            \n#             loss_bce = bce_loss_fn(outputs, masks)\n#             outputs_sigmoid = torch.sigmoid(outputs)\n#             loss_dice = dice_loss_fn(outputs_sigmoid, masks)\n#             loss = loss_dice + (lambda_bce * loss_bce)\n            \n#             loss.backward()\n#             optimizer.step()\n            \n#             train_loss += loss.item()\n#             train_iou += calculate_iou(outputs_sigmoid, masks)\n#             train_dice += (1 - loss_dice.item())\n#             loop.set_postfix(loss=loss.item())\n\n#         # Validation Phase\n#         model.eval()\n#         val_loss, val_iou, val_dice = 0, 0, 0\n#         with torch.no_grad():\n#             val_loop = tqdm(test_loader, desc=f'Epoch {epoch+1}/{num_epochs} [Val]')\n#             for images, masks in val_loop:\n#                 images = images.to(device)\n#                 masks = masks.to(device)\n                \n#                 outputs = model(pixel_values=images).logits\n#                 outputs = nn.functional.interpolate(outputs, size=masks.shape[-2:], mode=\"bilinear\", align_corners=False)\n                \n#                 loss_bce = bce_loss_fn(outputs, masks)\n#                 outputs_sigmoid = torch.sigmoid(outputs)\n#                 loss_dice = dice_loss_fn(outputs_sigmoid, masks)\n#                 loss = loss_dice + (lambda_bce * loss_bce)\n                \n#                 val_loss += loss.item()\n#                 val_iou += calculate_iou(outputs_sigmoid, masks)\n#                 val_dice += (1 - loss_dice.item())\n\n#         # Epoch Summary\n#         print(f\"Train - Loss: {train_loss/len(train_loader):.4f}, Dice: {train_dice/len(train_loader):.4f}, IoU: {train_iou/len(train_loader):.4f}\")\n#         print(f\"Val   - Loss: {val_loss/len(test_loader):.4f}, Dice: {val_dice/len(test_loader):.4f}, IoU: {val_iou/len(test_loader):.4f}\\n\")\n\n#     # Save weights\n#     torch.save(model.state_dict(), 'segformer_baseline.pth')\n#     print(\"Model saved as segformer_baseline.pth\")","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# import torch.nn.functional as F\n\n# # 1. DEFINE MULTI-TASK MODEL (SegFormer + Severity Head)\n# class MultiTaskWoundModel(nn.Module):\n#     def __init__(self, base_model):\n#         super().__init__()\n#         self.base_model = base_model # SegFormer\n        \n#         # Lightweight Severity Head\n#         # SegFormer-B2 output dimension is 768 for the hidden state\n#         self.severity_head = nn.Sequential(\n#             nn.AdaptiveAvgPool2d(1),\n#             nn.Flatten(),\n#             nn.Linear(768, 128),\n#             nn.ReLU(),\n#             nn.Dropout(0.3),\n#             nn.Linear(128, 3) # 3 classes: Mild, Moderate, Severe\n#         )\n        \n#     def forward(self, pixel_values):\n#         # We need encoder hidden states for the severity head\n#         outputs = self.base_model(pixel_values=pixel_values, output_hidden_states=True)\n#         # Taking the last hidden state from the encoder\n#         encoder_features = outputs.hidden_states[-1] \n        \n#         # Segmentation Logits\n#         seg_logits = outputs.logits\n        \n#         # Severity Logits\n#         sev_logits = self.severity_head(encoder_features)\n        \n#         return seg_logits, sev_logits\n\n# # 2. INITIALIZE MULTI-TASK MODEL\n# # Using our already trained backbone (optional: load saved segformer_baseline.pth)\n# base_model = SegformerForSemanticSegmentation.from_pretrained('nvidia/segformer-b2-finetuned-ade-512-512', num_labels=1, ignore_mismatched_sizes=True)\n# multi_task_model = MultiTaskWoundModel(base_model).to(device)\n\n# print(\"Multi-task Model (Segmentation + Severity Head) initialized.\")","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# import torch\n# import torch.nn.functional as F\n\n# # 1. SMART REPORT GENERATOR FUNCTION\n# def generate_telehealth_report(area_percentage, severity_label, confidence_score):\n#     print(\"\\n\" + \"=\"*50)\n#     print(\" 🏥 WOUND AI: CLINICAL TELEHEALTH REPORT \")\n#     print(\"=\"*50)\n    \n#     # --- UNCERTAINTY GATE LOGIC ---\n#     if confidence_score >= 0.80:\n#         certainty_level = \"High Confidence\"\n#         clinical_wording = f\"The wound presents directly as {severity_label.upper()}.\"\n#         action = \"Standard clinical protocol applies.\"\n        \n#     elif 0.60 <= confidence_score < 0.80:\n#         certainty_level = \"Moderate Confidence (Hedged)\"\n#         clinical_wording = f\"The wound is likely {severity_label.lower()}.\"\n#         action = \"Recommend secondary clinical review to confirm boundaries.\"\n        \n#     else:\n#         certainty_level = \"Low Confidence (Cautious)\"\n#         clinical_wording = f\"The model indicates a possibly {severity_label.lower()} wound, but boundary delineation is uncertain.\"\n#         action = \"CAUTION: Manual clinical triage highly recommended.\"\n\n#     # --- REPORT TEMPLATE ---\n#     print(f\"▶ WOUND COVERAGE: {area_percentage:.2f}% of observed dermoscopic area.\")\n#     print(f\"▶ SEVERITY SCORE: {clinical_wording}\")\n#     print(f\"▶ UNCERTAINTY GATE: {certainty_level} (Score: {confidence_score:.2f})\")\n#     print(f\"▶ CLINICAL ACTION: {action}\")\n#     print(\"=\"*50 + \"\\n\")\n\n\n# # 2. INFERENCE TESTING (DUMMY BATCH)\n# multi_task_model.eval()\n\n# # Assuming we take one batch from our train_loader to test the pipeline\n# images, masks, true_severities = next(iter(train_loader))\n# images = images.to(device)\n\n# with torch.no_grad():\n#     # Model Forward Pass\n#     seg_logits, sev_logits = multi_task_model(images)\n    \n#     # Process Segmentation Area\n#     seg_masks = torch.sigmoid(nn.functional.interpolate(seg_logits, size=(512, 512), mode=\"bilinear\", align_corners=False))\n#     predicted_binary_masks = (seg_masks > 0.5).float()\n    \n#     # Process Severity & Confidence\n#     sev_probs = F.softmax(sev_logits, dim=1)\n#     confidence_scores, predicted_classes = torch.max(sev_probs, dim=1)\n    \n#     severity_mapping = {0: \"Mild\", 1: \"Moderate\", 2: \"Severe\"}\n\n#     # Generate Reports for the batch\n#     for i in range(images.size(0)):\n#         # Calculate Area Percentage from predicted mask\n#         total_pixels = 512 * 512\n#         wound_pixels = predicted_binary_masks[i].sum().item()\n#         area_pct = (wound_pixels / total_pixels) * 100\n        \n#         pred_label = severity_mapping[predicted_classes[i].item()]\n#         conf_score = confidence_scores[i].item()\n        \n#         print(f\"Patient/Image Record #{i+1}:\")\n#         generate_telehealth_report(area_pct, pred_label, conf_score)","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# import torch\n# import torch.nn as nn\n# import torch.nn.functional as F\n# from transformers import SegformerForSemanticSegmentation\n\n# # 1. REDEFINE MODEL ARCHITECTURE\n# class MultiTaskWoundModel(nn.Module):\n#     def __init__(self, base_model):\n#         super().__init__()\n#         self.base_model = base_model \n#         self.severity_head = nn.Sequential(\n#             nn.AdaptiveAvgPool2d(1),\n#             nn.Flatten(),\n#             nn.Linear(512, 128),  \n#             nn.ReLU(),\n#             nn.Dropout(0.3),\n#             nn.Linear(128, 3) \n#         )\n        \n#     def forward(self, pixel_values):\n#         outputs = self.base_model(pixel_values=pixel_values, output_hidden_states=True)\n#         encoder_features = outputs.hidden_states[-1] \n#         seg_logits = outputs.logits\n#         sev_logits = self.severity_head(encoder_features)\n#         return seg_logits, sev_logits\n\n# device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')\n\n# # 2. INITIALIZE MODEL\n# print(\"Loading Base Model...\")\n# base_model = SegformerForSemanticSegmentation.from_pretrained('nvidia/segformer-b2-finetuned-ade-512-512', num_labels=1, ignore_mismatched_sizes=True)\n# multi_task_model = MultiTaskWoundModel(base_model).to(device)\n\n# # 3. LOAD YOUR 25-EPOCH TRAINED WEIGHTS (Crucial Step!)\n# print(\"\\nLoading your fully trained weights...\")\n# try:\n#     multi_task_model.load_state_dict(torch.load('multi_task_segformer_final.pth', map_location=device))\n#     print(\"✅ Weights loaded successfully! Model is ready for Telehealth Triage.\")\n# except FileNotFoundError:\n#     print(\"❌ Warning: 'multi_task_segformer_final.pth' not found. Ensure the file is in the working directory.\")\n\n# multi_task_model.eval()\n\n# # 4. RUN INFERENCE & GENERATE REPORT\n# try:\n#     batch = next(iter(test_loader)) # Use test_loader for final evaluation\n#     images = batch[0].to(device)\n#     print(\"\\nTesting on actual patient dataset...\\n\")\n# except NameError:\n#     print(\"\\nDataLoader not found in memory. Testing with dummy simulated patient image...\\n\")\n#     images = torch.rand((2, 3, 512, 512)).to(device)\n\n# with torch.no_grad():\n#     seg_logits, sev_logits = multi_task_model(images)\n    \n#     # Process Segmentation Area\n#     seg_masks = torch.sigmoid(nn.functional.interpolate(seg_logits, size=(512, 512), mode=\"bilinear\", align_corners=False))\n#     predicted_binary_masks = (seg_masks > 0.5).float()\n    \n#     # Process Severity & Confidence\n#     sev_probs = F.softmax(sev_logits, dim=1)\n#     confidence_scores, predicted_classes = torch.max(sev_probs, dim=1)\n    \n#     severity_mapping = {0: \"Mild\", 1: \"Moderate\", 2: \"Severe\"}\n\n#     # Generate Reports\n#     for i in range(images.size(0)):\n#         total_pixels = 512 * 512\n#         wound_pixels = predicted_binary_masks[i].sum().item()\n#         area_pct = (wound_pixels / total_pixels) * 100\n        \n#         pred_label = severity_mapping[predicted_classes[i].item()]\n#         conf_score = confidence_scores[i].item()\n        \n#         print(f\"Patient/Image Record #{i+1}:\")\n#         print(\"=\"*50)\n#         print(\" 🏥 WOUND AI: CLINICAL TELEHEALTH REPORT \")\n#         print(\"=\"*50)\n#         print(f\"▶ WOUND COVERAGE: {area_pct:.2f}% of observed dermoscopic area.\")\n        \n#         # Uncertainty Gate Logic\n#         if conf_score >= 0.80:\n#             print(f\"▶ SEVERITY SCORE: The wound presents directly as {pred_label.upper()}.\")\n#             print(f\"▶ UNCERTAINTY GATE: High Confidence (Score: {conf_score:.2f})\")\n#             print(\"▶ CLINICAL ACTION: Standard clinical protocol applies.\")\n#         elif 0.60 <= conf_score < 0.80:\n#             print(f\"▶ SEVERITY SCORE: The wound is likely {pred_label.lower()}.\")\n#             print(f\"▶ UNCERTAINTY GATE: Moderate Confidence (Hedged) (Score: {conf_score:.2f})\")\n#             print(\"▶ CLINICAL ACTION: Recommend secondary clinical review.\")\n#         else:\n#             print(f\"▶ SEVERITY SCORE: The model indicates a possibly {pred_label.lower()} wound, but boundaries are uncertain.\")\n#             print(f\"▶ UNCERTAINTY GATE: Low Confidence (Cautious) (Score: {conf_score:.2f})\")\n#             print(\"▶ CLINICAL ACTION: CAUTION: Manual clinical triage highly recommended.\")\n#         print(\"=\"*50 + \"\\n\")","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# import torch\n# import torch.nn as nn\n# import torch.nn.functional as F\n# import torchvision.transforms.functional as TF\n# from transformers import SegformerForSemanticSegmentation\n\n# # 1. REDEFINE MODEL (To prevent NameError)\n# class MultiTaskWoundModel(nn.Module):\n#     def __init__(self, base_model):\n#         super().__init__()\n#         self.base_model = base_model \n#         self.severity_head = nn.Sequential(\n#             nn.AdaptiveAvgPool2d(1),\n#             nn.Flatten(),\n#             nn.Linear(512, 128),  \n#             nn.ReLU(),\n#             nn.Dropout(0.3),\n#             nn.Linear(128, 3) \n#         )\n        \n#     def forward(self, pixel_values):\n#         outputs = self.base_model(pixel_values=pixel_values, output_hidden_states=True)\n#         encoder_features = outputs.hidden_states[-1] \n#         seg_logits = outputs.logits\n#         sev_logits = self.severity_head(encoder_features)\n#         return seg_logits, sev_logits\n\n# # Initialize Model\n# device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')\n# base_model = SegformerForSemanticSegmentation.from_pretrained('nvidia/segformer-b2-finetuned-ade-512-512', num_labels=1, ignore_mismatched_sizes=True)\n# multi_task_model = MultiTaskWoundModel(base_model).to(device)\n# multi_task_model.eval()\n\n# # ==========================================\n# # EXPERIMENT 5: TELEHEALTH ROBUSTNESS TEST\n# # ==========================================\n# print(\"\\nStarting Experiment 5: Telehealth Noise/Blur Simulation...\\n\")\n\n# # Safe data loading\n# try:\n#     images, masks, true_severities = next(iter(test_loader))\n#     print(\"Using actual images from test_loader...\")\n# except NameError:\n#     print(\"DataLoader not found in memory. Using simulated patient images...\")\n#     images = torch.rand((2, 3, 512, 512))\n\n# # 1. Simulate Bad Camera/Low Quality Telehealth Image (Gaussian Blur)\n# blurred_images = TF.gaussian_blur(images, kernel_size=[15, 15], sigma=[5.0, 5.0])\n# blurred_images = blurred_images.to(device)\n# original_images = images.to(device)\n\n# def test_inference(input_images, condition_name):\n#     print(f\"\\n--- TESTING CONDITION: {condition_name} ---\")\n#     with torch.no_grad():\n#         seg_logits, sev_logits = multi_task_model(input_images)\n        \n#         sev_probs = F.softmax(sev_logits, dim=1)\n#         confidence_scores, predicted_classes = torch.max(sev_probs, dim=1)\n        \n#         severity_mapping = {0: \"Mild\", 1: \"Moderate\", 2: \"Severe\"}\n\n#         for i in range(input_images.size(0)):\n#             pred_label = severity_mapping[predicted_classes[i].item()]\n#             conf_score = confidence_scores[i].item()\n            \n#             print(f\"Image #{i+1} | Prediction: {pred_label} | Confidence: {conf_score:.4f}\")\n#             if conf_score < 0.60:\n#                 print(\">> RESULT: Uncertainty Gate successfully triggered! (Flagged for manual review)\")\n#             else:\n#                 print(\">> RESULT: Model remained confident.\")\n\n# # Run on Clean Images\n# test_inference(original_images, \"CLEAN IMAGES (Baseline)\")\n\n# # Run on Blurred (Telehealth) Images\n# test_inference(blurred_images, \"BLURRED IMAGES (Simulated Telehealth/Poor Camera)\")","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# import torch\n# import torch.nn as nn\n# import matplotlib.pyplot as plt\n# from transformers import SegformerForSemanticSegmentation\n# import numpy as np\n\n# # 1. CRASH-PROOF MODEL RE-INIT\n# class MultiTaskWoundModel(nn.Module):\n#     def __init__(self, base_model):\n#         super().__init__()\n#         self.base_model = base_model \n#         self.severity_head = nn.Sequential(\n#             nn.AdaptiveAvgPool2d(1),\n#             nn.Flatten(),\n#             nn.Linear(512, 128),  \n#             nn.ReLU(),\n#             nn.Dropout(0.3),\n#             nn.Linear(128, 3) \n#         )\n#     def forward(self, pixel_values):\n#         outputs = self.base_model(pixel_values=pixel_values, output_hidden_states=True)\n#         return outputs.logits, self.severity_head(outputs.hidden_states[-1])\n\n# device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')\n# base_model = SegformerForSemanticSegmentation.from_pretrained('nvidia/segformer-b2-finetuned-ade-512-512', num_labels=1, ignore_mismatched_sizes=True)\n# multi_task_model = MultiTaskWoundModel(base_model).to(device)\n# multi_task_model.eval()\n\n# # 2. FETCH DATA & PLOT\n# print(\"\\nGenerating Visual Comparison for the Paper...\")\n\n# try:\n#     images, masks, true_severities = next(iter(test_loader))\n#     print(\"Using actual images from test_loader...\")\n# except NameError:\n#     print(\"DataLoader not found in memory. Using dummy images to test plotting logic...\")\n#     images = torch.rand((2, 3, 512, 512))\n#     masks = torch.randint(0, 2, (2, 1, 512, 512)).float()\n\n# images = images.to(device)\n\n# with torch.no_grad():\n#     seg_logits, _ = multi_task_model(images)\n    \n#     # Upsample to 512x512, apply sigmoid, and threshold at 0.5\n#     seg_masks_probs = torch.sigmoid(nn.functional.interpolate(seg_logits, size=(512, 512), mode=\"bilinear\", align_corners=False))\n#     predicted_masks = (seg_masks_probs > 0.5).float().cpu().numpy()\n\n# # 3. MATPLOTLIB VISUALIZATION\n# images_cpu = images.cpu().numpy()\n# masks_cpu = masks.cpu().numpy()\n# num_images = min(2, images.size(0)) # Show max 2 images\n\n# fig, axes = plt.subplots(num_images, 3, figsize=(15, 5 * num_images))\n# fig.suptitle('SegFormer Segmentation vs Ground Truth', fontsize=16)\n\n# for i in range(num_images):\n#     # Convert image tensor back to displayable format (Denormalize rough approx for display)\n#     img = np.transpose(images_cpu[i], (1, 2, 0))\n#     img = (img - img.min()) / (img.max() - img.min()) # Normalize to [0,1] for viewing\n    \n#     # Original Image\n#     axes[i, 0].imshow(img)\n#     axes[i, 0].set_title('Original Telehealth Image')\n#     axes[i, 0].axis('off')\n    \n#     # Ground Truth Mask\n#     axes[i, 1].imshow(masks_cpu[i, 0], cmap='gray')\n#     axes[i, 1].set_title('Ground Truth (Expert)')\n#     axes[i, 1].axis('off')\n    \n#     # Predicted Mask\n#     axes[i, 2].imshow(predicted_masks[i, 0], cmap='inferno') # using 'inferno' to highlight the prediction\n#     axes[i, 2].set_title('SegFormer Prediction')\n#     axes[i, 2].axis('off')\n\n# plt.tight_layout()\n# plt.show()\n# print(\"Visualization complete! Save this plot for your paper's Results section.\")","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# import os\n# import cv2\n# import numpy as np\n# import pandas as pd\n# import torch\n# import torch.nn as nn\n# import torch.nn.functional as F\n# import torch.optim as optim\n# from torch.utils.data import Dataset, DataLoader\n# from torchvision import transforms\n# from PIL import Image\n# from transformers import SegformerForSemanticSegmentation\n# from tqdm import tqdm\n\n# # ==========================================\n# # 1. SETUP & PATHS\n# # ==========================================\n# BASE_DIR = '/kaggle/input/datasets/leoscode/wound-segmentation-images/data_wound_seg'\n# TRAIN_IMG_DIR = os.path.join(BASE_DIR, 'train_images')\n# TRAIN_MASK_DIR = os.path.join(BASE_DIR, 'train_masks')\n# TEST_IMG_DIR = os.path.join(BASE_DIR, 'test_images')\n# TEST_MASK_DIR = os.path.join(BASE_DIR, 'test_masks')\n\n# # ==========================================\n# # 2. GENERATE CSV (Auto-Recovery)\n# # ==========================================\n# def generate_severity_labels():\n#     print(\"Generating 'severity_labels.csv' from masks...\")\n#     data = []\n#     for split, mask_dir in [('train', TRAIN_MASK_DIR), ('test', TEST_MASK_DIR)]:\n#         if not os.path.exists(mask_dir): continue\n#         mask_files = [f for f in os.listdir(mask_dir) if f.lower().endswith(('.png', '.jpg', '.jpeg'))]\n#         for filename in mask_files:\n#             mask_path = os.path.join(mask_dir, filename)\n#             mask = cv2.imread(mask_path, cv2.IMREAD_GRAYSCALE)\n#             if mask is None: continue\n#             total_pixels = mask.shape[0] * mask.shape[1]\n#             wound_pixels = np.count_nonzero(mask)\n#             area_percentage = (wound_pixels / total_pixels) * 100\n            \n#             if area_percentage < 5.0: class_id = 0\n#             elif 5.0 <= area_percentage <= 15.0: class_id = 1\n#             else: class_id = 2\n                \n#             data.append({'image_id': filename, 'split': split, 'severity_class_id': class_id})\n#     df = pd.DataFrame(data)\n#     df.to_csv('severity_labels.csv', index=False)\n#     print(f\"Generated {len(df)} labels successfully.\\n\")\n#     return df\n\n# if not os.path.exists('severity_labels.csv'):\n#     df = generate_severity_labels()\n# else:\n#     df = pd.read_csv('severity_labels.csv')\n\n# # ==========================================\n# # 3. METRICS & LOSS FUNCTIONS\n# # ==========================================\n# class DiceLoss(nn.Module):\n#     def __init__(self, smooth=1e-6):\n#         super(DiceLoss, self).__init__()\n#         self.smooth = smooth\n#     def forward(self, inputs, targets):\n#         inputs = inputs.view(-1)\n#         targets = targets.view(-1)\n#         intersection = (inputs * targets).sum()                            \n#         dice = (2. * intersection + self.smooth) / (inputs.sum() + targets.sum() + self.smooth)  \n#         return 1 - dice\n\n# def calculate_iou(preds, labels, threshold=0.5):\n#     preds = (preds > threshold).float()\n#     intersection = (preds * labels).sum()\n#     union = preds.sum() + labels.sum() - intersection\n#     iou = (intersection + 1e-6) / (union + 1e-6)\n#     return iou.item()\n\n# # ==========================================\n# # 4. DATASET & DATALOADERS\n# # ==========================================\n# class WoundMultiTaskDataset(Dataset):\n#     def __init__(self, image_dir, mask_dir, labels_df, split='train', img_transform=None, mask_transform=None):\n#         self.image_dir = image_dir\n#         self.mask_dir = mask_dir\n#         self.labels_df = labels_df[labels_df['split'] == split].reset_index(drop=True)\n#         self.img_transform = img_transform\n#         self.mask_transform = mask_transform\n\n#     def __len__(self):\n#         return len(self.labels_df)\n\n#     def __getitem__(self, idx):\n#         row = self.labels_df.iloc[idx]\n#         img_name = row['image_id']\n#         severity_label = row['severity_class_id']\n        \n#         img_path = os.path.join(self.image_dir, img_name)\n#         mask_path = os.path.join(self.mask_dir, img_name)\n\n#         image = Image.open(img_path).convert(\"RGB\")\n#         mask = Image.open(mask_path).convert(\"L\")\n\n#         if self.img_transform:\n#             image = self.img_transform(image)\n#         if self.mask_transform:\n#             mask = self.mask_transform(mask)\n#             mask = (mask > 0.5).float() \n\n#         return image, mask, torch.tensor(severity_label, dtype=torch.long)\n\n# img_transform = transforms.Compose([\n#     transforms.Resize((512, 512)),\n#     transforms.ToTensor(),\n#     transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])\n# ])\n# mask_transform = transforms.Compose([\n#     transforms.Resize((512, 512)),\n#     transforms.ToTensor()\n# ])\n\n# train_dataset = WoundMultiTaskDataset(TRAIN_IMG_DIR, TRAIN_MASK_DIR, df, split='train', img_transform=img_transform, mask_transform=mask_transform)\n# test_dataset = WoundMultiTaskDataset(TEST_IMG_DIR, TEST_MASK_DIR, df, split='test', img_transform=img_transform, mask_transform=mask_transform)\n\n# train_loader = DataLoader(train_dataset, batch_size=2, shuffle=True)\n# test_loader = DataLoader(test_dataset, batch_size=2, shuffle=False)\n\n# # ==========================================\n# # 5. MULTI-TASK ARCHITECTURE\n# # ==========================================\n# class MultiTaskWoundModel(nn.Module):\n#     def __init__(self, base_model):\n#         super().__init__()\n#         self.base_model = base_model \n#         self.severity_head = nn.Sequential(\n#             nn.AdaptiveAvgPool2d(1),\n#             nn.Flatten(),\n#             nn.Linear(512, 128),  \n#             nn.ReLU(),\n#             nn.Dropout(0.3),\n#             nn.Linear(128, 3) \n#         )\n        \n#     def forward(self, pixel_values):\n#         outputs = self.base_model(pixel_values=pixel_values, output_hidden_states=True)\n#         encoder_features = outputs.hidden_states[-1] \n#         seg_logits = outputs.logits\n#         sev_logits = self.severity_head(encoder_features)\n#         return seg_logits, sev_logits\n\n# device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')\n# print(\"Initializing Model on Device:\", device)\n# base_model = SegformerForSemanticSegmentation.from_pretrained('nvidia/segformer-b2-finetuned-ade-512-512', num_labels=1, ignore_mismatched_sizes=True)\n# multi_task_model = MultiTaskWoundModel(base_model).to(device)\n\n# # ==========================================\n# # 6. TRAINING SETUP & LOOP (20 EPOCHS)\n# # ==========================================\n# bce_loss_fn = nn.BCEWithLogitsLoss()\n# dice_loss_fn = DiceLoss()\n\n# weights = torch.tensor([1.0, 4.0, 13.0]).to(device) \n# severity_loss_fn = nn.CrossEntropyLoss(weight=weights)\n\n# optimizer = optim.AdamW(multi_task_model.parameters(), lr=5e-5) \n# num_epochs = 20 \n# lambda_bce = 0.5\n# alpha = 0.5 \n\n# print(f\"\\n--- Starting Full Multi-Task Training ({num_epochs} Epochs) ---\")\n\n# for epoch in range(num_epochs):\n#     # --- TRAINING PHASE ---\n#     multi_task_model.train()\n#     train_loss, train_iou, train_dice = 0, 0, 0\n    \n#     loop = tqdm(train_loader, desc=f'Epoch {epoch+1}/{num_epochs} [Train]')\n#     for images, masks, sev_labels in loop:\n#         images, masks, sev_labels = images.to(device), masks.to(device), sev_labels.to(device)\n        \n#         optimizer.zero_grad()\n#         seg_logits, sev_logits = multi_task_model(images)\n#         seg_logits = nn.functional.interpolate(seg_logits, size=masks.shape[-2:], mode=\"bilinear\", align_corners=False)\n        \n#         loss_seg_bce = bce_loss_fn(seg_logits, masks)\n#         seg_probs = torch.sigmoid(seg_logits)\n#         loss_seg_dice = dice_loss_fn(seg_probs, masks)\n        \n#         loss_seg = loss_seg_dice + (lambda_bce * loss_seg_bce)\n#         loss_sev = severity_loss_fn(sev_logits, sev_labels)\n        \n#         loss = loss_seg + (alpha * loss_sev)\n#         loss.backward()\n#         optimizer.step()\n        \n#         train_loss += loss.item()\n#         train_iou += calculate_iou(seg_probs, masks)\n#         train_dice += (1 - loss_seg_dice.item())\n#         loop.set_postfix(loss=loss.item())\n\n#     # --- VALIDATION PHASE ---\n#     multi_task_model.eval()\n#     val_loss, val_iou, val_dice = 0, 0, 0\n#     with torch.no_grad():\n#         val_loop = tqdm(test_loader, desc=f'Epoch {epoch+1}/{num_epochs} [Val]')\n#         for images, masks, sev_labels in val_loop:\n#             images, masks, sev_labels = images.to(device), masks.to(device), sev_labels.to(device)\n            \n#             seg_logits, sev_logits = multi_task_model(images)\n#             seg_logits = nn.functional.interpolate(seg_logits, size=masks.shape[-2:], mode=\"bilinear\", align_corners=False)\n            \n#             loss_seg_bce = bce_loss_fn(seg_logits, masks)\n#             seg_probs = torch.sigmoid(seg_logits)\n#             loss_seg_dice = dice_loss_fn(seg_probs, masks)\n            \n#             loss_seg = loss_seg_dice + (lambda_bce * loss_seg_bce)\n#             loss_sev = severity_loss_fn(sev_logits, sev_labels)\n            \n#             loss = loss_seg + (alpha * loss_sev)\n            \n#             val_loss += loss.item()\n#             val_iou += calculate_iou(seg_probs, masks)\n#             val_dice += (1 - loss_seg_dice.item())\n\n#     print(f\"Train - Loss: {train_loss/len(train_loader):.4f}, Dice: {train_dice/len(train_loader):.4f}, IoU: {train_iou/len(train_loader):.4f}\")\n#     print(f\"Val   - Loss: {val_loss/len(test_loader):.4f}, Dice: {val_dice/len(test_loader):.4f}, IoU: {val_iou/len(test_loader):.4f}\\n\")\n\n# torch.save(multi_task_model.state_dict(), 'multi_task_segformer_final.pth')\n# print(\"Training Complete! Final model saved as 'multi_task_segformer_final.pth'\")","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# import os\n\n# print(\"Searching for train.csv everywhere in /kaggle/input/ ...\\n\")\n\n# found = False\n# for root, dirs, files in os.walk('/kaggle/input/'):\n#     if 'train.csv' in files:\n#         print(\"✅ MIL GAYI! Aapke exact paths yeh hone chahiye:\\n\")\n#         print(f\"TRAIN_CSV = '{os.path.join(root, 'train.csv')}'\")\n        \n#         # Check for image directories\n#         if 'jpeg' in dirs:\n#             print(f\"TRAIN_IMG_DIR = '{os.path.join(root, 'jpeg/train')}'\")\n#         elif 'train' in dirs:\n#             print(f\"TRAIN_IMG_DIR = '{os.path.join(root, 'train')}'\")\n#         elif 'images' in dirs:\n#             print(f\"TRAIN_IMG_DIR = '{os.path.join(root, 'images/train')}'\")\n        \n#         found = True\n#         break\n\n# if not found:\n#     print(\"❌ Dataset abhi tak sahi tarah attach nahi hua ya train.csv missing hai.\")","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# # ==========================================\n# # 3. REAL DATASET & STRATIFIED SPLIT\n# # ==========================================\n# import os\n# import random\n# import numpy as np\n# import pandas as pd\n# import torch\n# from torch.utils.data import Dataset, DataLoader\n# from torchvision import transforms\n# from PIL import Image\n# from sklearn.model_selection import GroupKFold\n\n# print(\"Loading REAL CSV and performing Patient-Stratified Split...\\n\")\n\n# # EXACT PATHS FOUND\n# TRAIN_CSV = '/kaggle/input/competitions/siim-isic-melanoma-classification/train.csv'\n# TRAIN_IMG_DIR = '/kaggle/input/competitions/siim-isic-melanoma-classification/jpeg/train'\n\n# # Read the actual dataset\n# df_train = pd.read_csv(TRAIN_CSV)\n# print(f\"Successfully loaded {len(df_train)} real patient records!\")\n\n# # Initialize GroupKFold (5 splits)\n# gkf = GroupKFold(n_splits=5)\n\n# # Create a new column for fold numbers\n# df_train['fold'] = -1\n# for fold, (train_idx, val_idx) in enumerate(gkf.split(df_train, groups=df_train['patient_id'])):\n#     df_train.loc[val_idx, 'fold'] = fold\n\n# print(\"Patient-Stratified Split Complete! Displaying fold distribution:\")\n# print(df_train.groupby(['fold', 'target']).size())\n\n# class MelanomaDataset(Dataset):\n#     def __init__(self, df, img_dir, transform=None):\n#         self.df = df.reset_index(drop=True)\n#         self.img_dir = img_dir\n#         self.transform = transform\n\n#     def __len__(self):\n#         return len(self.df)\n\n#     def __getitem__(self, idx):\n#         row = self.df.iloc[idx]\n#         img_name = row['image_name']\n#         img_path = os.path.join(self.img_dir, f\"{img_name}.jpg\")\n        \n#         image = Image.open(img_path).convert('RGB')\n#         label = torch.tensor(row['target'], dtype=torch.float32)\n\n#         if self.transform:\n#             image = self.transform(image)\n\n#         return image, label\n\n# train_transform = transforms.Compose([\n#     transforms.Resize((224, 224)),\n#     transforms.RandomHorizontalFlip(),\n#     transforms.RandomVerticalFlip(),\n#     transforms.ToTensor(),\n#     transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])\n# ])\n\n# val_transform = transforms.Compose([\n#     transforms.Resize((224, 224)),\n#     transforms.ToTensor(),\n#     transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])\n# ])\n\n# # Use Fold 0 for validation, rest for training\n# train_data = df_train[df_train['fold'] != 0]\n# val_data = df_train[df_train['fold'] == 0]\n\n# train_dataset = MelanomaDataset(train_data, TRAIN_IMG_DIR, transform=train_transform)\n# val_dataset = MelanomaDataset(val_data, TRAIN_IMG_DIR, transform=val_transform)\n\n# train_loader = DataLoader(train_dataset, batch_size=32, shuffle=True, num_workers=2)\n# val_loader = DataLoader(val_dataset, batch_size=32, shuffle=False, num_workers=2)\n\n# print(f\"\\nReal DataLoaders Ready! Training samples: {len(train_dataset)}, Validation samples: {len(val_dataset)}\")","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# import os\n# import torch\n# import torch.nn as nn\n# import torch.optim as optim\n# import pandas as pd\n# import numpy as np\n# from tqdm import tqdm\n# from sklearn.metrics import roc_auc_score, accuracy_score\n# from sklearn.model_selection import GroupKFold\n# from torch.utils.data import Dataset, DataLoader\n# from torchvision import transforms, models\n# from PIL import Image\n\n# # ==========================================\n# # 1. DATA LOADING & STRATIFIED SPLIT\n# # ==========================================\n# print(\"Step 1: Loading REAL Data and Creating Stratified Folds...\\n\")\n# device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')\n\n# TRAIN_CSV = '/kaggle/input/competitions/siim-isic-melanoma-classification/train.csv'\n# TRAIN_IMG_DIR = '/kaggle/input/competitions/siim-isic-melanoma-classification/jpeg/train'\n\n# df_train = pd.read_csv(TRAIN_CSV)\n# gkf = GroupKFold(n_splits=5)\n# df_train['fold'] = -1\n# for fold, (train_idx, val_idx) in enumerate(gkf.split(df_train, groups=df_train['patient_id'])):\n#     df_train.loc[val_idx, 'fold'] = fold\n\n# class MelanomaDataset(Dataset):\n#     def __init__(self, df, img_dir, transform=None):\n#         self.df = df.reset_index(drop=True)\n#         self.img_dir = img_dir\n#         self.transform = transform\n\n#     def __len__(self):\n#         return len(self.df)\n\n#     def __getitem__(self, idx):\n#         row = self.df.iloc[idx]\n#         img_name = row['image_name']\n#         img_path = os.path.join(self.img_dir, f\"{img_name}.jpg\")\n#         image = Image.open(img_path).convert('RGB')\n#         label = torch.tensor(row['target'], dtype=torch.float32)\n#         if self.transform:\n#             image = self.transform(image)\n#         return image, label\n\n# train_transform = transforms.Compose([\n#     transforms.Resize((224, 224)),\n#     transforms.RandomHorizontalFlip(),\n#     transforms.RandomVerticalFlip(),\n#     transforms.ToTensor(),\n#     transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])\n# ])\n\n# val_transform = transforms.Compose([\n#     transforms.Resize((224, 224)),\n#     transforms.ToTensor(),\n#     transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])\n# ])\n\n# train_data = df_train[df_train['fold'] != 0]\n# val_data = df_train[df_train['fold'] == 0]\n\n# train_dataset = MelanomaDataset(train_data, TRAIN_IMG_DIR, transform=train_transform)\n# val_dataset = MelanomaDataset(val_data, TRAIN_IMG_DIR, transform=val_transform)\n\n# train_loader = DataLoader(train_dataset, batch_size=32, shuffle=True, num_workers=2)\n# val_loader = DataLoader(val_dataset, batch_size=32, shuffle=False, num_workers=2)\n\n# print(f\"DataLoaders Ready! Training samples: {len(train_dataset)}, Validation samples: {len(val_dataset)}\\n\")\n\n\n# # ==========================================\n# # 2. MODEL ARCHITECTURE & TRAINING LOOP\n# # ==========================================\n# print(\"Step 2: Initializing ResNet34 Model...\\n\")\n\n# class MelanomaClassifier(nn.Module):\n#     def __init__(self, pretrained=True):\n#         super().__init__()\n#         self.backbone = models.resnet34(weights=models.ResNet34_Weights.IMAGENET1K_V1 if pretrained else None)\n#         in_features = self.backbone.fc.in_features\n#         self.backbone.fc = nn.Linear(in_features, 1)\n\n#     def forward(self, x):\n#         return self.backbone(x)\n\n# model = MelanomaClassifier().to(device)\n# criterion = nn.BCEWithLogitsLoss()\n# optimizer = optim.AdamW(model.parameters(), lr=1e-4, weight_decay=1e-5)\n\n# epochs = 5 \n\n# print(f\"--- Starting REAL Training Pipeline ({epochs} Epochs) ---\")\n\n# for epoch in range(epochs):\n#     # --- TRAINING PHASE ---\n#     model.train()\n#     train_loss = 0.0\n    \n#     loop = tqdm(train_loader, desc=f\"Epoch {epoch+1}/{epochs} [Train]\")\n#     for images, labels in loop:\n#         images, labels = images.to(device), labels.to(device).unsqueeze(1) \n        \n#         optimizer.zero_grad()\n#         outputs = model(images)\n#         loss = criterion(outputs, labels)\n        \n#         loss.backward()\n#         optimizer.step()\n        \n#         train_loss += loss.item() * images.size(0)\n#         loop.set_postfix(loss=loss.item())\n        \n#     train_loss /= len(train_loader.dataset)\n    \n#     # --- VALIDATION PHASE ---\n#     model.eval()\n#     val_loss = 0.0\n#     all_labels = []\n#     all_preds = []\n    \n#     val_loop = tqdm(val_loader, desc=f\"Epoch {epoch+1}/{epochs} [Val]\")\n#     with torch.no_grad():\n#         for images, labels in val_loop:\n#             images, labels = images.to(device), labels.to(device).unsqueeze(1)\n            \n#             outputs = model(images)\n#             loss = criterion(outputs, labels)\n#             val_loss += loss.item() * images.size(0)\n            \n#             probs = torch.sigmoid(outputs).cpu().numpy()\n#             all_preds.extend(probs)\n#             all_labels.extend(labels.cpu().numpy())\n            \n#     val_loss /= len(val_loader.dataset)\n    \n#     all_preds = np.array(all_preds)\n#     all_labels = np.array(all_labels)\n    \n#     val_acc = accuracy_score(all_labels, (all_preds > 0.5).astype(int))\n#     try:\n#         val_auc = roc_auc_score(all_labels, all_preds)\n#     except ValueError:\n#         val_auc = 0.5 \n    \n#     print(f\"Train Loss: {train_loss:.4f} | Val Loss: {val_loss:.4f} | Val Acc: {val_acc:.4f} | Val AUC: {val_auc:.4f}\\n\")\n\n# # Save the final real model\n# torch.save(model.state_dict(), 'resnet34_melanoma_exp4.pth')\n# print(\"Real Training Complete! Model saved as 'resnet34_melanoma_exp4.pth'\")","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# !pip install gdown -q\n# import gdown\n\n# # Aapka diya gaya Google Drive link\n# drive_link = \"https://drive.google.com/file/d/1tFbV2YMFL01rlrLeqE35pOZ7ArO9Gs0x/view?usp=drive_link\"\n\n# print(\"Downloading model directly to Kaggle working directory...\\n\")\n# gdown.download(drive_link, '/kaggle/working/resnet34_melanoma_exp4.pth', quiet=False, fuzzy=True)\n# print(\"\\n✅ Download Complete! Model successfully Kaggle mein aa gaya hai.\")","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# import os\n# import torch\n# import torch.nn as nn\n# import pandas as pd\n# import numpy as np\n# import matplotlib.pyplot as plt\n# import seaborn as sns\n# from sklearn.metrics import roc_curve, auc, confusion_matrix\n# from sklearn.model_selection import GroupKFold\n# from torch.utils.data import Dataset, DataLoader\n# from torchvision import transforms, models\n# from PIL import Image\n# from tqdm import tqdm\n\n# print(\"Generating Publication-Ready Plots for Melanoma Paper...\\n\")\n\n# device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')\n\n# # ==========================================\n# # 1. MODEL ARCHITECTURE & DATA LOADING\n# # ==========================================\n# class MelanomaClassifier(nn.Module):\n#     def __init__(self, pretrained=False):\n#         super().__init__()\n#         self.backbone = models.resnet34(weights=None)\n#         in_features = self.backbone.fc.in_features\n#         self.backbone.fc = nn.Linear(in_features, 1)\n\n#     def forward(self, x):\n#         return self.backbone(x)\n\n# model = MelanomaClassifier().to(device)\n\n# TRAIN_CSV = '/kaggle/input/competitions/siim-isic-melanoma-classification/train.csv'\n# TRAIN_IMG_DIR = '/kaggle/input/competitions/siim-isic-melanoma-classification/jpeg/train'\n\n# df_train = pd.read_csv(TRAIN_CSV)\n# gkf = GroupKFold(n_splits=5)\n# df_train['fold'] = -1\n# for fold, (train_idx, val_idx) in enumerate(gkf.split(df_train, groups=df_train['patient_id'])):\n#     df_train.loc[val_idx, 'fold'] = fold\n\n# val_data = df_train[df_train['fold'] == 0]\n\n# class MelanomaDataset(Dataset):\n#     def __init__(self, df, img_dir, transform=None):\n#         self.df = df.reset_index(drop=True)\n#         self.img_dir = img_dir\n#         self.transform = transform\n\n#     def __len__(self):\n#         return len(self.df)\n\n#     def __getitem__(self, idx):\n#         row = self.df.iloc[idx]\n#         img_name = row['image_name']\n#         img_path = os.path.join(self.img_dir, f\"{img_name}.jpg\")\n#         image = Image.open(img_path).convert('RGB')\n#         label = torch.tensor(row['target'], dtype=torch.float32)\n#         if self.transform:\n#             image = self.transform(image)\n#         return image, label\n\n# val_transform = transforms.Compose([\n#     transforms.Resize((224, 224)),\n#     transforms.ToTensor(),\n#     transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])\n# ])\n\n# val_dataset = MelanomaDataset(val_data, TRAIN_IMG_DIR, transform=val_transform)\n# val_loader = DataLoader(val_dataset, batch_size=32, shuffle=False, num_workers=2)\n\n# # ==========================================\n# # 2. LOAD TRAINED WEIGHTS\n# # ==========================================\n# model_path = '/kaggle/working/resnet34_melanoma_exp4.pth'\n\n# if os.path.exists(model_path):\n#     model.load_state_dict(torch.load(model_path, map_location=device))\n#     model.eval()\n#     print(\"✅ Model loaded successfully from /kaggle/working/!\\n\")\n# else:\n#     print(\"Searching for the model in Kaggle Inputs...\")\n#     found = False\n#     for root, dirs, files in os.walk('/kaggle/input/'):\n#         if 'resnet34_melanoma_exp4.pth' in files:\n#             model.load_state_dict(torch.load(os.path.join(root, 'resnet34_melanoma_exp4.pth'), map_location=device))\n#             model.eval()\n#             print(\"✅ Model loaded successfully from Kaggle Input!\\n\")\n#             found = True\n#             break\n#     if not found:\n#         raise FileNotFoundError(\"❌ Model file not found! Please make sure 'resnet34_melanoma_exp4.pth' is available.\")\n\n# # ==========================================\n# # 3. RUN INFERENCE ON VALIDATION SET\n# # ==========================================\n# all_labels = []\n# all_preds = []\n# all_preds_binary = []\n\n# with torch.no_grad():\n#     val_loop = tqdm(val_loader, desc=\"Evaluating for Plots\")\n#     for images, labels in val_loop:\n#         images, labels = images.to(device), labels.to(device).unsqueeze(1)\n#         outputs = model(images)\n        \n#         probs = torch.sigmoid(outputs).cpu().numpy()\n#         preds = (probs > 0.5).astype(int)\n        \n#         all_preds.extend(probs)\n#         all_preds_binary.extend(preds)\n#         all_labels.extend(labels.cpu().numpy())\n\n# all_labels = np.array(all_labels)\n# all_preds = np.array(all_preds)\n# all_preds_binary = np.array(all_preds_binary)\n\n# # ==========================================\n# # 4. GENERATE PLOTS\n# # ==========================================\n# fpr, tpr, _ = roc_curve(all_labels, all_preds)\n# roc_auc = auc(fpr, tpr)\n\n# plt.figure(figsize=(14, 6))\n\n# # PLOT 1: ROC-AUC CURVE\n# plt.subplot(1, 2, 1)\n# plt.plot(fpr, tpr, color='#e76f51', lw=2, label=f'ResNet34 (AUC = {roc_auc:.4f})')\n# plt.plot([0, 1], [0, 1], color='navy', lw=2, linestyle='--')\n# plt.xlim([0.0, 1.0])\n# plt.ylim([0.0, 1.05])\n# plt.xlabel('False Positive Rate', fontweight='bold')\n# plt.ylabel('True Positive Rate', fontweight='bold')\n# plt.title('Receiver Operating Characteristic (ROC)', fontweight='bold', pad=15)\n# plt.legend(loc=\"lower right\")\n# plt.grid(alpha=0.3)\n\n# # PLOT 2: CONFUSION MATRIX\n# cm = confusion_matrix(all_labels, all_preds_binary)\n\n# plt.subplot(1, 2, 2)\n# sns.heatmap(cm, annot=True, fmt='d', cmap='Blues', cbar=False,\n#             xticklabels=['Benign', 'Malignant'],\n#             yticklabels=['Benign', 'Malignant'],\n#             annot_kws={\"size\": 14, \"weight\": \"bold\"})\n# plt.xlabel('Predicted Label', fontweight='bold')\n# plt.ylabel('True Label', fontweight='bold')\n# plt.title('Patient-Stratified Confusion Matrix', fontweight='bold', pad=15)\n\n# plt.tight_layout()\n# plt.show()\n\n# print(\"\\nGraphs Generated! Right-click and save this image for your MDPI submission.\")","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# !pip install gdown -q\n# import gdown\n\n# # Aapka diya gaya Google Drive link\n# drive_link = \"https://drive.google.com/file/d/1tFbV2YMFL01rlrLeqE35pOZ7ArO9Gs0x/view?usp=drive_link\"\n\n# print(\"Downloading model directly to Kaggle working directory...\\n\")\n# gdown.download(drive_link, '/kaggle/working/resnet34_melanoma_exp4.pth', quiet=False, fuzzy=True)\n# print(\"\\n✅ Download Complete! Model successfully Kaggle mein aa gaya hai.\")","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# import os\n# import torch\n# import torch.nn as nn\n# import pandas as pd\n# import numpy as np\n# import matplotlib.pyplot as plt\n# import seaborn as sns\n# from sklearn.metrics import roc_curve, auc, confusion_matrix\n# from sklearn.model_selection import GroupKFold\n# from torch.utils.data import Dataset, DataLoader\n# from torchvision import transforms, models\n# from PIL import Image\n# from tqdm import tqdm\n\n# print(\"Initializing Final Evaluation Pipeline...\\n\")\n\n# device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')\n\n# # ==========================================\n# # 1. SETUP MODEL & DATA\n# # ==========================================\n# class MelanomaClassifier(nn.Module):\n#     def __init__(self, pretrained=False):\n#         super().__init__()\n#         self.backbone = models.resnet34(weights=None)\n#         in_features = self.backbone.fc.in_features\n#         self.backbone.fc = nn.Linear(in_features, 1)\n\n#     def forward(self, x):\n#         return self.backbone(x)\n\n# model = MelanomaClassifier().to(device)\n\n# TRAIN_CSV = '/kaggle/input/competitions/siim-isic-melanoma-classification/train.csv'\n# TRAIN_IMG_DIR = '/kaggle/input/competitions/siim-isic-melanoma-classification/jpeg/train'\n\n# df_train = pd.read_csv(TRAIN_CSV)\n# gkf = GroupKFold(n_splits=5)\n# df_train['fold'] = -1\n# for fold, (train_idx, val_idx) in enumerate(gkf.split(df_train, groups=df_train['patient_id'])):\n#     df_train.loc[val_idx, 'fold'] = fold\n\n# val_data = df_train[df_train['fold'] == 0]\n\n# class MelanomaDataset(Dataset):\n#     def __init__(self, df, img_dir, transform=None):\n#         self.df = df.reset_index(drop=True)\n#         self.img_dir = img_dir\n#         self.transform = transform\n\n#     def __len__(self):\n#         return len(self.df)\n\n#     def __getitem__(self, idx):\n#         row = self.df.iloc[idx]\n#         img_name = row['image_name']\n#         img_path = os.path.join(self.img_dir, f\"{img_name}.jpg\")\n#         image = Image.open(img_path).convert('RGB')\n#         label = torch.tensor(row['target'], dtype=torch.float32)\n#         if self.transform:\n#             image = self.transform(image)\n#         return image, label\n\n# val_transform = transforms.Compose([\n#     transforms.Resize((224, 224)),\n#     transforms.ToTensor(),\n#     transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])\n# ])\n\n# val_dataset = MelanomaDataset(val_data, TRAIN_IMG_DIR, transform=val_transform)\n# val_loader = DataLoader(val_dataset, batch_size=32, shuffle=False, num_workers=2)\n\n# # ==========================================\n# # 2. LOAD WEIGHTS\n# # ==========================================\n# model_path = '/kaggle/working/resnet34_melanoma_exp4.pth'\n# if os.path.exists(model_path):\n#     model.load_state_dict(torch.load(model_path, map_location=device))\n#     model.eval()\n#     print(\"✅ Model loaded successfully from /kaggle/working/!\\n\")\n# else:\n#     raise FileNotFoundError(\"❌ Model file nahi mili! Please gdown wala cell dobara run karein taake file download ho jaye.\")\n\n# # ==========================================\n# # 3. RUN INFERENCE\n# # ==========================================\n# all_labels = []\n# all_preds = []\n\n# with torch.no_grad():\n#     val_loop = tqdm(val_loader, desc=\"Evaluating for Plots\")\n#     for images, labels in val_loop:\n#         images, labels = images.to(device), labels.to(device).unsqueeze(1)\n#         outputs = model(images)\n#         probs = torch.sigmoid(outputs).cpu().numpy()\n        \n#         all_preds.extend(probs)\n#         all_labels.extend(labels.cpu().numpy())\n\n# all_labels = np.array(all_labels).flatten()\n# all_preds = np.array(all_preds).flatten()\n\n# # ==========================================\n# # 4. CALCULATE OPTIMAL THRESHOLD\n# # ==========================================\n# fpr, tpr, thresholds = roc_curve(all_labels, all_preds)\n# roc_auc = auc(fpr, tpr)\n# optimal_idx = np.argmax(tpr - fpr)\n# optimal_threshold = thresholds[optimal_idx]\n\n# print(f\"\\n🌟 Default Threshold tha: 0.5000\")\n# print(f\"✅ Naya Optimal Threshold hai: {optimal_threshold:.4f}\\n\")\n\n# # Default Predictions (0.5 threshold)\n# preds_default = (all_preds > 0.5).astype(int)\n# # Optimized Predictions (New threshold)\n# preds_optimized = (all_preds > optimal_threshold).astype(int)\n\n# # ==========================================\n# # 5. GENERATE PLOTS\n# # ==========================================\n# plt.figure(figsize=(20, 6))\n\n# # PLOT 1: ROC-AUC CURVE\n# plt.subplot(1, 3, 1)\n# plt.plot(fpr, tpr, color='#e76f51', lw=2, label=f'ResNet34 (AUC = {roc_auc:.4f})')\n# plt.plot([0, 1], [0, 1], color='navy', lw=2, linestyle='--')\n# plt.xlim([0.0, 1.0])\n# plt.ylim([0.0, 1.05])\n# plt.xlabel('False Positive Rate', fontweight='bold')\n# plt.ylabel('True Positive Rate', fontweight='bold')\n# plt.title('Receiver Operating Characteristic (ROC)', fontweight='bold')\n# plt.legend(loc=\"lower right\")\n# plt.grid(alpha=0.3)\n\n# # PLOT 2: DEFAULT CONFUSION MATRIX\n# cm_default = confusion_matrix(all_labels, preds_default)\n# plt.subplot(1, 3, 2)\n# sns.heatmap(cm_default, annot=True, fmt='d', cmap='Blues', cbar=False,\n#             xticklabels=['Benign', 'Malignant'],\n#             yticklabels=['Benign', 'Malignant'],\n#             annot_kws={\"size\": 14, \"weight\": \"bold\"})\n# plt.xlabel('Predicted Label', fontweight='bold')\n# plt.ylabel('True Label', fontweight='bold')\n# plt.title('Default Confusion Matrix (Threshold = 0.5)', fontweight='bold')\n\n# # PLOT 3: OPTIMIZED CONFUSION MATRIX\n# cm_optimized = confusion_matrix(all_labels, preds_optimized)\n# plt.subplot(1, 3, 3)\n# sns.heatmap(cm_optimized, annot=True, fmt='d', cmap='Reds', cbar=False,\n#             xticklabels=['Benign', 'Malignant'],\n#             yticklabels=['Benign', 'Malignant'],\n#             annot_kws={\"size\": 14, \"weight\": \"bold\"})\n# plt.xlabel('Predicted Label', fontweight='bold')\n# plt.ylabel('True Label', fontweight='bold')\n# plt.title(f'Optimized Confusion Matrix (Threshold = {optimal_threshold:.4f})', fontweight='bold')\n\n# plt.tight_layout()\n# plt.show()\n\n# print(\"\\nKamaal ho gaya! In 3 graphs wali image ko save kar lein, yeh paper ke liye best comparison hai.\")","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# import os\n# import torch\n# import torch.nn as nn\n# import pandas as pd\n# import numpy as np\n# import matplotlib.pyplot as plt\n# import seaborn as sns\n# from sklearn.metrics import roc_curve, auc, confusion_matrix\n# from sklearn.model_selection import GroupKFold\n# from torch.utils.data import Dataset, DataLoader\n# from torchvision import transforms, models\n# from PIL import Image\n# from tqdm import tqdm\n\n# print(\"✅ Step 1 Done: Saari libraries successfully load ho gayi hain!\")","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"!pip install gdown -q\nimport gdown\n\ndrive_link = \"https://drive.google.com/file/d/1tFbV2YMFL01rlrLeqE35pOZ7ArO9Gs0x/view?usp=drive_link\"\nprint(\"Downloading model...\")\ngdown.download(drive_link, '/kaggle/working/resnet34_melanoma_exp4.pth', quiet=False, fuzzy=True)\nprint(\"✅ Step 2 Done: Model download ho gaya!\")","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')\n\n# # 1. SETUP MODEL & DATA\n# class MelanomaClassifier(nn.Module):\n#     def __init__(self, pretrained=False):\n#         super().__init__()\n#         self.backbone = models.resnet34(weights=None)\n#         in_features = self.backbone.fc.in_features\n#         self.backbone.fc = nn.Linear(in_features, 1)\n\n#     def forward(self, x):\n#         return self.backbone(x)\n\n# model = MelanomaClassifier().to(device)\n\n# TRAIN_CSV = '/kaggle/input/competitions/siim-isic-melanoma-classification/train.csv'\n# TRAIN_IMG_DIR = '/kaggle/input/competitions/siim-isic-melanoma-classification/jpeg/train'\n\n# df_train = pd.read_csv(TRAIN_CSV)\n# gkf = GroupKFold(n_splits=5)\n# df_train['fold'] = -1\n# for fold, (train_idx, val_idx) in enumerate(gkf.split(df_train, groups=df_train['patient_id'])):\n#     df_train.loc[val_idx, 'fold'] = fold\n\n# val_data = df_train[df_train['fold'] == 0]\n\n# class MelanomaDataset(Dataset):\n#     def __init__(self, df, img_dir, transform=None):\n#         self.df = df.reset_index(drop=True)\n#         self.img_dir = img_dir\n#         self.transform = transform\n\n#     def __len__(self):\n#         return len(self.df)\n\n#     def __getitem__(self, idx):\n#         row = self.df.iloc[idx]\n#         img_name = row['image_name']\n#         img_path = os.path.join(self.img_dir, f\"{img_name}.jpg\")\n#         image = Image.open(img_path).convert('RGB')\n#         label = torch.tensor(row['target'], dtype=torch.float32)\n#         if self.transform:\n#             image = self.transform(image)\n#         return image, label\n\n# val_transform = transforms.Compose([\n#     transforms.Resize((224, 224)),\n#     transforms.ToTensor(),\n#     transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])\n# ])\n\n# val_dataset = MelanomaDataset(val_data, TRAIN_IMG_DIR, transform=val_transform)\n# val_loader = DataLoader(val_dataset, batch_size=32, shuffle=False, num_workers=2)\n\n# # 2. LOAD WEIGHTS\n# model.load_state_dict(torch.load('/kaggle/working/resnet34_melanoma_exp4.pth', map_location=device))\n# model.eval()\n# print(\"✅ Weights Loaded. Running Inference...\\n\")\n\n# # 3. RUN INFERENCE\n# all_labels = []\n# all_preds = []\n\n# with torch.no_grad():\n#     val_loop = tqdm(val_loader, desc=\"Evaluating\")\n#     for images, labels in val_loop:\n#         images, labels = images.to(device), labels.to(device).unsqueeze(1)\n#         outputs = model(images)\n#         probs = torch.sigmoid(outputs).cpu().numpy()\n#         all_preds.extend(probs)\n#         all_labels.extend(labels.cpu().numpy())\n\n# all_labels = np.array(all_labels).flatten()\n# all_preds = np.array(all_preds).flatten()\n\n# # 4. CALCULATE OPTIMAL THRESHOLD\n# fpr, tpr, thresholds = roc_curve(all_labels, all_preds)\n# roc_auc = auc(fpr, tpr)\n# optimal_idx = np.argmax(tpr - fpr)\n# optimal_threshold = thresholds[optimal_idx]\n\n# preds_default = (all_preds > 0.5).astype(int)\n# preds_optimized = (all_preds > optimal_threshold).astype(int)\n\n# # 5. GENERATE PLOTS\n# plt.figure(figsize=(20, 6))\n\n# plt.subplot(1, 3, 1)\n# plt.plot(fpr, tpr, color='#e76f51', lw=2, label=f'AUC = {roc_auc:.4f}')\n# plt.plot([0, 1], [0, 1], color='navy', lw=2, linestyle='--')\n# plt.title('ROC Curve', fontweight='bold')\n# plt.legend(loc=\"lower right\")\n# plt.grid(alpha=0.3)\n\n# cm_default = confusion_matrix(all_labels, preds_default)\n# plt.subplot(1, 3, 2)\n# sns.heatmap(cm_default, annot=True, fmt='d', cmap='Blues', cbar=False, annot_kws={\"size\": 14, \"weight\": \"bold\"})\n# plt.title('Default Confusion Matrix (Threshold = 0.5)', fontweight='bold')\n\n# cm_optimized = confusion_matrix(all_labels, preds_optimized)\n# plt.subplot(1, 3, 3)\n# sns.heatmap(cm_optimized, annot=True, fmt='d', cmap='Reds', cbar=False, annot_kws={\"size\": 14, \"weight\": \"bold\"})\n# plt.title(f'Optimized Matrix (Threshold = {optimal_threshold:.4f})', fontweight='bold')\n\n# plt.tight_layout()\n# plt.show()\n\n# print(\"\\n✅ DONE! Yeh graphs save kar lein aapke paper ke liye ready hain.\")","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# import os\n# import torch\n# import torch.nn as nn\n# import pandas as pd\n# import numpy as np\n# import matplotlib.pyplot as plt\n# from torch.utils.data import Dataset, DataLoader\n# from torchvision import transforms, models\n# from PIL import Image\n# from sklearn.model_selection import train_test_split\n# from tqdm import tqdm\n\n# device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')\n# print(f\"✅ Step 1 Done: Libraries loaded. Using device: {device}\")","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# # 1. Advanced Data Augmentation\n# train_transform = transforms.Compose([\n#     transforms.Resize((224, 224)),\n#     transforms.RandomHorizontalFlip(p=0.5),\n#     transforms.RandomVerticalFlip(p=0.5),\n#     transforms.RandomRotation(30),\n#     transforms.ColorJitter(brightness=0.2, contrast=0.2),\n#     transforms.ToTensor(),\n#     transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])\n# ])\n\n# val_transform = transforms.Compose([\n#     transforms.Resize((224, 224)),\n#     transforms.ToTensor(),\n#     transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])\n# ])\n\n# # 2. Dataset Class\n# class MelanomaDataset(Dataset):\n#     def __init__(self, df, img_dir, transform=None):\n#         self.df = df.reset_index(drop=True)\n#         self.img_dir = img_dir\n#         self.transform = transform\n\n#     def __len__(self):\n#         return len(self.df)\n\n#     def __getitem__(self, idx):\n#         row = self.df.iloc[idx]\n#         img_name = row['image_name']\n#         img_path = os.path.join(self.img_dir, f\"{img_name}.jpg\")\n#         image = Image.open(img_path).convert('RGB')\n#         label = torch.tensor(row['target'], dtype=torch.float32)\n#         if self.transform:\n#             image = self.transform(image)\n#         return image, label\n\n# print(\"✅ Step 2 Done: Augmentation and Dataset defined.\")","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# # Paths\n# TRAIN_CSV = '/kaggle/input/competitions/siim-isic-melanoma-classification/train.csv'\n# TRAIN_IMG_DIR = '/kaggle/input/competitions/siim-isic-melanoma-classification/jpeg/train'\n\n# # Data Splitting\n# df = pd.read_csv(TRAIN_CSV)\n# df_train, df_val = train_test_split(df, test_size=0.2, random_state=42, stratify=df['target'])\n\n# train_dataset = MelanomaDataset(df_train, TRAIN_IMG_DIR, transform=train_transform)\n# val_dataset = MelanomaDataset(df_val, TRAIN_IMG_DIR, transform=val_transform)\n\n# train_loader = DataLoader(train_dataset, batch_size=32, shuffle=True, num_workers=2)\n# val_loader = DataLoader(val_dataset, batch_size=32, shuffle=False, num_workers=2)\n\n# # Model Setup\n# class MelanomaClassifier(nn.Module):\n#     def __init__(self):\n#         super().__init__()\n#         self.backbone = models.resnet34(weights='IMAGENET1K_V1') \n#         in_features = self.backbone.fc.in_features\n#         self.backbone.fc = nn.Linear(in_features, 1)\n\n#     def forward(self, x):\n#         return self.backbone(x)\n\n# model = MelanomaClassifier().to(device)\n\n# # THE MAGIC WAND: Weighted Loss\n# num_negatives = len(df_train[df_train['target'] == 0])\n# num_positives = len(df_train[df_train['target'] == 1])\n# weight_ratio = num_negatives / num_positives\n# pos_weight = torch.tensor([weight_ratio]).to(device)\n\n# print(f\"🔍 Dataset Ratio (Benign:Malignant) = {weight_ratio:.2f}:1\")\n# print(f\"✅ Step 3 Done: Model & Weighted Loss ready with pos_weight = {weight_ratio:.2f}\")\n\n# criterion = nn.BCEWithLogitsLoss(pos_weight=pos_weight)\n# optimizer = torch.optim.Adam(model.parameters(), lr=1e-4)","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# EPOCHS = 3 \n# best_val_loss = float('inf')\n# save_path = '/kaggle/working/resnet34_melanoma_exp5_weighted.pth'\n\n# print(\"🚀 Starting Training...\\n\")\n# for epoch in range(EPOCHS):\n#     # Training Phase\n#     model.train()\n#     train_loss = 0.0\n#     train_loop = tqdm(train_loader, desc=f\"Epoch {epoch+1}/{EPOCHS} [Train]\")\n    \n#     for images, labels in train_loop:\n#         images, labels = images.to(device), labels.to(device).unsqueeze(1)\n        \n#         optimizer.zero_grad()\n#         outputs = model(images)\n#         loss = criterion(outputs, labels)\n        \n#         loss.backward()\n#         optimizer.step()\n        \n#         train_loss += loss.item()\n#         train_loop.set_postfix(loss=loss.item())\n        \n#     avg_train_loss = train_loss / len(train_loader)\n    \n#     # Validation Phase\n#     model.eval()\n#     val_loss = 0.0\n#     with torch.no_grad():\n#         val_loop = tqdm(val_loader, desc=f\"Epoch {epoch+1}/{EPOCHS} [Val]\")\n#         for images, labels in val_loop:\n#             images, labels = images.to(device), labels.to(device).unsqueeze(1)\n#             outputs = model(images)\n#             loss = criterion(outputs, labels)\n#             val_loss += loss.item()\n            \n#     avg_val_loss = val_loss / len(val_loader)\n    \n#     print(f\"\\nEpoch {epoch+1} Summary -> Train Loss: {avg_train_loss:.4f} | Val Loss: {avg_val_loss:.4f}\")\n    \n#     # Save Best Model\n#     if avg_val_loss < best_val_loss:\n#         best_val_loss = avg_val_loss\n#         torch.save(model.state_dict(), save_path)\n#         print(f\"🌟 Best model saved to {save_path}!\\n\")\n\n# print(\"✅ Training Complete! Naya Weighted Model ready hai.\")","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# import os\n# import torch\n# import torch.nn as nn\n# import pandas as pd\n# import numpy as np\n# from torch.utils.data import Dataset, DataLoader\n# from torchvision import transforms, models\n# from PIL import Image\n# from sklearn.model_selection import train_test_split\n# from tqdm import tqdm\n\n# print(\"🚀 Initializing 10/10 Training Pipeline...\\n\")\n# device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')\n\n# # ==========================================\n# # 1. DATA PREPARATION & AUGMENTATION\n# # ==========================================\n# train_transform = transforms.Compose([\n#     transforms.Resize((224, 224)),\n#     transforms.RandomHorizontalFlip(p=0.5),\n#     transforms.RandomVerticalFlip(p=0.5),\n#     transforms.RandomRotation(30),\n#     transforms.ColorJitter(brightness=0.2, contrast=0.2),\n#     transforms.ToTensor(),\n#     transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])\n# ])\n\n# val_transform = transforms.Compose([\n#     transforms.Resize((224, 224)),\n#     transforms.ToTensor(),\n#     transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])\n# ])\n\n# class MelanomaDataset(Dataset):\n#     def __init__(self, df, img_dir, transform=None):\n#         self.df = df.reset_index(drop=True)\n#         self.img_dir = img_dir\n#         self.transform = transform\n\n#     def __len__(self):\n#         return len(self.df)\n\n#     def __getitem__(self, idx):\n#         row = self.df.iloc[idx]\n#         img_name = row['image_name']\n#         img_path = os.path.join(self.img_dir, f\"{img_name}.jpg\")\n#         image = Image.open(img_path).convert('RGB')\n#         label = torch.tensor(row['target'], dtype=torch.float32)\n#         if self.transform:\n#             image = self.transform(image)\n#         return image, label\n\n# TRAIN_CSV = '/kaggle/input/competitions/siim-isic-melanoma-classification/train.csv'\n# TRAIN_IMG_DIR = '/kaggle/input/competitions/siim-isic-melanoma-classification/jpeg/train'\n\n# df = pd.read_csv(TRAIN_CSV)\n# df_train, df_val = train_test_split(df, test_size=0.2, random_state=42, stratify=df['target'])\n\n# train_dataset = MelanomaDataset(df_train, TRAIN_IMG_DIR, transform=train_transform)\n# val_dataset = MelanomaDataset(df_val, TRAIN_IMG_DIR, transform=val_transform)\n\n# train_loader = DataLoader(train_dataset, batch_size=32, shuffle=True, num_workers=2)\n# val_loader = DataLoader(val_dataset, batch_size=32, shuffle=False, num_workers=2)\n\n# # ==========================================\n# # 2. MODEL DEFINITION (Error Fix)\n# # ==========================================\n# class MelanomaClassifier(nn.Module):\n#     def __init__(self):\n#         super().__init__()\n#         # Using pretrained ResNet34\n#         self.backbone = models.resnet34(weights='IMAGENET1K_V1') \n#         in_features = self.backbone.fc.in_features\n#         self.backbone.fc = nn.Linear(in_features, 1)\n\n#     def forward(self, x):\n#         return self.backbone(x)\n\n# # Model initialize kar ke device (GPU/CPU) par bhej diya gaya\n# model = MelanomaClassifier().to(device)\n# print(\"✅ Model created successfully!\")\n\n# # ==========================================\n# # 3. WEIGHTED LOSS (The Magic Wand)\n# # ==========================================\n# num_negatives = len(df_train[df_train['target'] == 0])\n# num_positives = len(df_train[df_train['target'] == 1])\n# weight_ratio = num_negatives / num_positives\n# pos_weight = torch.tensor([weight_ratio]).to(device)\n\n# print(f\"🔍 Dataset Ratio -> Benign : Malignant = {weight_ratio:.2f} : 1\")\n# criterion = nn.BCEWithLogitsLoss(pos_weight=pos_weight)\n# optimizer = torch.optim.Adam(model.parameters(), lr=1e-4)\n\n# # ==========================================\n# # 4. TRAINING LOOP\n# # ==========================================\n# EPOCHS = 3 \n# best_val_loss = float('inf')\n# save_path = '/kaggle/working/resnet34_melanoma_exp5_weighted.pth'\n\n# print(\"🚀 Starting Training Loop...\\n\")\n# for epoch in range(EPOCHS):\n#     # Training Phase\n#     model.train()\n#     train_loss = 0.0\n#     train_loop = tqdm(train_loader, desc=f\"Epoch {epoch+1}/{EPOCHS} [Train]\")\n    \n#     for images, labels in train_loop:\n#         images, labels = images.to(device), labels.to(device).unsqueeze(1)\n        \n#         optimizer.zero_grad()\n#         outputs = model(images)\n#         loss = criterion(outputs, labels)\n        \n#         loss.backward()\n#         optimizer.step()\n        \n#         train_loss += loss.item()\n#         train_loop.set_postfix(loss=loss.item())\n        \n#     avg_train_loss = train_loss / len(train_loader)\n    \n#     # Validation Phase\n#     model.eval()\n#     val_loss = 0.0\n#     with torch.no_grad():\n#         val_loop = tqdm(val_loader, desc=f\"Epoch {epoch+1}/{EPOCHS} [Val]\")\n#         for images, labels in val_loop:\n#             images, labels = images.to(device), labels.to(device).unsqueeze(1)\n#             outputs = model(images)\n#             loss = criterion(outputs, labels)\n#             val_loss += loss.item()\n            \n#     avg_val_loss = val_loss / len(val_loader)\n    \n#     print(f\"\\nEpoch {epoch+1} Summary -> Train Loss: {avg_train_loss:.4f} | Val Loss: {avg_val_loss:.4f}\")\n    \n#     # Save Best Model\n#     if avg_val_loss < best_val_loss:\n#         best_val_loss = avg_val_loss\n#         torch.save(model.state_dict(), save_path)\n#         print(f\"🌟 Best model saved to {save_path}!\\n\")\n\n# print(\"✅ Training Complete! Naya Weighted Model ready hai.\")","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# !pip install gdown -q\n# import gdown\n# import os\n# import torch\n# import torch.nn as nn\n# import pandas as pd\n# import numpy as np\n# import matplotlib.pyplot as plt\n# import seaborn as sns\n# from sklearn.metrics import roc_curve, auc, confusion_matrix\n# from sklearn.model_selection import GroupKFold\n# from torch.utils.data import Dataset, DataLoader\n# from torchvision import transforms, models\n# from PIL import Image\n# from tqdm import tqdm\n\n# print(\"🚀 Starting Final Evaluation with NEW Google Drive Model...\\n\")\n# device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')\n\n# # ==========================================\n# # 1. DOWNLOAD MODEL FROM NEW DRIVE LINK\n# # ==========================================\n# drive_link = \"https://drive.google.com/file/d/1igpS4q4450b7qmd3Azy4B48ysiyHNm2-/view?usp=sharing\"\n# model_path = '/kaggle/working/resnet34_melanoma_latest.pth'\n\n# # Agar purani file pari hai toh usay hata dein taake naya model fresh download ho\n# if os.path.exists(model_path):\n#     os.remove(model_path)\n\n# print(\"Downloading new model from Google Drive...\")\n# gdown.download(drive_link, model_path, quiet=False, fuzzy=True)\n# print(\"✅ Model downloaded successfully!\\n\")\n\n# # ==========================================\n# # 2. DATA SETUP (Only Validation needed)\n# # ==========================================\n# TRAIN_CSV = '/kaggle/input/competitions/siim-isic-melanoma-classification/train.csv'\n# TRAIN_IMG_DIR = '/kaggle/input/competitions/siim-isic-melanoma-classification/jpeg/train'\n\n# df_train = pd.read_csv(TRAIN_CSV)\n# gkf = GroupKFold(n_splits=5)\n# df_train['fold'] = -1\n# for fold, (train_idx, val_idx) in enumerate(gkf.split(df_train, groups=df_train['patient_id'])):\n#     df_train.loc[val_idx, 'fold'] = fold\n\n# val_data = df_train[df_train['fold'] == 0]\n\n# val_transform = transforms.Compose([\n#     transforms.Resize((224, 224)),\n#     transforms.ToTensor(),\n#     transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])\n# ])\n\n# class MelanomaDataset(Dataset):\n#     def __init__(self, df, img_dir, transform=None):\n#         self.df = df.reset_index(drop=True)\n#         self.img_dir = img_dir\n#         self.transform = transform\n#     def __len__(self): return len(self.df)\n#     def __getitem__(self, idx):\n#         row = self.df.iloc[idx]\n#         image = Image.open(os.path.join(self.img_dir, f\"{row['image_name']}.jpg\")).convert('RGB')\n#         label = torch.tensor(row['target'], dtype=torch.float32)\n#         if self.transform: image = self.transform(image)\n#         return image, label\n\n# val_dataset = MelanomaDataset(val_data, TRAIN_IMG_DIR, transform=val_transform)\n# val_loader = DataLoader(val_dataset, batch_size=32, shuffle=False, num_workers=2)\n\n# # ==========================================\n# # 3. LOAD MODEL & INFERENCE\n# # ==========================================\n# class MelanomaClassifier(nn.Module):\n#     def __init__(self):\n#         super().__init__()\n#         self.backbone = models.resnet34(weights=None)\n#         self.backbone.fc = nn.Linear(self.backbone.fc.in_features, 1)\n#     def forward(self, x): return self.backbone(x)\n\n# model = MelanomaClassifier().to(device)\n# model.load_state_dict(torch.load(model_path, map_location=device))\n# model.eval()\n\n# all_labels, all_preds = [], []\n# with torch.no_grad():\n#     val_loop = tqdm(val_loader, desc=\"Generating Final Results\")\n#     for images, labels in val_loop:\n#         probs = torch.sigmoid(model(images.to(device))).cpu().numpy()\n#         all_preds.extend(probs)\n#         all_labels.extend(labels.numpy())\n\n# all_labels = np.array(all_labels).flatten()\n# all_preds = np.array(all_preds).flatten()\n\n# # ==========================================\n# # 4. PLOTTING GRAPHS\n# # ==========================================\n# fpr, tpr, thresholds = roc_curve(all_labels, all_preds)\n# roc_auc = auc(fpr, tpr)\n# optimal_threshold = thresholds[np.argmax(tpr - fpr)]\n\n# preds_default = (all_preds > 0.5).astype(int)\n# preds_optimized = (all_preds > optimal_threshold).astype(int)\n\n# plt.figure(figsize=(20, 6))\n\n# plt.subplot(1, 3, 1)\n# plt.plot(fpr, tpr, color='#e76f51', lw=2, label=f'ResNet34 (AUC = {roc_auc:.4f})')\n# plt.plot([0, 1], [0, 1], color='navy', lw=2, linestyle='--')\n# plt.title('Receiver Operating Characteristic (ROC)', fontweight='bold')\n# plt.legend(loc=\"lower right\")\n\n# plt.subplot(1, 3, 2)\n# sns.heatmap(confusion_matrix(all_labels, preds_default), annot=True, fmt='d', cmap='Blues', cbar=False,\n#             xticklabels=['Benign', 'Malignant'], yticklabels=['Benign', 'Malignant'], annot_kws={\"size\": 15, \"weight\": \"bold\"})\n# plt.title('Default Matrix (Threshold = 0.5)', fontweight='bold')\n\n# plt.subplot(1, 3, 3)\n# sns.heatmap(confusion_matrix(all_labels, preds_optimized), annot=True, fmt='d', cmap='Reds', cbar=False,\n#             xticklabels=['Benign', 'Malignant'], yticklabels=['Benign', 'Malignant'], annot_kws={\"size\": 15, \"weight\": \"bold\"})\n# plt.title(f'Optimized Matrix (Threshold = {optimal_threshold:.4f})', fontweight='bold')\n\n# plt.tight_layout()\n# plt.show()\n\n# print(\"\\n🎉 ALL DONE! Is tasweer ko jaldi se save karein aur paper mukammal karein. Best of luck!\")","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"!pip install gdown -q\nimport gdown  # <-- Yeh line miss ho gayi thi!\nimport os\nimport torch\nimport torch.nn as nn\nimport pandas as pd\nimport numpy as np\nimport matplotlib.pyplot as plt\nimport seaborn as sns\nfrom sklearn.metrics import roc_curve, auc, confusion_matrix\nfrom sklearn.model_selection import train_test_split\nfrom torch.utils.data import Dataset, DataLoader\nfrom torchvision import transforms, models\nfrom PIL import Image\nfrom tqdm import tqdm\n\nprint(\"🚀 Starting Unified Evaluation (Baseline vs Weighted)...\\n\")\ndevice = torch.device('cuda' if torch.cuda.is_available() else 'cpu')\n\n# ==========================================\n# 1. DOWNLOAD BOTH MODELS\n# ==========================================\nbaseline_link = \"https://drive.google.com/file/d/1tFbV2YMFL01rlrLeqE35pOZ7ArO9Gs0x/view?usp=drive_link\"\nweighted_link = \"https://drive.google.com/file/d/1igpS4q4450b7qmd3Azy4B48ysiyHNm2-/view?usp=sharing\"\n\nbase_path = '/kaggle/working/baseline.pth'\nweight_path = '/kaggle/working/weighted.pth'\n\nif not os.path.exists(base_path): gdown.download(baseline_link, base_path, quiet=True, fuzzy=True)\nif not os.path.exists(weight_path): gdown.download(weighted_link, weight_path, quiet=True, fuzzy=True)\nprint(\"✅ Both models downloaded successfully!\\n\")\n\n# ==========================================\n# 2. STRICT DATA SPLIT (Hold-out Test Set)\n# ==========================================\nTRAIN_CSV = '/kaggle/input/competitions/siim-isic-melanoma-classification/train.csv'\nTRAIN_IMG_DIR = '/kaggle/input/competitions/siim-isic-melanoma-classification/jpeg/train'\n\ndf = pd.read_csv(TRAIN_CSV)\n# Strict stratify to lock down the test set distribution\n_, df_test = train_test_split(df, test_size=0.2, random_state=42, stratify=df['target'])\n\nval_transform = transforms.Compose([\n    transforms.Resize((224, 224)),\n    transforms.ToTensor(),\n    transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])\n])\n\nclass MelanomaDataset(Dataset):\n    def __init__(self, df, img_dir, transform=None):\n        self.df = df.reset_index(drop=True)\n        self.img_dir = img_dir\n        self.transform = transform\n    def __len__(self): return len(self.df)\n    def __getitem__(self, idx):\n        row = self.df.iloc[idx]\n        image = Image.open(os.path.join(self.img_dir, f\"{row['image_name']}.jpg\")).convert('RGB')\n        label = torch.tensor(row['target'], dtype=torch.float32)\n        if self.transform: image = self.transform(image)\n        return image, label\n\ntest_dataset = MelanomaDataset(df_test, TRAIN_IMG_DIR, transform=val_transform)\ntest_loader = DataLoader(test_dataset, batch_size=32, shuffle=False, num_workers=2)\n\n# ==========================================\n# 3. MODEL DEFINITION\n# ==========================================\nclass MelanomaClassifier(nn.Module):\n    def __init__(self):\n        super().__init__()\n        self.backbone = models.resnet34(weights=None)\n        self.backbone.fc = nn.Linear(self.backbone.fc.in_features, 1)\n    def forward(self, x): return self.backbone(x)\n\ndef evaluate_model(model_path, loader):\n    model = MelanomaClassifier().to(device)\n    model.load_state_dict(torch.load(model_path, map_location=device))\n    model.eval()\n    \n    all_labels, all_preds = [], []\n    with torch.no_grad():\n        for images, labels in tqdm(loader, desc=f\"Evaluating {model_path.split('/')[-1]}\"):\n            probs = torch.sigmoid(model(images.to(device))).cpu().numpy()\n            all_preds.extend(probs)\n            all_labels.extend(labels.numpy())\n            \n    return np.array(all_labels).flatten(), np.array(all_preds).flatten()\n\nprint(\"🔍 Evaluating Baseline Model...\")\nlabels_base, preds_base = evaluate_model(base_path, test_loader)\nprint(\"🔍 Evaluating Weighted Model...\")\nlabels_weight, preds_weight = evaluate_model(weight_path, test_loader)\n\n# ==========================================\n# 4. PLOTTING THE UNIFIED STORY\n# ==========================================\ndef get_metrics(y_true, y_pred):\n    fpr, tpr, thresholds = roc_curve(y_true, y_pred)\n    opt_idx = np.argmax(tpr - fpr)\n    return fpr, tpr, thresholds[opt_idx], auc(fpr, tpr)\n\nfpr_b, tpr_b, thresh_b, auc_b = get_metrics(labels_base, preds_base)\nfpr_w, tpr_w, thresh_w, auc_w = get_metrics(labels_weight, preds_weight)\n\nfig, axes = plt.subplots(2, 3, figsize=(20, 12))\nplt.subplots_adjust(hspace=0.3)\n\n# --- ROW 1: BASELINE ---\naxes[0,0].plot(fpr_b, tpr_b, color='#1f77b4', lw=2, label=f'Baseline (AUC = {auc_b:.4f})')\naxes[0,0].plot([0, 1], [0, 1], color='black', linestyle='--')\naxes[0,0].set_title('Baseline ROC Curve', fontweight='bold')\naxes[0,0].legend(loc=\"lower right\")\n\nsns.heatmap(confusion_matrix(labels_base, (preds_base > 0.5).astype(int)), annot=True, fmt='d', cmap='Blues', cbar=False, ax=axes[0,1], annot_kws={\"size\": 14, \"weight\": \"bold\"})\naxes[0,1].set_title('Baseline Default (Threshold = 0.5)', fontweight='bold')\n\nsns.heatmap(confusion_matrix(labels_base, (preds_base > thresh_b).astype(int)), annot=True, fmt='d', cmap='Blues', cbar=False, ax=axes[0,2], annot_kws={\"size\": 14, \"weight\": \"bold\"})\naxes[0,2].set_title(f'Baseline Optimized (Threshold = {thresh_b:.4f})', fontweight='bold')\n\n# --- ROW 2: WEIGHTED ---\naxes[1,0].plot(fpr_w, tpr_w, color='#e76f51', lw=2, label=f'Weighted (AUC = {auc_w:.4f})')\naxes[1,0].plot([0, 1], [0, 1], color='black', linestyle='--')\naxes[1,0].set_title('Weighted ROC Curve', fontweight='bold')\naxes[1,0].legend(loc=\"lower right\")\n\nsns.heatmap(confusion_matrix(labels_weight, (preds_weight > 0.5).astype(int)), annot=True, fmt='d', cmap='Reds', cbar=False, ax=axes[1,1], annot_kws={\"size\": 14, \"weight\": \"bold\"})\naxes[1,1].set_title('Weighted Default (Threshold = 0.5)', fontweight='bold')\n\nsns.heatmap(confusion_matrix(labels_weight, (preds_weight > thresh_w).astype(int)), annot=True, fmt='d', cmap='Reds', cbar=False, ax=axes[1,2], annot_kws={\"size\": 14, \"weight\": \"bold\"})\naxes[1,2].set_title(f'Weighted Optimized (Threshold = {thresh_w:.4f})', fontweight='bold')\n\nplt.show()\nprint(\"\\n🎉 DONE! Is ek image ko paper mein laga dein, reviewer ki pehli demand poori ho gayi!\")","metadata":{"trusted":true},"outputs":[],"execution_count":null}]}