{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.11.13","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"},"kaggle":{"accelerator":"nvidiaTeslaT4","dataSources":[{"sourceType":"competition","sourceId":29653,"databundleVersionId":2420395}],"dockerImageVersionId":31154,"isInternetEnabled":false,"language":"python","sourceType":"notebook","isGpuEnabled":true}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"# =========================\n# INSTALL\n# =========================\n!pip install -q pydicom\n\n# =========================\n# IMPORTS\n# =========================\nimport pandas as pd\nimport numpy as np\nimport os\nimport pydicom\nimport torch\nimport torch.nn as nn\nimport torch.optim as optim\nfrom torch.utils.data import Dataset, DataLoader\nfrom sklearn.model_selection import train_test_split\nfrom sklearn.metrics import accuracy_score, f1_score, cohen_kappa_score, roc_auc_score, roc_curve, confusion_matrix, ConfusionMatrixDisplay\nfrom skimage.transform import resize\nimport torchvision.models as models\nimport matplotlib.pyplot as plt\nfrom IPython.display import Image, display\nimport warnings\nwarnings.filterwarnings(\"ignore\")\n\n# =========================\n# SAVE DIRECTORY + DISPLAY\n# =========================\nSAVE_DIR = \"/kaggle/working/\"\nos.makedirs(SAVE_DIR, exist_ok=True)\n\ndef save_and_show(fig, filename):\n    path = os.path.join(SAVE_DIR, filename)\n    fig.savefig(path, bbox_inches='tight')\n    plt.close(fig)\n    display(Image(filename=path))\n\n# =========================\n# DATASET\n# =========================\nclass MRIDataset2D(Dataset):\n    def __init__(self, df, data_dir):\n        self.df = df.reset_index(drop=True)\n        self.data_dir = data_dir\n\n    def __len__(self):\n        return len(self.df)\n\n    def __getitem__(self, idx):\n        row = self.df.iloc[idx]\n        pid = str(row['BraTS21ID']).zfill(5)\n        path = os.path.join(self.data_dir, pid)\n\n        img = np.zeros((224,224), dtype=np.float32)\n\n        try:\n            m_path = os.path.join(path, \"FLAIR\")\n            files = sorted([f for f in os.listdir(m_path) if f.endswith('.dcm')])\n\n            if len(files) > 0:\n                f = files[len(files)//2]\n                dcm = pydicom.dcmread(os.path.join(m_path, f))\n                img = dcm.pixel_array.astype(np.float32)\n                img = resize(img, (224,224), preserve_range=True)\n                img = (img - np.mean(img)) / (np.std(img)+1e-8)\n        except:\n            pass\n\n        img = np.stack([img]*3, axis=0)\n        return torch.FloatTensor(img), torch.FloatTensor([row['MGMT_value']])\n\n# =========================\n# CNN\n# =========================\nclass SimpleCNN(nn.Module):\n    def __init__(self):\n        super().__init__()\n        self.net = nn.Sequential(\n            nn.Conv2d(3,32,3,padding=1),\n            nn.ReLU(),\n            nn.MaxPool2d(2),\n\n            nn.Conv2d(32,64,3,padding=1),\n            nn.ReLU(),\n            nn.MaxPool2d(2),\n\n            nn.Conv2d(64,128,3,padding=1),\n            nn.ReLU(),\n            nn.AdaptiveAvgPool2d(1),\n\n            nn.Flatten(),\n            nn.Linear(128,64),\n            nn.ReLU(),\n            nn.Linear(64,1)\n        )\n\n    def forward(self,x):\n        return self.net(x)\n\n# =========================\n# MODEL LOADER\n# =========================\ndef get_model(name):\n\n    if name == \"CNN\":\n        return SimpleCNN()\n\n    elif name == \"ResNet50\":\n        model = models.resnet50(weights=None)\n        model.fc = nn.Linear(model.fc.in_features,1)\n        return model\n\n    elif name == \"VGG16\":\n        model = models.vgg16(weights=None)\n        model.classifier[6] = nn.Linear(4096,1)\n        return model\n\n    elif name == \"VGG19\":\n        model = models.vgg19(weights=None)\n        model.classifier[6] = nn.Linear(4096,1)\n        return model\n\n    elif name == \"Inception_v3\":\n        model = models.inception_v3(weights=None, aux_logits=False)\n        model.fc = nn.Linear(model.fc.in_features,1)\n        return model\n\n    elif name == \"MobileNet\":\n        model = models.mobilenet_v2(weights=None)\n        model.classifier[1] = nn.Linear(model.last_channel,1)\n        return model\n\n    elif name == \"DenseNet169\":\n        model = models.densenet169(weights=None)\n        model.classifier = nn.Linear(model.classifier.in_features,1)\n        return model\n\n    elif name == \"DenseNet121\":\n        model = models.densenet121(weights=None)\n        model.classifier = nn.Linear(model.classifier.in_features,1)\n        return model\n\n    elif name == \"EfficientNet\":\n        model = models.efficientnet_b0(weights=None)\n        model.classifier[1] = nn.Linear(model.classifier[1].in_features,1)\n        return model\n\n    elif name == \"InceptionResNetV2\":\n        print(\"⚠️ Using ResNet50 as fallback\")\n        model = models.resnet50(weights=None)\n        model.fc = nn.Linear(model.fc.in_features,1)\n        return model\n\n# =========================\n# TRAIN\n# =========================\ndef train_model(model, train_loader, val_loader, device, name):\n    model = model.to(device)\n    loss_fn = nn.BCEWithLogitsLoss()\n    optimizer = optim.Adam(model.parameters(), lr=1e-4)\n\n    best_auc = 0\n    best_weights = None\n    auc_history = []\n\n    for epoch in range(3):\n        model.train()\n\n        for x,y in train_loader:\n            x,y = x.to(device), y.to(device)\n\n            optimizer.zero_grad()\n            out = model(x)\n            loss = loss_fn(out,y)\n            loss.backward()\n            optimizer.step()\n\n        model.eval()\n        preds, labels = [], []\n\n        with torch.no_grad():\n            for x,y in val_loader:\n                x = x.to(device)\n                out = torch.sigmoid(model(x)).cpu().numpy()\n                preds.extend(out.flatten())\n                labels.extend(y.numpy().flatten())\n\n        auc = roc_auc_score(labels, preds)\n        auc_history.append(auc)\n        print(f\"Epoch {epoch+1} AUC: {auc:.4f}\")\n\n        if auc > best_auc:\n            best_auc = auc\n            best_weights = model.state_dict()\n\n    if best_weights:\n        model.load_state_dict(best_weights)\n\n    # TRAINING CURVE\n    fig = plt.figure()\n    plt.plot(auc_history, marker='o')\n    plt.title(f\"{name} Training AUC\")\n    plt.xlabel(\"Epoch\")\n    plt.ylabel(\"AUC\")\n    save_and_show(fig, f\"training_curve_{name}.png\")\n\n    return model\n\n# =========================\n# EVALUATE\n# =========================\ndef evaluate(model, loader, device, name):\n    model.eval()\n    preds, labels = [], []\n\n    with torch.no_grad():\n        for x,y in loader:\n            x = x.to(device)\n            out = torch.sigmoid(model(x)).cpu().numpy()\n            preds.extend(out.flatten())\n            labels.extend(y.numpy().flatten())\n\n    preds_bin = (np.array(preds) > 0.5).astype(int)\n\n    # ROC\n    fpr, tpr, _ = roc_curve(labels, preds)\n    fig1 = plt.figure()\n    plt.plot(fpr, tpr)\n    plt.title(f\"ROC - {name}\")\n    save_and_show(fig1, f\"roc_{name}.png\")\n\n    # CONFUSION MATRIX\n    cm = confusion_matrix(labels, preds_bin)\n    fig2 = plt.figure()\n    disp = ConfusionMatrixDisplay(cm)\n    disp.plot()\n    plt.title(name)\n    save_and_show(fig2, f\"conf_matrix_{name}.png\")\n\n    return {\n        \"accuracy\": accuracy_score(labels, preds_bin),\n        \"f1\": f1_score(labels, preds_bin),\n        \"kappa\": cohen_kappa_score(labels, preds_bin),\n        \"auc\": roc_auc_score(labels, preds)\n    }\n\n# =========================\n# MAIN\n# =========================\ntrain_csv = '/kaggle/input/rsna-miccai-brain-tumor-radiogenomic-classification/train_labels.csv'\ntrain_dir = '/kaggle/input/rsna-miccai-brain-tumor-radiogenomic-classification/train'\n\ndf = pd.read_csv(train_csv)\n\ntrain_df, val_df = train_test_split(\n    df, test_size=0.2, stratify=df['MGMT_value'], random_state=42\n)\n\ntrain_dataset = MRIDataset2D(train_df,train_dir)\nval_dataset = MRIDataset2D(val_df,train_dir)\n\ntrain_loader = DataLoader(train_dataset, batch_size=16, shuffle=True)\nval_loader = DataLoader(val_dataset, batch_size=16)\n\ndevice = torch.device('cuda' if torch.cuda.is_available() else 'cpu')\n\n# MRI SAMPLE\nimg, label = train_dataset[0]\nfig = plt.figure()\nplt.imshow(img[0].numpy(), cmap='gray')\nplt.title(f\"Label: {int(label.item())}\")\nplt.axis('off')\nsave_and_show(fig, \"mri_sample.png\")\n\n# =========================\n# TRAIN MODELS\n# =========================\nmodel_names = [\n    \"CNN\",\"ResNet50\",\"VGG16\",\"VGG19\",\"Inception_v3\",\n    \"MobileNet\",\"DenseNet169\",\"DenseNet121\",\"EfficientNet\",\"InceptionResNetV2\"\n]\n\nresults = []\n\nfor name in model_names:\n    print(f\"\\n========== {name} ==========\")\n\n    model = get_model(name)\n    model = train_model(model, train_loader, val_loader, device, name)\n\n    metrics = evaluate(model, val_loader, device, name)\n    metrics[\"model\"] = name\n\n    results.append(metrics)\n\n# =========================\n# FINAL COMPARISON\n# =========================\nresults_df = pd.DataFrame(results)\nresults_df.to_csv(\"model_results.csv\", index=False)\n\nfig = plt.figure()\nplt.bar(results_df['model'], results_df['auc'])\nplt.xticks(rotation=45)\nplt.title(\"Model Comparison (AUC)\")\nsave_and_show(fig, \"model_comparison.png\")\n\nprint(\"\\n✅ DONE! Images displayed + saved in /kaggle/working/\")\nprint(results_df)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-05-05T04:18:10.438241Z","iopub.execute_input":"2026-05-05T04:18:10.439187Z","iopub.status.idle":"2026-05-05T04:22:06.492939Z","shell.execute_reply.started":"2026-05-05T04:18:10.439158Z","shell.execute_reply":"2026-05-05T04:22:06.492254Z"}},"outputs":[],"execution_count":null}]}