{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.12.12","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"},"kaggle":{"accelerator":"none","dataSources":[{"sourceType":"competition","sourceId":4117,"databundleVersionId":46665},{"sourceType":"datasetVersion","sourceId":3337316,"datasetId":2015227,"databundleVersionId":3388378}],"dockerImageVersionId":31287,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":false}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"import shutil\n\nshutil.rmtree(\"/kaggle/working/\", ignore_errors=True)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-05-01T13:43:54.998983Z","iopub.execute_input":"2026-05-01T13:43:54.999258Z","iopub.status.idle":"2026-05-01T13:43:55.006634Z","shell.execute_reply.started":"2026-05-01T13:43:54.999229Z","shell.execute_reply":"2026-05-01T13:43:55.005737Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import os\nimport numpy as np\nimport pandas as pd\nfrom PIL import Image\nimport matplotlib.pyplot as plt\nfrom tqdm import tqdm","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true,"execution":{"iopub.status.busy":"2026-05-01T13:44:10.491723Z","iopub.execute_input":"2026-05-01T13:44:10.492485Z","iopub.status.idle":"2026-05-01T13:44:10.791870Z","shell.execute_reply.started":"2026-05-01T13:44:10.492455Z","shell.execute_reply":"2026-05-01T13:44:10.790939Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import torch\nfrom torchvision import datasets, transforms\nfrom torch.utils.data import DataLoader","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-05-01T13:44:31.489923Z","iopub.execute_input":"2026-05-01T13:44:31.490367Z","iopub.status.idle":"2026-05-01T13:44:31.494474Z","shell.execute_reply.started":"2026-05-01T13:44:31.490338Z","shell.execute_reply":"2026-05-01T13:44:31.493737Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"transform = transforms.Compose([\n    transforms.Resize((224, 224)),\n    transforms.Grayscale(num_output_channels=3),  # convert to 3-channel\n    transforms.ToTensor(),\n])","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-05-01T13:44:26.318600Z","iopub.execute_input":"2026-05-01T13:44:26.319177Z","iopub.status.idle":"2026-05-01T13:44:26.323712Z","shell.execute_reply.started":"2026-05-01T13:44:26.319147Z","shell.execute_reply":"2026-05-01T13:44:26.322932Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import os\n\nDATA_PATH = \"/kaggle/input/datasets/manmandes/malimg/malimg_dataset\"\n\nos.listdir(DATA_PATH)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-05-01T13:44:28.623689Z","iopub.execute_input":"2026-05-01T13:44:28.624453Z","iopub.status.idle":"2026-05-01T13:44:28.639509Z","shell.execute_reply.started":"2026-05-01T13:44:28.624419Z","shell.execute_reply":"2026-05-01T13:44:28.638721Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"BASE_PATH = \"/kaggle/input/datasets/manmandes/malimg/malimg_dataset\"\n\ntrain_data = datasets.ImageFolder(os.path.join(BASE_PATH, \"train\"), transform=transform)\nval_data = datasets.ImageFolder(os.path.join(BASE_PATH, \"val\"), transform=transform)\ntest_data = datasets.ImageFolder(os.path.join(BASE_PATH, \"test\"), transform=transform)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-05-01T13:44:34.084310Z","iopub.execute_input":"2026-05-01T13:44:34.085104Z","iopub.status.idle":"2026-05-01T13:44:41.452686Z","shell.execute_reply.started":"2026-05-01T13:44:34.085033Z","shell.execute_reply":"2026-05-01T13:44:41.452112Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"train_loader = DataLoader(train_data, batch_size=32, shuffle=True)\nval_loader = DataLoader(val_data, batch_size=32, shuffle=False)\ntest_loader = DataLoader(test_data, batch_size=32, shuffle=False)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-05-01T13:44:42.746383Z","iopub.execute_input":"2026-05-01T13:44:42.747157Z","iopub.status.idle":"2026-05-01T13:44:42.751420Z","shell.execute_reply.started":"2026-05-01T13:44:42.747127Z","shell.execute_reply":"2026-05-01T13:44:42.750577Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"print(train_data.classes)\nprint(\"Number of classes:\", len(train_data.classes))","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-05-01T13:44:45.049702Z","iopub.execute_input":"2026-05-01T13:44:45.050564Z","iopub.status.idle":"2026-05-01T13:44:45.055244Z","shell.execute_reply.started":"2026-05-01T13:44:45.050534Z","shell.execute_reply":"2026-05-01T13:44:45.054519Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import torch\nimport torch.nn as nn\nimport torch.optim as optim\nfrom torchvision import models","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-05-01T13:44:47.849866Z","iopub.execute_input":"2026-05-01T13:44:47.850536Z","iopub.status.idle":"2026-05-01T13:44:47.854449Z","shell.execute_reply.started":"2026-05-01T13:44:47.850506Z","shell.execute_reply":"2026-05-01T13:44:47.853657Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"device = torch.device(\"cuda\" if torch.cuda.is_available() else \"cpu\")\nprint(device)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-05-01T13:44:53.003842Z","iopub.execute_input":"2026-05-01T13:44:53.004140Z","iopub.status.idle":"2026-05-01T13:44:53.263628Z","shell.execute_reply.started":"2026-05-01T13:44:53.004114Z","shell.execute_reply":"2026-05-01T13:44:53.262870Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"#pretrained resnet\n\nmodel = models.resnet18(pretrained=True)\n\n# Modify final layer\nnum_classes = 25\nmodel.fc = nn.Linear(model.fc.in_features, num_classes)\n\nmodel = model.to(device)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-05-01T13:44:55.360552Z","iopub.execute_input":"2026-05-01T13:44:55.360831Z","iopub.status.idle":"2026-05-01T13:44:56.251761Z","shell.execute_reply.started":"2026-05-01T13:44:55.360809Z","shell.execute_reply":"2026-05-01T13:44:56.251126Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"criterion = nn.CrossEntropyLoss()\noptimizer = optim.Adam(model.parameters(), lr=0.001)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-05-01T13:45:04.689948Z","iopub.execute_input":"2026-05-01T13:45:04.690640Z","iopub.status.idle":"2026-05-01T13:45:04.694894Z","shell.execute_reply.started":"2026-05-01T13:45:04.690608Z","shell.execute_reply":"2026-05-01T13:45:04.694102Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def train_model(model, train_loader, val_loader, epochs=15):\n    for epoch in range(epochs):\n        model.train()\n        total_loss = 0\n        correct = 0\n\n        for images, labels in train_loader:\n            images, labels = images.to(device), labels.to(device)\n\n            optimizer.zero_grad()\n            outputs = model(images)\n            loss = criterion(outputs, labels)\n\n            loss.backward()\n            optimizer.step()\n\n            total_loss += loss.item()\n            _, preds = torch.max(outputs, 1)\n            correct += (preds == labels).sum().item()\n\n        train_acc = correct / len(train_loader.dataset)\n\n        print(f\"Epoch {epoch+1}/{epochs}, Loss: {total_loss:.4f}, Train Acc: {train_acc:.4f}\")\n\n        evaluate(model, val_loader)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-05-01T13:45:06.811776Z","iopub.execute_input":"2026-05-01T13:45:06.812672Z","iopub.status.idle":"2026-05-01T13:45:06.818519Z","shell.execute_reply.started":"2026-05-01T13:45:06.812642Z","shell.execute_reply":"2026-05-01T13:45:06.817694Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def evaluate(model, loader):\n    model.eval()\n    correct = 0\n\n    with torch.no_grad():\n        for images, labels in loader:\n            images, labels = images.to(device), labels.to(device)\n\n            outputs = model(images)\n            _, preds = torch.max(outputs, 1)\n\n            correct += (preds == labels).sum().item()\n\n    acc = correct / len(loader.dataset)\n    print(f\"Test Accuracy: {acc:.4f}\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-05-01T13:45:09.685634Z","iopub.execute_input":"2026-05-01T13:45:09.686468Z","iopub.status.idle":"2026-05-01T13:45:09.691317Z","shell.execute_reply.started":"2026-05-01T13:45:09.686435Z","shell.execute_reply":"2026-05-01T13:45:09.690629Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"train_model(model, train_loader, val_loader)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-05-01T13:45:14.952224Z","iopub.execute_input":"2026-05-01T13:45:14.952840Z","iopub.status.idle":"2026-05-01T14:01:56.605955Z","shell.execute_reply.started":"2026-05-01T13:45:14.952810Z","shell.execute_reply":"2026-05-01T14:01:56.605302Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"#baseline CNN accuracy\n\nevaluate(model, test_loader)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-05-03T11:05:31.670618Z","iopub.execute_input":"2026-05-03T11:05:31.671158Z","iopub.status.idle":"2026-05-03T11:05:31.677651Z","shell.execute_reply.started":"2026-05-03T11:05:31.671128Z","shell.execute_reply":"2026-05-03T11:05:31.676230Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"from sklearn.metrics import classification_report, confusion_matrix\nimport numpy as np\n\ndef get_preds(model, loader):\n    model.eval()\n    y_true, y_pred = [], []\n    with torch.no_grad():\n        for x, y in loader:\n            x = x.to(device)\n            out = model(x)\n            preds = out.argmax(1).cpu().numpy()\n            y_pred.extend(preds)\n            y_true.extend(y.numpy())\n    return np.array(y_true), np.array(y_pred)\n\ny_true, y_pred = get_preds(model, test_loader)\n\nprint(classification_report(y_true, y_pred, target_names=train_data.classes))\n\ncm = confusion_matrix(y_true, y_pred)\nprint(cm)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-05-01T14:02:46.647899Z","iopub.execute_input":"2026-05-01T14:02:46.648688Z","iopub.status.idle":"2026-05-01T14:02:53.080394Z","shell.execute_reply.started":"2026-05-01T14:02:46.648653Z","shell.execute_reply":"2026-05-01T14:02:53.079428Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"#SE Attention Block\nimport torch\nimport torch.nn as nn\n\nclass SEBlock(nn.Module):\n    def __init__(self, channels, reduction=16):\n        super(SEBlock, self).__init__()\n        self.fc1 = nn.Linear(channels, channels // reduction)\n        self.fc2 = nn.Linear(channels // reduction, channels)\n\n    def forward(self, x):\n        b, c, h, w = x.size()\n\n        y = x.view(b, c, -1).mean(dim=2)  # global avg pool\n        y = torch.relu(self.fc1(y))\n        y = torch.sigmoid(self.fc2(y))\n        y = y.view(b, c, 1, 1)\n\n        return x * y","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-05-01T14:03:00.985520Z","iopub.execute_input":"2026-05-01T14:03:00.986093Z","iopub.status.idle":"2026-05-01T14:03:00.991758Z","shell.execute_reply.started":"2026-05-01T14:03:00.986024Z","shell.execute_reply":"2026-05-01T14:03:00.991003Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"#Modify ResNet18\n\nfrom torchvision import models\n\nclass ResNetWithSE(nn.Module):\n    def __init__(self, num_classes):\n        super().__init__()\n\n        self.base = models.resnet18(pretrained=True)\n\n        self.se = SEBlock(512)\n\n        self.base.fc = nn.Linear(512, num_classes)\n\n    def forward(self, x):\n        x = self.base.conv1(x)\n        x = self.base.bn1(x)\n        x = self.base.relu(x)\n        x = self.base.maxpool(x)\n\n        x = self.base.layer1(x)\n        x = self.base.layer2(x)\n        x = self.base.layer3(x)\n        x = self.base.layer4(x)\n\n        x = self.se(x)  # 🔥 ATTENTION HERE\n\n        x = self.base.avgpool(x)\n        x = torch.flatten(x, 1)\n        x = self.base.fc(x)\n\n        return x","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-05-01T14:03:04.393603Z","iopub.execute_input":"2026-05-01T14:03:04.394553Z","iopub.status.idle":"2026-05-01T14:03:04.400634Z","shell.execute_reply.started":"2026-05-01T14:03:04.394514Z","shell.execute_reply":"2026-05-01T14:03:04.399741Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"#intialise new model \nmodel_att = ResNetWithSE(num_classes=25).to(device)\n\ncriterion = nn.CrossEntropyLoss()\noptimizer = torch.optim.Adam(model_att.parameters(), lr=0.0003, weight_decay=1e-4)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-05-01T14:03:08.310527Z","iopub.execute_input":"2026-05-01T14:03:08.311298Z","iopub.status.idle":"2026-05-01T14:03:08.511121Z","shell.execute_reply.started":"2026-05-01T14:03:08.311267Z","shell.execute_reply":"2026-05-01T14:03:08.510055Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def train_model(model, train_loader, val_loader, epochs=15):\n    train_acc_list = []\n    val_acc_list = []\n    train_loss_list = []\n\n    for epoch in range(epochs):\n        model.train()\n        total_loss = 0\n        correct = 0\n\n        for images, labels in train_loader:\n            images, labels = images.to(device), labels.to(device)\n\n            optimizer.zero_grad()\n            outputs = model(images)\n            loss = criterion(outputs, labels)\n\n            loss.backward()\n            optimizer.step()\n\n            total_loss += loss.item()\n            _, preds = torch.max(outputs, 1)\n            correct += (preds == labels).sum().item()\n\n        # ✅ Fix here\n        avg_loss = total_loss / len(train_loader)\n\n        train_acc = correct / len(train_loader.dataset)\n        val_acc = evaluate_return(model, val_loader)\n\n        train_acc_list.append(train_acc)\n        val_acc_list.append(val_acc)\n        train_loss_list.append(avg_loss)\n\n        print(f\"Epoch {epoch+1}: Train Acc={train_acc:.4f}, Val Acc={val_acc:.4f}, Loss={avg_loss:.4f}\")\n\n    return train_acc_list, val_acc_list, train_loss_list","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-05-01T14:04:32.624570Z","iopub.execute_input":"2026-05-01T14:04:32.625284Z","iopub.status.idle":"2026-05-01T14:04:32.632138Z","shell.execute_reply.started":"2026-05-01T14:04:32.625255Z","shell.execute_reply":"2026-05-01T14:04:32.631307Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def evaluate_return(model, loader):\n    model.eval()\n    correct = 0\n\n    with torch.no_grad():\n        for images, labels in loader:\n            images, labels = images.to(device), labels.to(device)\n\n            outputs = model(images)\n            _, preds = torch.max(outputs, 1)\n            correct += (preds == labels).sum().item()\n\n    return correct / len(loader.dataset)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-05-01T14:04:29.316965Z","iopub.execute_input":"2026-05-01T14:04:29.317766Z","iopub.status.idle":"2026-05-01T14:04:29.322784Z","shell.execute_reply.started":"2026-05-01T14:04:29.317732Z","shell.execute_reply":"2026-05-01T14:04:29.321972Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"train_acc, val_acc, train_loss = train_model(model_att, train_loader, val_loader)\n\nplt.figure()\nplt.plot(train_acc, label='Train Accuracy')\nplt.plot(val_acc, label='Validation Accuracy')\nplt.xlabel('Epochs')\nplt.ylabel('Accuracy')\nplt.legend()\nplt.title('Training vs Validation Accuracy')\nplt.show()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-05-01T14:04:36.074361Z","iopub.execute_input":"2026-05-01T14:04:36.075037Z","iopub.status.idle":"2026-05-01T14:20:32.394782Z","shell.execute_reply.started":"2026-05-01T14:04:36.075005Z","shell.execute_reply":"2026-05-01T14:20:32.394098Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"#attention cnn accuracy \nprint(f\"Test Accuracy: {evaluate_return(model_att, test_loader):.4f}\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-05-01T12:17:56.507802Z","iopub.execute_input":"2026-05-01T12:17:56.508061Z","iopub.status.idle":"2026-05-01T12:18:03.118343Z","shell.execute_reply.started":"2026-05-01T12:17:56.508041Z","shell.execute_reply":"2026-05-01T12:18:03.117444Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"plt.figure()\nplt.plot(train_loss, label='Training Loss')\nplt.xlabel('Epochs')\nplt.ylabel('Loss')\nplt.legend()\nplt.title('Training Loss Curve')\nplt.show()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-05-01T14:22:20.959327Z","iopub.execute_input":"2026-05-01T14:22:20.959930Z","iopub.status.idle":"2026-05-01T14:22:21.089825Z","shell.execute_reply.started":"2026-05-01T14:22:20.959903Z","shell.execute_reply":"2026-05-01T14:22:21.089117Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"from sklearn.metrics import classification_report, confusion_matrix\nimport numpy as np\n\ndef get_preds(model, loader):\n    model.eval()\n    y_true, y_pred = [], []\n    with torch.no_grad():\n        for x, y in loader:\n            x = x.to(device)\n            out = model(x)\n            preds = out.argmax(1).cpu().numpy()\n            y_pred.extend(preds)\n            y_true.extend(y.numpy())\n    return np.array(y_true), np.array(y_pred)\n\ny_true, y_pred = get_preds(model_att, test_loader)\n\nprint(classification_report(y_true, y_pred, target_names=train_data.classes))\n\ncm = confusion_matrix(y_true, y_pred)\nprint(cm)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-05-01T14:22:28.206931Z","iopub.execute_input":"2026-05-01T14:22:28.207230Z","iopub.status.idle":"2026-05-01T14:22:34.228576Z","shell.execute_reply.started":"2026-05-01T14:22:28.207205Z","shell.execute_reply":"2026-05-01T14:22:34.227840Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import seaborn as sns\nfrom sklearn.metrics import confusion_matrix\n\ncm = confusion_matrix(y_true, y_pred)\n\nplt.figure(figsize=(12,10))\nsns.heatmap(cm, cmap=\"Blues\")\nplt.title(\"Confusion Matrix\")\nplt.xlabel(\"Predicted\")\nplt.ylabel(\"Actual\")\nplt.show()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-05-01T10:59:18.731930Z","iopub.execute_input":"2026-05-01T10:59:18.732382Z","iopub.status.idle":"2026-05-01T10:59:19.465890Z","shell.execute_reply.started":"2026-05-01T10:59:18.732351Z","shell.execute_reply":"2026-05-01T10:59:19.465235Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"sns.heatmap(cm, xticklabels=train_data.classes, yticklabels=train_data.classes)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-05-01T10:59:23.943193Z","iopub.execute_input":"2026-05-01T10:59:23.943975Z","iopub.status.idle":"2026-05-01T10:59:24.350932Z","shell.execute_reply.started":"2026-05-01T10:59:23.943945Z","shell.execute_reply":"2026-05-01T10:59:24.350240Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"models = ['Baseline CNN', 'CNN + Attention']\naccuracy = [0.9655, 0.9937]\n\nplt.figure()\nplt.bar(models, accuracy)\nplt.ylabel('Accuracy')\nplt.title('Model Comparison')\nplt.show()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-05-01T10:59:32.575338Z","iopub.execute_input":"2026-05-01T10:59:32.575743Z","iopub.status.idle":"2026-05-01T10:59:32.666116Z","shell.execute_reply.started":"2026-05-01T10:59:32.575715Z","shell.execute_reply":"2026-05-01T10:59:32.665324Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"#grad-came {Explainable-AI}\n\n!pip install grad-cam","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-05-01T10:59:38.361958Z","iopub.execute_input":"2026-05-01T10:59:38.362650Z","iopub.status.idle":"2026-05-01T10:59:49.235641Z","shell.execute_reply.started":"2026-05-01T10:59:38.362616Z","shell.execute_reply":"2026-05-01T10:59:49.234677Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"from pytorch_grad_cam import GradCAM\nfrom pytorch_grad_cam.utils.image import show_cam_on_image\nimport cv2\nimport numpy as np","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-04-28T17:10:53.251532Z","iopub.execute_input":"2026-04-28T17:10:53.252030Z","iopub.status.idle":"2026-04-28T17:10:54.094719Z","shell.execute_reply.started":"2026-04-28T17:10:53.251998Z","shell.execute_reply":"2026-04-28T17:10:54.094128Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"target_layer = model_att.base.layer4[-1]","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-04-27T18:05:40.607869Z","iopub.execute_input":"2026-04-27T18:05:40.608395Z","iopub.status.idle":"2026-04-27T18:05:40.612525Z","shell.execute_reply.started":"2026-04-27T18:05:40.608366Z","shell.execute_reply":"2026-04-27T18:05:40.611676Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"cam = GradCAM(model=model_att, target_layers=[target_layer])","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-04-27T18:05:56.100599Z","iopub.execute_input":"2026-04-27T18:05:56.101233Z","iopub.status.idle":"2026-04-27T18:05:56.105412Z","shell.execute_reply.started":"2026-04-27T18:05:56.101195Z","shell.execute_reply":"2026-04-27T18:05:56.104676Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"dataset = test_data\nimg, label = dataset[0]\n\ninput_tensor = img.unsqueeze(0).to(device)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-04-27T18:06:07.354793Z","iopub.execute_input":"2026-04-27T18:06:07.355228Z","iopub.status.idle":"2026-04-27T18:06:07.366873Z","shell.execute_reply.started":"2026-04-27T18:06:07.355199Z","shell.execute_reply":"2026-04-27T18:06:07.366115Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"grayscale_cam = cam(input_tensor=input_tensor)[0]","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-04-27T18:06:14.726227Z","iopub.execute_input":"2026-04-27T18:06:14.726491Z","iopub.status.idle":"2026-04-27T18:06:14.891807Z","shell.execute_reply.started":"2026-04-27T18:06:14.726469Z","shell.execute_reply":"2026-04-27T18:06:14.891217Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"img_np = img.permute(1, 2, 0).cpu().numpy()\nimg_np = img_np / img_np.max()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-04-27T18:06:27.961896Z","iopub.execute_input":"2026-04-27T18:06:27.962415Z","iopub.status.idle":"2026-04-27T18:06:27.966907Z","shell.execute_reply.started":"2026-04-27T18:06:27.962385Z","shell.execute_reply":"2026-04-27T18:06:27.966045Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"visualization = show_cam_on_image(img_np, grayscale_cam, use_rgb=True)\n\nimport matplotlib.pyplot as plt\n\nplt.imshow(visualization)\nplt.title(f\"True: {train_data.classes[label]}\")\nplt.axis('off')\nplt.show()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-04-27T18:06:41.609285Z","iopub.execute_input":"2026-04-27T18:06:41.609926Z","iopub.status.idle":"2026-04-27T18:06:41.768466Z","shell.execute_reply.started":"2026-04-27T18:06:41.609898Z","shell.execute_reply":"2026-04-27T18:06:41.767605Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"Comparision of plain cnn vs att cnn","metadata":{}},{"cell_type":"code","source":"model.eval()\nmodel_att.eval()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-04-28T17:11:05.868702Z","iopub.execute_input":"2026-04-28T17:11:05.869369Z","iopub.status.idle":"2026-04-28T17:11:05.876559Z","shell.execute_reply.started":"2026-04-28T17:11:05.869335Z","shell.execute_reply":"2026-04-28T17:11:05.875733Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"target_layer_base = model.layer4[-1]          # baseline\ntarget_layer_att = model_att.base.layer4[-1] # attention","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-04-28T17:11:25.485744Z","iopub.execute_input":"2026-04-28T17:11:25.486341Z","iopub.status.idle":"2026-04-28T17:11:25.490323Z","shell.execute_reply.started":"2026-04-28T17:11:25.486268Z","shell.execute_reply":"2026-04-28T17:11:25.489360Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"cam_base = GradCAM(model=model, target_layers=[target_layer_base])\ncam_att = GradCAM(model=model_att, target_layers=[target_layer_att])","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-04-28T17:11:55.176430Z","iopub.execute_input":"2026-04-28T17:11:55.176707Z","iopub.status.idle":"2026-04-28T17:11:55.189613Z","shell.execute_reply.started":"2026-04-28T17:11:55.176687Z","shell.execute_reply":"2026-04-28T17:11:55.188772Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"img, label = test_data[10]   # change index for different cases\ninput_tensor = img.unsqueeze(0).to(device)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-04-28T17:12:15.586508Z","iopub.execute_input":"2026-04-28T17:12:15.586891Z","iopub.status.idle":"2026-04-28T17:12:15.597110Z","shell.execute_reply.started":"2026-04-28T17:12:15.586859Z","shell.execute_reply":"2026-04-28T17:12:15.596479Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"cam_base_out = cam_base(input_tensor=input_tensor)[0]\ncam_att_out = cam_att(input_tensor=input_tensor)[0]","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-04-28T17:12:28.056912Z","iopub.execute_input":"2026-04-28T17:12:28.057379Z","iopub.status.idle":"2026-04-28T17:12:28.086719Z","shell.execute_reply.started":"2026-04-28T17:12:28.057350Z","shell.execute_reply":"2026-04-28T17:12:28.086068Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"img_np = img.permute(1, 2, 0).cpu().numpy()\nimg_np = img_np / img_np.max()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-04-28T17:12:40.794707Z","iopub.execute_input":"2026-04-28T17:12:40.795218Z","iopub.status.idle":"2026-04-28T17:12:40.799534Z","shell.execute_reply.started":"2026-04-28T17:12:40.795192Z","shell.execute_reply":"2026-04-28T17:12:40.798832Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"vis_base = show_cam_on_image(img_np, cam_base_out, use_rgb=True)\nvis_att = show_cam_on_image(img_np, cam_att_out, use_rgb=True)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-04-28T17:12:48.638974Z","iopub.execute_input":"2026-04-28T17:12:48.639321Z","iopub.status.idle":"2026-04-28T17:12:48.672072Z","shell.execute_reply.started":"2026-04-28T17:12:48.639295Z","shell.execute_reply":"2026-04-28T17:12:48.671210Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"plt.figure(figsize=(12,4))\n\nplt.subplot(1,3,1)\nplt.imshow(img_np)\nplt.title(\"Original\")\nplt.axis('off')\n\nplt.subplot(1,3,2)\nplt.imshow(vis_base)\nplt.title(\"Baseline CNN\")\nplt.axis('off')\n\nplt.subplot(1,3,3)\nplt.imshow(vis_att)\nplt.title(\"Attention CNN\")\nplt.axis('off')\n\nplt.show()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-04-28T17:12:57.220382Z","iopub.execute_input":"2026-04-28T17:12:57.221005Z","iopub.status.idle":"2026-04-28T17:12:57.486184Z","shell.execute_reply.started":"2026-04-28T17:12:57.220973Z","shell.execute_reply":"2026-04-28T17:12:57.485305Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import matplotlib.pyplot as plt\n\ndef show_comparison(idx):\n    img, label = test_data[idx]\n    input_tensor = img.unsqueeze(0).to(device)\n\n    cam_base_out = cam_base(input_tensor=input_tensor)[0]\n    cam_att_out = cam_att(input_tensor=input_tensor)[0]\n\n    img_np = img.permute(1,2,0).cpu().numpy()\n    img_np = img_np / img_np.max()\n\n    vis_base = show_cam_on_image(img_np, cam_base_out, use_rgb=True)\n    vis_att = show_cam_on_image(img_np, cam_att_out, use_rgb=True)\n\n    plt.figure(figsize=(10,3))\n\n    plt.subplot(1,3,1)\n    plt.imshow(img_np)\n    plt.title(\"Original\")\n    plt.axis('off')\n\n    plt.subplot(1,3,2)\n    plt.imshow(vis_base)\n    plt.title(\"Baseline\")\n    plt.axis('off')\n\n    plt.subplot(1,3,3)\n    plt.imshow(vis_att)\n    plt.title(\"Attention\")\n    plt.axis('off')\n\n    plt.show()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-04-28T17:16:15.076362Z","iopub.execute_input":"2026-04-28T17:16:15.077295Z","iopub.status.idle":"2026-04-28T17:16:15.083780Z","shell.execute_reply.started":"2026-04-28T17:16:15.077226Z","shell.execute_reply":"2026-04-28T17:16:15.082851Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"for i in range(10, 30):\n    show_comparison(i)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-04-28T17:16:24.323222Z","iopub.execute_input":"2026-04-28T17:16:24.323962Z","iopub.status.idle":"2026-04-28T17:16:28.996718Z","shell.execute_reply.started":"2026-04-28T17:16:24.323932Z","shell.execute_reply":"2026-04-28T17:16:28.995841Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def find_class_index(class_name):\n    for i in range(len(test_data)):\n        _, label = test_data[i]\n        if train_data.classes[label] == class_name:\n            return i\n    return None\n\nidx_autorun = find_class_index(\"Autorun.K\")\nprint(\"Autorun.K index:\", idx_autorun)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-04-28T17:19:45.806905Z","iopub.execute_input":"2026-04-28T17:19:45.807619Z","iopub.status.idle":"2026-04-28T17:19:47.860733Z","shell.execute_reply.started":"2026-04-28T17:19:45.807588Z","shell.execute_reply":"2026-04-28T17:19:47.860018Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"idx_swizzor = find_class_index(\"Swizzor.gen!E\")  # or \"Swizzor.gen!I\"\nprint(\"Swizzor index:\", idx_swizzor)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-04-28T17:20:05.559019Z","iopub.execute_input":"2026-04-28T17:20:05.559364Z","iopub.status.idle":"2026-04-28T17:20:08.735712Z","shell.execute_reply.started":"2026-04-28T17:20:05.559337Z","shell.execute_reply":"2026-04-28T17:20:08.734993Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def show_gradcam_comparison(idx):\n    img, label = test_data[idx]\n    input_tensor = img.unsqueeze(0).to(device)\n\n    # CAMs\n    cam_base_out = cam_base(input_tensor=input_tensor)[0]\n    cam_att_out = cam_att(input_tensor=input_tensor)[0]\n\n    # Image prep\n    img_np = img.permute(1,2,0).cpu().numpy()\n    img_np = img_np / img_np.max()\n\n    vis_base = show_cam_on_image(img_np, cam_base_out, use_rgb=True)\n    vis_att = show_cam_on_image(img_np, cam_att_out, use_rgb=True)\n\n    class_name = train_data.classes[label]\n\n    import matplotlib.pyplot as plt\n    plt.figure(figsize=(12,4))\n\n    plt.subplot(1,3,1)\n    plt.imshow(img_np)\n    plt.title(f\"Original\\n{class_name}\")\n    plt.axis('off')\n\n    plt.subplot(1,3,2)\n    plt.imshow(vis_base)\n    plt.title(\"Baseline CNN\")\n    plt.axis('off')\n\n    plt.subplot(1,3,3)\n    plt.imshow(vis_att)\n    plt.title(\"Attention CNN\")\n    plt.axis('off')\n\n    plt.show()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-04-28T17:20:21.708181Z","iopub.execute_input":"2026-04-28T17:20:21.708840Z","iopub.status.idle":"2026-04-28T17:20:21.715082Z","shell.execute_reply.started":"2026-04-28T17:20:21.708810Z","shell.execute_reply":"2026-04-28T17:20:21.714346Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"show_gradcam_comparison(idx_autorun)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-04-28T17:20:30.234025Z","iopub.execute_input":"2026-04-28T17:20:30.234351Z","iopub.status.idle":"2026-04-28T17:20:30.546467Z","shell.execute_reply.started":"2026-04-28T17:20:30.234325Z","shell.execute_reply":"2026-04-28T17:20:30.545481Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"show_gradcam_comparison(idx_swizzor)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-04-28T17:20:50.068050Z","iopub.execute_input":"2026-04-28T17:20:50.068359Z","iopub.status.idle":"2026-04-28T17:20:50.388537Z","shell.execute_reply.started":"2026-04-28T17:20:50.068335Z","shell.execute_reply":"2026-04-28T17:20:50.387660Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"","metadata":{"trusted":true},"outputs":[],"execution_count":null}]}