{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.11.11","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"},"kaggle":{"accelerator":"none","dataSources":[{"sourceId":29653,"databundleVersionId":2420395,"sourceType":"competition"}],"dockerImageVersionId":31012,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":false}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"# =============================\n# 1. Imports\n# =============================\nimport os\nimport numpy as np\nimport pandas as pd\nimport pydicom\nimport torch\nimport torch.nn as nn\nimport torch.optim as optim\nimport torchvision.models as models\nfrom torch.utils.data import Dataset, DataLoader, random_split\nfrom sklearn.metrics import accuracy_score, f1_score, cohen_kappa_score, roc_auc_score\nimport cv2\n\n# =============================\n# 2. Configurations\n# =============================\nclass CFG:\n    path = \"/kaggle/input/rsna-miccai-brain-tumor-radiogenomic-classification/\"\n    num_classes = 1\n    batch_size = 8\n    num_epochs = 5\n    learning_rate = 1e-4\n    device = torch.device(\"cuda\" if torch.cuda.is_available() else \"cpu\")\n    img_size = (224, 224)\n\n# =============================\n# 3. Dataset\n# =============================\nclass BrainTumorDataset(Dataset):\n    def __init__(self, csv_file, folder):\n        self.labels = pd.read_csv(csv_file)\n        self.folder = folder\n\n    def __len__(self):\n        return len(self.labels)\n\n    def __getitem__(self, idx):\n        patient_id = str(self.labels.iloc[idx, 0]).zfill(5)\n        label = self.labels.iloc[idx, 1]\n        img = self.load_mri_image(patient_id)\n        return img, torch.tensor(label, dtype=torch.float32)\n\n    def load_mri_image(self, folder, scan_type=\"FLAIR\"):\n        path_file = os.path.join(CFG.path, 'train', folder, scan_type)\n        slices = [s for s in os.listdir(path_file) if s.endswith('.dcm')]\n        slices.sort()\n        mid = len(slices) // 2\n        selected = [slices[mid-1], slices[mid], slices[mid+1]]\n        imgs = []\n        for s in selected:\n            dcm = pydicom.dcmread(os.path.join(path_file, s))\n            img = dcm.pixel_array\n            img = cv2.resize(img, CFG.img_size)\n            imgs.append(img)\n        imgs = np.stack(imgs, axis=0)\n        imgs = imgs / np.max(imgs)\n        return torch.tensor(imgs, dtype=torch.float32)\n\n# =============================\n# 4. Model\n# =============================\nclass ImageClf(nn.Module):\n    def __init__(self):\n        super(ImageClf, self).__init__()\n        self.enc = models.resnet152(pretrained=True)\n        self.enc.fc = nn.Identity()\n        self.pooler = nn.AdaptiveAvgPool2d((1,1))\n        self.clf = nn.Linear(2048, 1)\n\n    def forward(self, x):\n        x = self.enc.conv1(x)\n        x = self.enc.bn1(x)\n        x = self.enc.relu(x)\n        x = self.enc.maxpool(x)\n        x = self.enc.layer1(x)\n        x = self.enc.layer2(x)\n        x = self.enc.layer3(x)\n        x = self.enc.layer4(x)\n        x = self.pooler(x).squeeze(-1).squeeze(-1)\n        x = self.clf(x)\n        return x.squeeze(-1)\n\n# =============================\n# 5. Training and Evaluation\n# =============================\n\ndef train_fn(model, loader, optimizer, criterion):\n    model.train()\n    all_preds = []\n    all_labels = []\n    for imgs, labels in loader:\n        imgs, labels = imgs.to(CFG.device), labels.to(CFG.device)\n        optimizer.zero_grad()\n        outputs = model(imgs)\n        loss = criterion(outputs, labels)\n        loss.backward()\n        optimizer.step()\n\n        preds = torch.sigmoid(outputs) > 0.5\n        all_preds.extend(preds.cpu().numpy())\n        all_labels.extend(labels.cpu().numpy())\n\n    acc = accuracy_score(all_labels, all_preds)\n    return acc\n\n\ndef eval_fn(model, loader):\n    model.eval()\n    all_preds = []\n    all_probs = []\n    all_labels = []\n\n    with torch.no_grad():\n        for imgs, labels in loader:\n            imgs, labels = imgs.to(CFG.device), labels.to(CFG.device)\n\n            outputs = model(imgs)\n            probs = torch.sigmoid(outputs)\n\n            # Handle NaNs early\n            probs = torch.nan_to_num(probs, nan=0.0)\n\n            preds = probs > 0.5\n\n            all_preds.extend(preds.cpu().numpy())\n            all_probs.extend(probs.cpu().numpy())\n            all_labels.extend(labels.cpu().numpy())\n\n    acc = accuracy_score(all_labels, all_preds)\n    f1 = f1_score(all_labels, all_preds)\n    kappa = cohen_kappa_score(all_labels, all_preds)\n\n    try:\n        roc = roc_auc_score(all_labels, all_probs)\n    except ValueError:\n        roc = float('nan')  # If only one class present in y_true, AUC can't be computed\n\n    return acc, f1, kappa, roc\n\n\n# =============================\n# 6. Run everything\n# =============================\nfull_dataset = BrainTumorDataset(CFG.path + 'train_labels.csv', CFG.path)\ntrain_size = int(0.7 * len(full_dataset))\nval_size = int(0.15 * len(full_dataset))\ntest_size = len(full_dataset) - train_size - val_size\n\ntrain_ds, val_ds, test_ds = random_split(full_dataset, [train_size, val_size, test_size])\ntrain_loader = DataLoader(train_ds, batch_size=CFG.batch_size, shuffle=True)\nval_loader = DataLoader(val_ds, batch_size=CFG.batch_size, shuffle=False)\ntest_loader = DataLoader(test_ds, batch_size=CFG.batch_size, shuffle=False)\n\nmodel = ImageClf().to(CFG.device)\noptimizer = optim.Adam(model.parameters(), lr=CFG.learning_rate)\ncriterion = nn.BCEWithLogitsLoss()\n\nfor epoch in range(CFG.num_epochs):\n    train_acc = train_fn(model, train_loader, optimizer, criterion)\n    val_acc, val_f1, val_kappa, val_roc = eval_fn(model, val_loader)\n    print(f\"Epoch {epoch+1}/{CFG.num_epochs} => Train Acc: {train_acc:.4f} | Val Acc: {val_acc:.4f} | F1: {val_f1:.4f} | Kappa: {val_kappa:.4f} | ROC-AUC: {val_roc:.4f}\")\n\n# Final test evaluation\ntest_acc, test_f1, test_kappa, test_roc = eval_fn(model, test_loader)\nprint(\"\\n=== FINAL TEST RESULTS ===\")\nprint(f\"Test Accuracy: {test_acc:.4f}\")\nprint(f\"Test F1 Score: {test_f1:.4f}\")\nprint(f\"Test Cohen's Kappa: {test_kappa:.4f}\")\nprint(f\"Test ROC AUC: {test_roc:.4f}\")\n","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true,"execution":{"iopub.status.busy":"2025-04-29T18:09:53.970947Z","iopub.execute_input":"2025-04-29T18:09:53.971253Z","iopub.status.idle":"2025-04-29T18:40:15.320420Z","shell.execute_reply.started":"2025-04-29T18:09:53.971232Z","shell.execute_reply":"2025-04-29T18:40:15.319438Z"}},"outputs":[],"execution_count":null}]}