{"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":"import os\nimport numpy as np\nimport pandas as pd\nimport matplotlib.pyplot as plt\nimport seaborn as sns\nfrom sklearn.metrics import accuracy_score, f1_score, cohen_kappa_score, roc_auc_score, roc_curve, confusion_matrix\nfrom sklearn.model_selection import train_test_split\nimport torch\nimport torch.nn as nn\nfrom torch.utils.data import Dataset, DataLoader\nfrom torchvision import models, transforms\nimport pydicom\nfrom PIL import Image\n\n# Device setup\ndevice = torch.device('cuda' if torch.cuda.is_available() else 'cpu')\n\n# CSV and image root\ndata_csv = '/kaggle/input/rsna-miccai-brain-tumor-radiogenomic-classification/train_labels.csv'\ndata_root = '/kaggle/input/rsna-miccai-brain-tumor-radiogenomic-classification/train'\n\ndf = pd.read_csv(data_csv)\ndf = df.dropna()  # drop rows with missing labels\n\n# Train/val/test split\ntrain_ids, test_ids = train_test_split(df, test_size=0.2, random_state=42, stratify=df['MGMT_value'])\ntrain_ids, val_ids = train_test_split(train_ids, test_size=0.1, random_state=42, stratify=train_ids['MGMT_value'])\n\n# Image transform\ntransform = transforms.Compose([\n    transforms.Resize((128, 128)),\n    transforms.ToTensor(),\n    transforms.Normalize([0.5], [0.5])\n])\n\nclass BrainDataset(Dataset):\n    def __init__(self, df, root_dir, transform=None):\n        self.df = df.reset_index(drop=True)\n        self.root_dir = root_dir\n        self.transform = transform\n\n    def __len__(self):\n        return len(self.df)\n\n    def __getitem__(self, idx):\n        patient_id = str(self.df.loc[idx, 'BraTS21ID']).zfill(5)\n        label = int(self.df.loc[idx, 'MGMT_value'])\n\n        flair_path = os.path.join(self.root_dir, patient_id, 'FLAIR')\n        slices = sorted(os.listdir(flair_path))\n        mid_slice = slices[len(slices) // 2]\n\n        dicom = pydicom.dcmread(os.path.join(flair_path, mid_slice))\n        img = dicom.pixel_array.astype(np.float32)\n        img = (img - np.min(img)) / (np.max(img) - np.min(img))\n        img = Image.fromarray((img * 255).astype(np.uint8)).convert('L')\n\n        if self.transform:\n            img = self.transform(img)\n\n        return img, torch.tensor(label).long()\n\n# Loaders\ntrain_ds = BrainDataset(train_ids, data_root, transform)\nval_ds = BrainDataset(val_ids, data_root, transform)\ntest_ds = BrainDataset(test_ids, data_root, transform)\n\ntrain_loader = DataLoader(train_ds, batch_size=16, shuffle=True, num_workers=2)\nval_loader = DataLoader(val_ds, batch_size=16, shuffle=False, num_workers=2)\ntest_loader = DataLoader(test_ds, batch_size=16, shuffle=False, num_workers=2)\n\n# Model\nmodel = models.densenet121(pretrained=True)\nmodel.features.conv0 = nn.Conv2d(1, 64, kernel_size=7, stride=2, padding=3, bias=False)  # for 1-channel\nmodel.classifier = nn.Linear(model.classifier.in_features, 2)\nmodel = model.to(device)\n\n# Loss and optimizer\ncriterion = nn.CrossEntropyLoss()\noptimizer = torch.optim.Adam(model.parameters(), lr=1e-4)\n\n# Training loop\ntrain_losses, val_losses, train_accs, val_accs = [], [], [], []\nfor epoch in range(10):\n    model.train()\n    correct, total, loss_sum = 0, 0, 0\n    for x, y in train_loader:\n        x, y = x.to(device), y.to(device)\n        out = model(x)\n        loss = criterion(out, y)\n\n        optimizer.zero_grad()\n        loss.backward()\n        optimizer.step()\n\n        loss_sum += loss.item() * x.size(0)\n        _, pred = torch.max(out, 1)\n        correct += (pred == y).sum().item()\n        total += y.size(0)\n\n    train_losses.append(loss_sum / total)\n    train_accs.append(correct / total)\n\n    # Validation\n    model.eval()\n    correct, total, val_loss = 0, 0, 0\n    with torch.no_grad():\n        for x, y in val_loader:\n            x, y = x.to(device), y.to(device)\n            out = model(x)\n            loss = criterion(out, y)\n            val_loss += loss.item() * x.size(0)\n            _, pred = torch.max(out, 1)\n            correct += (pred == y).sum().item()\n            total += y.size(0)\n\n    val_losses.append(val_loss / total)\n    val_accs.append(correct / total)\n\n    print(f\"Epoch {epoch+1}/10 - Train Acc: {train_accs[-1]:.4f}, Val Acc: {val_accs[-1]:.4f}\")\n\n# Test evaluation\nmodel.eval()\ny_true, y_pred, y_prob = [], [], []\nwith torch.no_grad():\n    for x, y in test_loader:\n        x = x.to(device)\n        out = model(x)\n        prob = torch.softmax(out, 1)[:, 1].cpu().numpy()\n        pred = torch.argmax(out, 1).cpu().numpy()\n        y_true.extend(y.numpy())\n        y_pred.extend(pred)\n        y_prob.extend(prob)\n\n# Metrics\ntest_acc = accuracy_score(y_true, y_pred)\nf1 = f1_score(y_true, y_pred)\nkappa = cohen_kappa_score(y_true, y_pred)\nauc = roc_auc_score(y_true, y_prob)\nprint(f\"\\nTest Accuracy: {test_acc:.4f}, F1: {f1:.4f}, Kappa: {kappa:.4f}, AUC: {auc:.4f}\")\n\n# Graphs\nplt.figure()\nplt.plot(train_accs, label='Train Acc')\nplt.plot(val_accs, label='Val Acc')\nplt.legend()\nplt.title('Accuracy over Epochs')\nplt.show()\n\nplt.figure()\nplt.plot(train_losses, label='Train Loss')\nplt.plot(val_losses, label='Val Loss')\nplt.legend()\nplt.title('Loss over Epochs')\nplt.show()\n\nfpr, tpr, _ = roc_curve(y_true, y_prob)\nplt.figure()\nplt.plot(fpr, tpr, label=f'AUC = {auc:.4f}')\nplt.plot([0, 1], [0, 1], 'k--')\nplt.xlabel('FPR')\nplt.ylabel('TPR')\nplt.title('ROC Curve')\nplt.legend()\nplt.show()\n\ncm = confusion_matrix(y_true, y_pred)\nsns.heatmap(cm, annot=True, fmt='d', cmap='Blues')\nplt.title('Confusion Matrix')\nplt.xlabel('Predicted')\nplt.ylabel('Actual')\nplt.show()\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-04T18:36:47.096991Z","iopub.execute_input":"2025-05-04T18:36:47.097406Z","iopub.status.idle":"2025-05-04T18:45:19.933259Z","shell.execute_reply.started":"2025-05-04T18:36:47.097378Z","shell.execute_reply":"2025-05-04T18:45:19.931768Z"}},"outputs":[],"execution_count":null}]}