{"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":18647,"databundleVersionId":1126921,"sourceType":"competition"},{"sourceId":1101206,"sourceType":"datasetVersion","datasetId":615046}],"dockerImageVersionId":31012,"isInternetEnabled":true,"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","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"!pip install timm --quiet  # Hugely helpful for loading DeiT/Vision Transformers\n\nimport os\nimport pandas as pd\nimport numpy as np\nfrom PIL import Image\nimport torch\nimport torch.nn as nn\nimport torch.optim as optim\nfrom torch.utils.data import Dataset, DataLoader\nfrom torchvision import transforms\nfrom sklearn.model_selection import train_test_split\nfrom sklearn.metrics import accuracy_score, f1_score, cohen_kappa_score, roc_auc_score, confusion_matrix, ConfusionMatrixDisplay\nimport matplotlib.pyplot as plt\n\nimport timm  # for transformer models like DeiT\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-07T12:12:48.978789Z","iopub.execute_input":"2025-05-07T12:12:48.979027Z","iopub.status.idle":"2025-05-07T12:14:50.429053Z","shell.execute_reply.started":"2025-05-07T12:12:48.978987Z","shell.execute_reply":"2025-05-07T12:14:50.428055Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"LABEL_CSV = \"/kaggle/input/prostate-cancer-grade-assessment/train.csv\"\nRESIZED_IMG_DIR = \"/kaggle/input/panda-resized-train-data-512x512/train_images/train_images\"\n\ndf = pd.read_csv(LABEL_CSV)[[\"image_id\", \"isup_grade\"]]\ndf[\"image_path\"] = df[\"image_id\"].apply(lambda x: os.path.join(RESIZED_IMG_DIR, f\"{x}.png\"))\ndf = df[df[\"image_path\"].apply(os.path.exists)].reset_index(drop=True)\n\ntrain_df, val_df = train_test_split(df, test_size=0.2, stratify=df[\"isup_grade\"], random_state=42)\ntrain_df.to_csv(\"/kaggle/working/train.csv\", index=False)\nval_df.to_csv(\"/kaggle/working/val.csv\", index=False)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-07T12:16:16.877057Z","iopub.execute_input":"2025-05-07T12:16:16.877372Z","iopub.status.idle":"2025-05-07T12:16:48.003139Z","shell.execute_reply.started":"2025-05-07T12:16:16.877348Z","shell.execute_reply":"2025-05-07T12:16:48.002151Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"class ProstateDataset(Dataset):\n    def __init__(self, csv_path, transform=None):\n        self.data = pd.read_csv(csv_path)\n        self.transform = transform\n\n    def __len__(self):\n        return len(self.data)\n\n    def __getitem__(self, idx):\n        row = self.data.iloc[idx]\n        image = Image.open(row[\"image_path\"]).convert(\"RGB\")\n        label = int(row[\"isup_grade\"])\n        if self.transform:\n            image = self.transform(image)\n        return image, label\n\ntransform = transforms.Compose([\n    transforms.Resize((224, 224)),\n    transforms.ToTensor(),\n    transforms.Normalize([0.5]*3, [0.5]*3)\n])\n\ntrain_dataset = ProstateDataset(\"/kaggle/working/train.csv\", transform)\nval_dataset = ProstateDataset(\"/kaggle/working/val.csv\", transform)\ntrain_loader = DataLoader(train_dataset, batch_size=8, shuffle=True)\nval_loader = DataLoader(val_dataset, batch_size=8, shuffle=False)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-07T12:17:15.138459Z","iopub.execute_input":"2025-05-07T12:17:15.138823Z","iopub.status.idle":"2025-05-07T12:17:15.182024Z","shell.execute_reply.started":"2025-05-07T12:17:15.138796Z","shell.execute_reply":"2025-05-07T12:17:15.181247Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"class ChatCADTransformer(nn.Module):\n    def __init__(self, num_classes=6):\n        super(ChatCADTransformer, self).__init__()\n        self.backbone = timm.create_model(\"deit_small_patch16_224\", pretrained=True)\n        self.backbone.head = nn.Identity()  # remove original head\n        self.fc = nn.Sequential(\n            nn.Linear(384, 128),\n            nn.ReLU(),\n            nn.Dropout(0.3),\n            nn.Linear(128, num_classes)\n        )\n\n    def forward(self, x):\n        x = self.backbone(x)\n        return self.fc(x)\n\ndevice = torch.device(\"cuda\" if torch.cuda.is_available() else \"cpu\")\nmodel = ChatCADTransformer().to(device)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-07T12:17:43.16705Z","iopub.execute_input":"2025-05-07T12:17:43.170235Z","iopub.status.idle":"2025-05-07T12:17:44.901256Z","shell.execute_reply.started":"2025-05-07T12:17:43.170175Z","shell.execute_reply":"2025-05-07T12:17:44.900264Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"criterion = nn.CrossEntropyLoss()\noptimizer = optim.Adam(model.parameters(), lr=2e-4)\n\ndef train_one_epoch(model, loader):\n    model.train()\n    total_loss = 0\n    for imgs, labels in loader:\n        imgs, labels = imgs.to(device), labels.to(device)\n        out = model(imgs)\n        loss = criterion(out, labels)\n        optimizer.zero_grad()\n        loss.backward()\n        optimizer.step()\n        total_loss += loss.item()\n    print(f\"Training Loss: {total_loss:.2f}\")\n\ndef evaluate(model, loader):\n    model.eval()\n    y_true, y_pred, y_prob = [], [], []\n    with torch.no_grad():\n        for imgs, labels in loader:\n            imgs, labels = imgs.to(device), labels.to(device)\n            out = model(imgs)\n            prob = torch.softmax(out, dim=1)\n            pred = torch.argmax(prob, dim=1)\n            y_true.extend(labels.cpu().numpy())\n            y_pred.extend(pred.cpu().numpy())\n            y_prob.extend(prob.cpu().numpy())\n    acc = accuracy_score(y_true, y_pred)\n    f1 = f1_score(y_true, y_pred, average='weighted')\n    kappa = cohen_kappa_score(y_true, y_pred)\n    roc = roc_auc_score(y_true, y_prob, multi_class='ovr')\n    cm = confusion_matrix(y_true, y_pred)\n    print(f\"Accuracy: {acc:.4f}\")\n    print(f\"F1 Score: {f1:.4f}\")\n    print(f\"Kappa: {kappa:.4f}\")\n    print(f\"ROC AUC: {roc:.4f}\")\n    ConfusionMatrixDisplay(confusion_matrix=cm, display_labels=list(range(6))).plot(cmap='Blues')\n    plt.title(\"Validation Confusion Matrix\")\n    plt.show()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-07T12:18:34.980242Z","iopub.execute_input":"2025-05-07T12:18:34.980581Z","iopub.status.idle":"2025-05-07T12:18:34.992841Z","shell.execute_reply.started":"2025-05-07T12:18:34.980558Z","shell.execute_reply":"2025-05-07T12:18:34.991771Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"for epoch in range(5):\n    print(f\"\\nEpoch {epoch+1}\")\n    train_one_epoch(model, train_loader)\n    evaluate(model, val_loader)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-07T12:19:01.225464Z","iopub.execute_input":"2025-05-07T12:19:01.22583Z","iopub.status.idle":"2025-05-07T15:45:13.419195Z","shell.execute_reply.started":"2025-05-07T12:19:01.2258Z","shell.execute_reply":"2025-05-07T15:45:13.416679Z"}},"outputs":[],"execution_count":null}]}