{"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":"gpu","dataSources":[{"sourceType":"competition","sourceId":3649,"databundleVersionId":46718},{"sourceType":"kernelVersion","sourceId":140376581}],"dockerImageVersionId":31286,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":true}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"markdown","source":"<h1 style=\"background-color:#E8EDFF;color:#0321B8;\npadding:12px;border-radius:8px;text-align:center;\nbox-shadow:0px 2px 6px rgba(0,0,0,0.1);margin:10px;\">\nComparison of Various Optimization Techniques on CIFAR-10 Dataset\n</h1>","metadata":{"execution":{"iopub.status.busy":"2026-03-12T13:51:48.901342Z","iopub.execute_input":"2026-03-12T13:51:48.902120Z","iopub.status.idle":"2026-03-12T13:51:48.907359Z","shell.execute_reply.started":"2026-03-12T13:51:48.902083Z","shell.execute_reply":"2026-03-12T13:51:48.906533Z"}}},{"cell_type":"markdown","source":"<h4 style=\"background-color:#F7F9FF;color:#0321B8;\npadding:6px;border-left:5px solid #0321B8;\">\nProject Abstract\n</h4>\n\n<div style=\"background-color:#F7F9FF;border-left:6px solid #0321B8;\npadding:10px;border-radius:6px;\">\n\n<p style=\"color:#333333;font-size:14px;\">\nThis project presents a comprehensive study on training Convolutional Neural Networks (CNNs) for image classification using the <b>CIFAR-10 dataset</b>. \nThe objective is to evaluate and compare the performance of various optimization algorithms, including <b>SGD, SGD with Momentum, Nesterov Accelerated Gradient (NAG), Adam, AdamW, Adagrad, and RMSprop</b>. \n\nA consistent CNN architecture is employed across all experiments to ensure fair comparison. Each optimizer is analyzed based on <b>convergence speed, training stability, and validation accuracy</b>. \nExperimental results demonstrate that <b>momentum-based optimizers</b>, particularly <b>SGD with NAG</b>, achieve superior performance with faster convergence and higher accuracy. \nAdaptive optimizers such as <b>Adam and AdamW</b> provide rapid initial learning and competitive results, while <b>Adagrad</b> shows strong early progress but plateaus due to aggressive learning rate decay. \n<b>RMSprop</b> exhibits unstable behavior under the chosen hyperparameters.\n\nThis study highlights the critical role of optimizer selection in deep learning, showing that <b>momentum-based methods offer the best balance between efficiency, stability, and generalization performance</b> for image classification tasks.\n</p>\n\n</div>","metadata":{"execution":{"iopub.status.busy":"2026-03-22T08:00:30.865572Z","iopub.execute_input":"2026-03-22T08:00:30.866397Z","iopub.status.idle":"2026-03-22T08:00:30.876657Z","shell.execute_reply.started":"2026-03-22T08:00:30.866363Z","shell.execute_reply":"2026-03-22T08:00:30.875832Z"}}},{"cell_type":"markdown","source":"<h2 style=\"background-color:#F1F4FF;color:#4F6BD8;\npadding:6px;border-radius:6px;text-align:center;\">\nImporting Libraries\n</h2>","metadata":{"execution":{"iopub.status.busy":"2026-03-12T13:36:40.915675Z","iopub.execute_input":"2026-03-12T13:36:40.916061Z","iopub.status.idle":"2026-03-12T13:36:40.925231Z","shell.execute_reply.started":"2026-03-12T13:36:40.916031Z","shell.execute_reply":"2026-03-12T13:36:40.924261Z"}}},{"cell_type":"code","source":"import numpy as np\nimport pandas as pd\nimport torch\nimport torch.nn as nn\nimport torch.optim as optim\nimport torchvision\nimport torchvision.transforms as transforms\nfrom torch.utils.data import random_split\nimport torch.nn.functional as F\nimport matplotlib.pyplot as plt\nimport seaborn as sns\nimport random\n\nfrom sklearn.metrics import (\n    accuracy_score,\n    precision_score,\n    recall_score,\n    f1_score,\n    confusion_matrix,\n    roc_auc_score,\n    classification_report\n)\nfrom sklearn.preprocessing import label_binarize\n\nimport warnings\nwarnings.filterwarnings(\"ignore\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-03-22T04:59:20.482407Z","iopub.execute_input":"2026-03-22T04:59:20.482670Z","iopub.status.idle":"2026-03-22T04:59:29.712532Z","shell.execute_reply.started":"2026-03-22T04:59:20.482614Z","shell.execute_reply":"2026-03-22T04:59:29.711902Z"},"_kg_hide-output":false},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"<h2 style=\"background-color:#F1F4FF;color:#4F6BD8;\npadding:6px;border-radius:6px;text-align:center;\">\nChecking for GPU\n</h2>","metadata":{}},{"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-03-22T04:59:29.714209Z","iopub.execute_input":"2026-03-22T04:59:29.714592Z","iopub.status.idle":"2026-03-22T04:59:29.770264Z","shell.execute_reply.started":"2026-03-22T04:59:29.714559Z","shell.execute_reply":"2026-03-22T04:59:29.769548Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"<h2 style=\"background-color:#F1F4FF;color:#4F6BD8;\npadding:6px;border-radius:6px;text-align:center;\">\nSetting Random Seed Generator\n</h2>","metadata":{}},{"cell_type":"markdown","source":"<div style=\"background-color:#F7F9FF;border-left:6px solid #0321B8;\npadding:10px;border-radius:6px;\">\n\n<b style=\"color:#0321B8;\">Random Seed Generator</b>\n\n<p style=\"color:#333333;font-size:14px;\">\nA random seed generator is used to control randomness in machine learning experiments. \nIn deep learning, processes such as <b>weight initialization, data shuffling, and dropout</b> depend on random numbers, which can lead to different results each time the model is trained. \nBy fixing a random seed, we ensure that the same sequence of random numbers is generated every run, making the experiment <b>reproducible</b>. \nThis is particularly important in this study because it guarantees a <b>fair comparison between different optimization algorithms</b>, ensuring that all models start from identical initial conditions.\n</p>\n\n</div>","metadata":{"execution":{"iopub.status.busy":"2026-03-12T13:56:29.141195Z","iopub.execute_input":"2026-03-12T13:56:29.141507Z","iopub.status.idle":"2026-03-12T13:56:29.147593Z","shell.execute_reply.started":"2026-03-12T13:56:29.141484Z","shell.execute_reply":"2026-03-12T13:56:29.146653Z"}}},{"cell_type":"code","source":"seed = 42\n\ntorch.manual_seed(seed)\ntorch.cuda.manual_seed(seed)\ntorch.cuda.manual_seed_all(seed)\n\nnp.random.seed(seed)\nrandom.seed(seed)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-03-22T04:59:29.771055Z","iopub.execute_input":"2026-03-22T04:59:29.771261Z","iopub.status.idle":"2026-03-22T04:59:29.799574Z","shell.execute_reply.started":"2026-03-22T04:59:29.771244Z","shell.execute_reply":"2026-03-22T04:59:29.798776Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"<h2 style=\"background-color:#F1F4FF;color:#4F6BD8;\npadding:6px;border-radius:6px;text-align:center;\">\nDataset Loading and Data Augmentation\n</h2>","metadata":{}},{"cell_type":"markdown","source":"<div style=\"background-color:#F7F9FF;border-left:6px solid #0321B8;\npadding:10px;border-radius:6px;\">\n\n<p style=\"color:#333333;font-size:14px;\">\nIn this step, the CIFAR-10 dataset is loaded using <b>torchvision</b>. \nData augmentation techniques such as <b>random horizontal flipping</b> and <b>random cropping</b> are applied to improve the model’s ability to generalize by exposing it to slightly varied versions of the same images. \nThe images are then converted to tensors and normalized using the CIFAR-10 dataset statistics to stabilize training. \nFinally, the dataset is split into <b>training (80%)</b> and <b>validation (20%)</b> sets, and PyTorch <b>DataLoader</b> is used to efficiently load batches of data during training.\n</p>\n\n</div>","metadata":{"execution":{"iopub.status.busy":"2026-03-12T14:01:42.451951Z","iopub.execute_input":"2026-03-12T14:01:42.452507Z","iopub.status.idle":"2026-03-12T14:01:42.459114Z","shell.execute_reply.started":"2026-03-12T14:01:42.452477Z","shell.execute_reply":"2026-03-12T14:01:42.458164Z"}}},{"cell_type":"code","source":"trainset = torchvision.datasets.CIFAR10(root='/kaggle/working/data', \n                                        train=True, \n                                        download=True,\n                                        transform = transforms.Compose([transforms.RandomHorizontalFlip(),\n                                                                      transforms.RandomCrop(32, padding=4),\n                                                                      transforms.ToTensor(),\n                                                                      transforms.Normalize((0.4914,0.4822,0.4465),(0.2470,0.2435,0.2616))]\n                                                                    ))\ntrain_size = int(0.8 * len(trainset))\nval_size = len(trainset) - train_size\n\ntrain_dataset, val_dataset = random_split(trainset, [train_size, val_size])\n\ng = torch.Generator()\ng.manual_seed(seed)\n\ntrainloader = torch.utils.data.DataLoader(train_dataset, batch_size=256, shuffle=True, num_workers = 4, generator=g,pin_memory=True)\n\nvalloader = torch.utils.data.DataLoader(val_dataset, batch_size=256, shuffle=False, num_workers = 4,generator = g, pin_memory=True)\n\nmean = torch.tensor([0.4914,0.4822,0.4465])\nstd = torch.tensor([0.2470,0.2435,0.2616])\n\nimage, label = trainset[0]\n\nimage = image * std[:, None, None] + mean[:, None, None]\n\nplt.imshow(image.permute(1,2,0))\nplt.title(trainset.classes[label])\nplt.axis(\"off\")\nplt.show()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-03-22T04:59:29.800679Z","iopub.execute_input":"2026-03-22T04:59:29.800979Z","iopub.status.idle":"2026-03-22T04:59:34.175683Z","shell.execute_reply.started":"2026-03-22T04:59:29.800944Z","shell.execute_reply":"2026-03-22T04:59:34.174933Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"<h2 style=\"background-color:#F1F4FF;color:#4F6BD8;\npadding:6px;border-radius:6px;text-align:center;\">\nModel Architecture and Training Configuration\n</h2>","metadata":{"execution":{"iopub.status.busy":"2026-03-12T14:02:42.491682Z","iopub.execute_input":"2026-03-12T14:02:42.492018Z","iopub.status.idle":"2026-03-12T14:02:42.497413Z","shell.execute_reply.started":"2026-03-12T14:02:42.491992Z","shell.execute_reply":"2026-03-12T14:02:42.496502Z"}}},{"cell_type":"markdown","source":"<h4 style=\"background-color:#F7F9FF;color:#0321B8;\npadding:6px;border-left:5px solid #0321B8;\">\nConvolutional Neural Network Architecture\n</h4>\n<div style=\"background-color:#F7F9FF;border-left:6px solid #0321B8;\npadding:10px;border-radius:6px;\">\n\n\n<p style=\"color:#333333;font-size:14px;\">\nA Convolutional Neural Network (CNN) is designed to extract hierarchical features from images. \nIn this architecture, multiple <b>convolutional layers</b> are used to learn spatial patterns such as edges, textures, and shapes from the CIFAR-10 images. \nEach convolution layer is followed by <b>Batch Normalization</b> to stabilize and accelerate training, and <b>ReLU activation</b> to introduce non-linearity. \n<b>Max Pooling</b> layers reduce spatial dimensions and help the network focus on the most important features. \nTo reduce overfitting, <b>Dropout layers</b> are applied before the fully connected layers. \nFinally, the extracted features are passed through fully connected layers to produce predictions for the <b>10 CIFAR-10 classes</b>.\n</p>\n\n</div>","metadata":{"execution":{"iopub.status.busy":"2026-03-12T14:02:54.569139Z","iopub.execute_input":"2026-03-12T14:02:54.569870Z","iopub.status.idle":"2026-03-12T14:02:54.575313Z","shell.execute_reply.started":"2026-03-12T14:02:54.569830Z","shell.execute_reply":"2026-03-12T14:02:54.574465Z"}}},{"cell_type":"markdown","source":"<h4 style=\"color:#0321B8;text-align:center;margin-bottom:6px;\">\nTable: Trainable Parameter Calculations\n</h4>\n\n<div style=\"background-color:#F7F9FF;border-left:6px solid #0321B8;\npadding:12px;border-radius:6px;\">\n\n<table style=\"width:100%;border-collapse:collapse;font-size:14px;text-align:center;\">\n<tr style=\"background-color:#EAF0FF;\">\n<th style=\"padding:8px;border:1px solid #ccc;\">Layer</th>\n<th style=\"padding:8px;border:1px solid #ccc;\">Operation</th>\n<th style=\"padding:8px;border:1px solid #ccc;\">Output Shape</th>\n<th style=\"padding:8px;border:1px solid #ccc;\">Trainable Parameters</th>\n</tr>\n\n<tr>\n<td>Conv Block 1</td>\n<td>Conv2D (3 → 32, 3×3) + BatchNorm + ReLU</td>\n<td>32 × 32 × 32</td>\n<td>960</td>\n</tr>\n\n<tr>\n<td>Conv Block 2</td>\n<td>Conv2D (32 → 64, 3×3) + BatchNorm + ReLU + MaxPool</td>\n<td>64 × 16 × 16</td>\n<td>18624</td>\n</tr>\n\n<tr>\n<td>Conv Block 3</td>\n<td>Conv2D (64 → 128, 3×3) + BatchNorm + ReLU</td>\n<td>128 × 16 × 16</td>\n<td>74112</td>\n</tr>\n\n<tr>\n<td>Conv Block 4</td>\n<td>Conv2D (128 → 256, 3×3) + BatchNorm + ReLU + MaxPool</td>\n<td>256 × 8 × 8</td>\n<td>295680</td>\n</tr>\n\n<tr>\n<td>Flatten</td>\n<td>Feature Flattening</td>\n<td>16384</td>\n<td>0</td>\n</tr>\n\n<tr>\n<td>FC Layer 1</td>\n<td>Linear (16384 → 512) + Dropout</td>\n<td>512</td>\n<td>8,389,120</td>\n</tr>\n\n<tr>\n<td>FC Layer 2</td>\n<td>Linear (512 → 128) + Dropout</td>\n<td>128</td>\n<td>65,664</td>\n</tr>\n\n<tr>\n<td>Output Layer</td>\n<td>Linear (128 → 10)</td>\n<td>10</td>\n<td>1,290</td>\n</tr>\n\n</table>\n\n</div>","metadata":{}},{"cell_type":"code","source":"class Net(nn.Module):\n\n    def __init__(self):\n        super(Net, self).__init__()\n\n        self.conv1 = nn.Conv2d(3, 32, 3, padding=1)\n        self.bn1 = nn.BatchNorm2d(32)\n\n        self.conv2 = nn.Conv2d(32, 64, 3, padding=1)\n        self.bn2 = nn.BatchNorm2d(64)\n\n        self.conv3 = nn.Conv2d(64, 128, 3, padding=1)\n        self.bn3 = nn.BatchNorm2d(128)\n\n        self.conv4 = nn.Conv2d(128, 256, 3, padding=1)\n        self.bn4 = nn.BatchNorm2d(256)\n\n        self.pool = nn.MaxPool2d(2,2)\n\n        # Dropout layers\n        self.dropout1 = nn.Dropout(0.3)\n        self.dropout2 = nn.Dropout(0.5)\n\n        self.fc1 = nn.Linear(256*8*8, 512)\n        self.fc2 = nn.Linear(512, 128)\n        self.fc3 = nn.Linear(128, 10)\n\n    def forward(self, x):\n\n        x = F.relu(self.bn1(self.conv1(x)))\n        x = self.pool(F.relu(self.bn2(self.conv2(x))))\n\n        x = F.relu(self.bn3(self.conv3(x)))\n        x = self.pool(F.relu(self.bn4(self.conv4(x))))\n\n        x = x.view(x.size(0), -1)\n\n        x = self.dropout1(F.relu(self.fc1(x)))\n        x = self.dropout2(F.relu(self.fc2(x)))\n\n        x = self.fc3(x)\n\n        return x\n\n\nnet = Net().to(device)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-03-22T04:59:34.176876Z","iopub.execute_input":"2026-03-22T04:59:34.177194Z","iopub.status.idle":"2026-03-22T04:59:34.394418Z","shell.execute_reply.started":"2026-03-22T04:59:34.177172Z","shell.execute_reply":"2026-03-22T04:59:34.393482Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"<h4 style=\"color:#0321B8;text-align:center;margin-bottom:6px;\">\nTable: Training Configuration and Experimental Setup\n</h4>\n\n<div style=\"background-color:#F7F9FF;border-left:6px solid #0321B8;\npadding:12px;border-radius:6px;\">\n\n<table style=\"width:100%;border-collapse:collapse;font-size:14px;text-align:center;\">\n<tr style=\"background-color:#EAF0FF;\">\n<th style=\"padding:8px;border:1px solid #ccc;\">Component</th>\n<th style=\"padding:8px;border:1px solid #ccc;\">Configuration</th>\n<th style=\"padding:8px;border:1px solid #ccc;\">Purpose</th>\n</tr>\n\n<tr>\n<td>Model Architecture</td>\n<td>Custom CNN with BatchNorm and Dropout</td>\n<td>Feature extraction and classification</td>\n</tr>\n\n<tr>\n<td>Loss Function</td>\n<td>CrossEntropyLoss</td>\n<td>Handles multi-class classification</td>\n</tr>\n\n<tr>\n<td>Optimizers</td>\n<td>SGD, SGD+Momentum, NAG, Adam, AdamW, RMSprop, Adagrad</td>\n<td>Compare optimization techniques</td>\n</tr>\n\n<tr>\n<td>Maximum Epochs</td>\n<td>100</td>\n<td>Upper bound for training iterations</td>\n</tr>\n\n<tr>\n<td>Early Stopping</td>\n<td>Patience = 5</td>\n<td>Stops training when validation loss stops improving</td>\n</tr>\n\n<tr>\n<td>Model Checkpointing</td>\n<td>Best model saved per optimizer</td>\n<td>Ensures best validation performance is preserved</td>\n</tr>\n\n<tr>\n<td>Evaluation Metrics</td>\n<td>Validation Loss and Accuracy</td>\n<td>Measure model performance</td>\n</tr>\n\n</table>\n\n</div>","metadata":{}},{"cell_type":"code","source":"criterion = nn.CrossEntropyLoss()\noptimizers = {\n    \"SGD\": torch.optim.SGD,\n    \"SGD_Momentum\": lambda params: torch.optim.SGD(params, lr=0.01, momentum=0.9),\n    \"SGD_Momentum+NAG\": lambda params: torch.optim.SGD(params, lr=0.01, momentum=0.9, nesterov=True),\n    \"Adam\": torch.optim.Adam,\n    \"AdamW\": torch.optim.AdamW,\n    \"RMSprop\": torch.optim.RMSprop,\n    \"Adagrad\": torch.optim.Adagrad\n}","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-03-22T04:59:34.395548Z","iopub.execute_input":"2026-03-22T04:59:34.395890Z","iopub.status.idle":"2026-03-22T04:59:34.401477Z","shell.execute_reply.started":"2026-03-22T04:59:34.395861Z","shell.execute_reply":"2026-03-22T04:59:34.400723Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def evaluate(model, loader, criterion, device):\n\n    model.eval()\n    total_loss = 0\n    correct = 0\n    total = 0\n\n    with torch.no_grad():\n        for inputs, labels in loader:\n\n            inputs = inputs.to(device)\n            labels = labels.to(device)\n\n            outputs = model(inputs)\n            loss = criterion(outputs, labels)\n\n            total_loss += loss.item()\n\n            _, predicted = torch.max(outputs, 1)\n\n            total += labels.size(0)\n            correct += (predicted == labels).sum().item()\n\n    avg_loss = total_loss / len(loader)\n    accuracy = correct / total\n\n    return avg_loss, accuracy","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-03-22T04:59:34.403840Z","iopub.execute_input":"2026-03-22T04:59:34.404274Z","iopub.status.idle":"2026-03-22T04:59:34.415473Z","shell.execute_reply.started":"2026-03-22T04:59:34.404254Z","shell.execute_reply":"2026-03-22T04:59:34.414857Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def train_model(optimizer_name, optimizer_fn, patience=5):\n\n    net = Net().to(device)\n\n    optimizer = optimizer_fn(net.parameters())\n    criterion = nn.CrossEntropyLoss()\n\n    train_losses = []\n    val_losses = []\n\n    best_val_loss = float(\"inf\")\n    counter = 0\n\n    epochs = 100\n\n    for epoch in range(epochs):\n\n        net.train()\n        running_loss = 0\n\n        for inputs, labels in trainloader:\n\n            inputs = inputs.to(device)\n            labels = labels.to(device)\n\n            optimizer.zero_grad()\n\n            outputs = net(inputs)\n            loss = criterion(outputs, labels)\n\n            loss.backward()\n            optimizer.step()\n\n            running_loss += loss.item()\n\n        train_loss = running_loss / len(trainloader)\n\n        val_loss, val_acc = evaluate(net, valloader, criterion, device)\n\n        train_losses.append(train_loss)\n        val_losses.append(val_loss)\n\n        print(f\"{optimizer_name} | Epoch {epoch+1}: \"\n              f\"Train Loss {train_loss:.4f}, \"\n              f\"Val Loss {val_loss:.4f}, \"\n              f\"Val Acc {val_acc:.4f}\")\n\n        # Early stopping check\n        if val_loss < best_val_loss:\n\n            best_val_loss = val_loss\n            counter = 0\n\n            torch.save(net.state_dict(), f\"best_{optimizer_name}.pth\")\n\n        else:\n\n            counter += 1\n\n            if counter >= patience:\n                print(f\"Early stopping triggered for {optimizer_name}\")\n                break\n\n    # Load best model before returning results\n    net.load_state_dict(torch.load(f\"best_{optimizer_name}.pth\"))\n\n    return train_losses, val_losses, val_acc","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-03-22T04:59:34.416584Z","iopub.execute_input":"2026-03-22T04:59:34.417160Z","iopub.status.idle":"2026-03-22T04:59:34.435115Z","shell.execute_reply.started":"2026-03-22T04:59:34.417131Z","shell.execute_reply":"2026-03-22T04:59:34.434324Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"results = {}\n\nfor name, opt in optimizers.items():\n\n    print(f\"\\nTraining with {name}\")\n\n    train_losses, val_losses, val_acc = train_model(name, opt)\n\n    results[name] = {\n        \"train_loss\": train_losses,\n        \"val_loss\": val_losses,\n        \"val_acc\": val_acc\n    }\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-03-22T04:59:34.436084Z","iopub.execute_input":"2026-03-22T04:59:34.436465Z","iopub.status.idle":"2026-03-22T05:38:41.289095Z","shell.execute_reply.started":"2026-03-22T04:59:34.436436Z","shell.execute_reply":"2026-03-22T05:38:41.288249Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"plt.figure(figsize=(10,6))\n\nfor name in results:\n    plt.plot(results[name][\"train_loss\"], label=name)\n\nplt.xlabel(\"Epochs\")\nplt.ylabel(\"Training Loss\")\nplt.title(\"Optimizer Comparison\")\nplt.legend()\n\nplt.show()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-03-22T05:38:41.290502Z","iopub.execute_input":"2026-03-22T05:38:41.290766Z","iopub.status.idle":"2026-03-22T05:38:41.482240Z","shell.execute_reply.started":"2026-03-22T05:38:41.290741Z","shell.execute_reply":"2026-03-22T05:38:41.481543Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"plt.figure(figsize=(10,6))\n\nfor name in results:\n    plt.plot(results[name][\"val_loss\"], label=name)\n\nplt.xlabel(\"Epochs\")\nplt.ylabel(\"Validation Loss\")\nplt.title(\"Optimizer Comparison\")\nplt.legend()\n\nplt.show()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-03-22T05:38:41.483158Z","iopub.execute_input":"2026-03-22T05:38:41.483465Z","iopub.status.idle":"2026-03-22T05:38:41.665181Z","shell.execute_reply.started":"2026-03-22T05:38:41.483428Z","shell.execute_reply":"2026-03-22T05:38:41.664121Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"<div style=\"background-color:#F7F9FF;border-left:6px solid #0321B8;\npadding:12px;border-radius:6px;\">\n\n<table style=\"width:100%;border-collapse:collapse;font-size:14px;text-align:center;\">\n<tr style=\"background-color:#EAF0FF;\">\n<th style=\"padding:8px;border:1px solid #ccc;\">Optimizer</th>\n<th style=\"padding:8px;border:1px solid #ccc;\">Convergence Behaviour</th>\n<th style=\"padding:8px;border:1px solid #ccc;\">Best Validation Accuracy</th>\n<th style=\"padding:8px;border:1px solid #ccc;\">Observation</th>\n</tr>\n\n<tr>\n<td style=\"padding:8px;border:1px solid #ccc;\"><b>SGD</b></td>\n<td style=\"padding:8px;border:1px solid #ccc;\">Slow convergence</td>\n<td style=\"padding:8px;border:1px solid #ccc;\">~65%</td>\n<td style=\"padding:8px;border:1px solid #ccc;\">Stable learning but requires many epochs</td>\n</tr>\n\n<tr>\n<td style=\"padding:8px;border:1px solid #ccc;\"><b>SGD + Momentum</b></td>\n<td style=\"padding:8px;border:1px solid #ccc;\">Fast and stable convergence</td>\n<td style=\"padding:8px;border:1px solid #ccc;\">~84–85%</td>\n<td style=\"padding:8px;border:1px solid #ccc;\">Best performance due to accelerated gradients</td>\n</tr>\n\n<tr>\n<td style=\"padding:8px;border:1px solid #ccc;\"><b>SGD + NAG</b></td>\n<td style=\"padding:8px;border:1px solid #ccc;\">Faster than SGD</td>\n<td style=\"padding:8px;border:1px solid #ccc;\">~71–72%</td>\n<td style=\"padding:8px;border:1px solid #ccc;\">Predictive gradient improves update direction</td>\n</tr>\n\n<tr>\n<td style=\"padding:8px;border:1px solid #ccc;\"><b>Adam</b></td>\n<td style=\"padding:8px;border:1px solid #ccc;\">Fast initial learning</td>\n<td style=\"padding:8px;border:1px solid #ccc;\">~80%</td>\n<td style=\"padding:8px;border:1px solid #ccc;\">Adaptive learning rates speed up convergence</td>\n</tr>\n\n<tr>\n<td style=\"padding:8px;border:1px solid #ccc;\"><b>AdamW</b></td>\n<td style=\"padding:8px;border:1px solid #ccc;\">Fast and stable</td>\n<td style=\"padding:8px;border:1px solid #ccc;\">~80%</td>\n<td style=\"padding:8px;border:1px solid #ccc;\">Improved weight decay regularization</td>\n</tr>\n\n<tr>\n<td style=\"padding:8px;border:1px solid #ccc;\"><b>Adagrad</b></td>\n<td style=\"padding:8px;border:1px solid #ccc;\">Moderate convergence</td>\n<td style=\"padding:8px;border:1px solid #ccc;\">~67%</td>\n<td style=\"padding:8px;border:1px solid #ccc;\">Learning rate decays quickly</td>\n</tr>\n\n<tr>\n<td style=\"padding:8px;border:1px solid #ccc;\"><b>RMSprop</b></td>\n<td style=\"padding:8px;border:1px solid #ccc;\">Unstable training</td>\n<td style=\"padding:8px;border:1px solid #ccc;\">~10%</td>\n<td style=\"padding:8px;border:1px solid #ccc;\">Failed to converge with current settings</td>\n</tr>\n\n</table>\n\n</div>\n\n<div style=\"background-color:#F7F9FF;border-left:6px solid #0321B8;\npadding:10px;border-radius:6px;margin-top:10px;\">\n\n<p style=\"font-size:14px;color:#333333;\">\nFrom the comparison, <b>SGD with Momentum</b> achieved the best overall performance, reaching the highest validation accuracy while maintaining stable convergence. \nAdaptive optimizers such as <b>Adam</b> and <b>AdamW</b> showed faster initial learning but slightly lower final accuracy compared to momentum-based SGD. \n<b>Adagrad</b> demonstrated moderate performance due to aggressive learning rate decay, while <b>RMSprop</b> failed to converge effectively with the chosen hyperparameters. \nThese results highlight the importance of momentum in accelerating gradient descent and improving training efficiency for CNN models.\n</p>\n\n</div>","metadata":{}},{"cell_type":"markdown","source":"<h2 style=\"background-color:#F1F4FF;color:#4F6BD8;\npadding:6px;border-radius:6px;text-align:center;\">\nModel Evaluation on Test Dataset\n</h2>","metadata":{"execution":{"iopub.status.busy":"2026-03-12T14:23:10.163841Z","iopub.execute_input":"2026-03-12T14:23:10.164413Z","iopub.status.idle":"2026-03-12T14:23:10.168994Z","shell.execute_reply.started":"2026-03-12T14:23:10.164385Z","shell.execute_reply":"2026-03-12T14:23:10.168225Z"}}},{"cell_type":"markdown","source":"<div style=\"background-color:#F7F9FF;border-left:6px solid #0321B8;\npadding:10px;border-radius:6px;\">\n\n<p style=\"color:#333333;font-size:14px;\">\nAfter training and comparing different optimization algorithms, the final step is to evaluate the model on the \n<b>CIFAR-10 test dataset</b>. This dataset contains unseen images that were not used during training or validation, \nallowing us to measure the model’s true generalization performance. The images are converted into tensors and \nnormalized using the CIFAR-10 dataset statistics to maintain consistency with the training pipeline. \nThe dataset is then loaded using a <b>PyTorch DataLoader</b>, which enables efficient batch-wise processing during \nmodel evaluation.\n</p>\n\n</div>","metadata":{}},{"cell_type":"code","source":"testset = torchvision.datasets.CIFAR10(root='/kaggle/working/data', \n                                        train=False, \n                                        download=True,\n                                        transform = transforms.Compose([transforms.RandomHorizontalFlip(),\n                                                                      transforms.RandomCrop(32, padding=4),\n                                                                      transforms.ToTensor(),\n                                                                      transforms.Normalize((0.4914,0.4822,0.4465),(0.2470,0.2435,0.2616))]\n                                                                      ))\ntestloader = torch.utils.data.DataLoader(testset,num_workers = 4, pin_memory=True)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-03-22T05:38:41.666371Z","iopub.execute_input":"2026-03-22T05:38:41.666618Z","iopub.status.idle":"2026-03-22T05:38:42.401087Z","shell.execute_reply.started":"2026-03-22T05:38:41.666598Z","shell.execute_reply":"2026-03-22T05:38:42.400492Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def get_predictions(model, loader):\n\n    model.eval()\n\n    all_labels = []\n    all_preds = []\n    all_probs = []\n\n    with torch.no_grad():\n\n        for images, labels in loader:\n\n            images = images.to(device)\n            labels = labels.to(device)\n\n            outputs = model(images)\n\n            probs = F.softmax(outputs, dim=1)\n\n            _, preds = torch.max(outputs, 1)\n\n            all_labels.extend(labels.cpu().numpy())\n            all_preds.extend(preds.cpu().numpy())\n            all_probs.extend(probs.cpu().numpy())\n\n    return np.array(all_labels), np.array(all_preds), np.array(all_probs)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-03-22T05:38:42.402055Z","iopub.execute_input":"2026-03-22T05:38:42.402344Z","iopub.status.idle":"2026-03-22T05:38:42.407840Z","shell.execute_reply.started":"2026-03-22T05:38:42.402324Z","shell.execute_reply":"2026-03-22T05:38:42.407337Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"optimizers_list = [\n    \"SGD\",\n    \"SGD_Momentum\",\n    \"SGD_Momentum+NAG\",\n    \"Adam\",\n    \"AdamW\",\n    \"RMSprop\",\n    \"Adagrad\"\n]","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-03-22T05:38:42.408827Z","iopub.execute_input":"2026-03-22T05:38:42.409105Z","iopub.status.idle":"2026-03-22T05:38:42.420438Z","shell.execute_reply.started":"2026-03-22T05:38:42.409078Z","shell.execute_reply":"2026-03-22T05:38:42.419835Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"from sklearn.metrics import (\n    accuracy_score,\n    confusion_matrix,\n    classification_report\n)\n\ndef evaluate_metrics(y_true, y_pred):\n\n    acc = accuracy_score(y_true, y_pred)\n\n    cm = confusion_matrix(y_true, y_pred)\n\n    report = classification_report(y_true, y_pred)\n\n    print(\"Accuracy:\", acc)\n    print(\"\\nClassification Report:\")\n    print(report)\n\n    return cm","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-03-22T05:38:42.421477Z","iopub.execute_input":"2026-03-22T05:38:42.421826Z","iopub.status.idle":"2026-03-22T05:38:42.434632Z","shell.execute_reply.started":"2026-03-22T05:38:42.421799Z","shell.execute_reply":"2026-03-22T05:38:42.433887Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"results = []\n\nfor opt in optimizers_list:\n\n    #print(f\"\\nEvaluating {opt}\")\n\n    net = Net().to(device)\n\n    net.load_state_dict(torch.load(f\"best_{opt}.pth\"))\n\n    y_true, y_pred, y_prob = get_predictions(net, testloader)\n\n    acc = accuracy_score(y_true, y_pred)\n\n    precision = precision_score(y_true, y_pred, average=\"macro\")\n    recall = recall_score(y_true, y_pred, average=\"macro\")\n    f1 = f1_score(y_true, y_pred, average=\"macro\")\n\n    y_true_bin = label_binarize(y_true, classes=list(range(10)))\n    auc = roc_auc_score(y_true_bin, y_prob, multi_class=\"ovr\")\n\n    results.append({\n        \"Optimizer\": opt,\n        \"Accuracy\": acc,\n        \"Precision\": precision,\n        \"Recall\": recall,\n        \"F1 Score\": f1,\n        \"AUC\": auc\n    })\n\nresults_df = pd.DataFrame(results)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-03-22T05:38:42.435450Z","iopub.execute_input":"2026-03-22T05:38:42.435793Z","iopub.status.idle":"2026-03-22T05:41:41.063952Z","shell.execute_reply.started":"2026-03-22T05:38:42.435769Z","shell.execute_reply":"2026-03-22T05:41:41.062932Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"plt.figure(figsize=(15,5))\n\nplt.bar(results_df[\"Optimizer\"], results_df[\"Accuracy\"])\n\nplt.title(\"Optimizer Accuracy Comparison\")\nplt.ylabel(\"Accuracy\")\nplt.xlabel(\"Optimizer\")\n\nplt.show()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-03-22T05:41:41.065523Z","iopub.execute_input":"2026-03-22T05:41:41.065829Z","iopub.status.idle":"2026-03-22T05:41:41.212601Z","shell.execute_reply.started":"2026-03-22T05:41:41.065804Z","shell.execute_reply":"2026-03-22T05:41:41.211672Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"<h4 style=\"color:#0321B8;text-align:center;margin-bottom:6px;\">\nTable: Overall Performance of Optimization Algorithms on CIFAR-10 test set\n</h4>\n\n<div style=\"background-color:#F7F9FF;border-left:6px solid #0321B8;\npadding:12px;border-radius:6px;\">\n\n<table style=\"width:100%;border-collapse:collapse;font-size:14px;text-align:center;\">\n<tr style=\"background-color:#EAF0FF;\">\n<th style=\"padding:8px;border:1px solid #ccc;\">Optimizer</th>\n<th style=\"padding:8px;border:1px solid #ccc;\">Accuracy</th>\n<th style=\"padding:8px;border:1px solid #ccc;\">Precision</th>\n<th style=\"padding:8px;border:1px solid #ccc;\">Recall</th>\n<th style=\"padding:8px;border:1px solid #ccc;\">F1 Score</th>\n<th style=\"padding:8px;border:1px solid #ccc;\">AUC</th>\n</tr>\n\n<tr><td><b>SGD</b></td><td>0.6486</td><td>0.6445</td><td>0.6486</td><td>0.6445</td><td>0.9426</td></tr>\n<tr><td><b>SGD + Momentum</b></td><td>0.8458</td><td>0.8478</td><td>0.8458</td><td>0.8456</td><td>0.9861</td></tr>\n<tr><td><b>SGD + NAG</b></td><td>0.7194</td><td>0.7264</td><td>0.7194</td><td>0.7201</td><td>0.9612</td></tr>\n<tr><td><b>Adam</b></td><td>0.8021</td><td>0.8035</td><td>0.8021</td><td>0.8007</td><td>0.9779</td></tr>\n<tr><td><b>AdamW</b></td><td>0.8002</td><td>0.8045</td><td>0.8002</td><td>0.8005</td><td>0.9778</td></tr>\n<tr><td><b>Adagrad</b></td><td>0.6756</td><td>0.6967</td><td>0.6756</td><td>0.6805</td><td>0.9515</td></tr>\n<tr><td><b>RMSprop</b></td><td>0.1000</td><td>0.0100</td><td>0.1000</td><td>0.0182</td><td>0.5000</td></tr>\n\n</table>\n\n</div>","metadata":{}},{"cell_type":"markdown","source":"<div style=\"background-color:#F7F9FF;border-left:6px solid #0321B8;\npadding:10px;border-radius:6px;margin-top:10px;\">\n\n<p style=\"font-size:14px;color:#333333;\">\n\nThe final comparison shows clear differences in the performance of optimization algorithms when applied to the CNN model on the CIFAR-10 dataset.\n\n<ul>\n\n<li><b>SGD with Momentum</b> achieved the best performance across all evaluation metrics with an accuracy of <b>84.58%</b> and the highest AUC score of <b>0.986</b>. This demonstrates that momentum significantly improves convergence by accelerating gradient updates and reducing oscillations.</li>\n\n<li><b>Adam</b> and <b>AdamW</b> also performed strongly with accuracies of approximately <b>80%</b>. These adaptive optimizers adjust learning rates dynamically for each parameter, enabling faster convergence during the early stages of training.</li>\n\n<li><b>SGD with Nesterov Accelerated Gradient</b> improved upon vanilla SGD but still lagged behind adaptive optimizers, reaching an accuracy of about <b>72%</b>.</li>\n\n<li><b>Adagrad</b> showed moderate performance with an accuracy of approximately <b>67%</b>. Its aggressive learning rate decay can slow down learning during later training stages.</li>\n\n<li><b>RMSprop</b> failed to converge effectively in this experiment, resulting in near-random performance (~<b>10%</b> accuracy). This indicates that the chosen hyperparameters were not suitable for this optimizer.</li>\n\n</ul>\n\nOverall, the results indicate that <b>SGD with Momentum provides the best balance between stability and performance</b> for the proposed CNN architecture on the CIFAR-10 dataset.\n\n</p>\n\n</div>","metadata":{}},{"cell_type":"code","source":"classes = testset.classes\n\nfor opt in optimizers.keys():\n\n    #print(f\"\\nConfusion Matrix for {opt}\")\n\n    # Load best trained model\n    net = Net().to(device)\n    net.load_state_dict(torch.load(f\"best_{opt}.pth\"))\n    net.eval()\n\n    y_true = []\n    y_pred = []\n\n    with torch.no_grad():\n\n        for images, labels in testloader:\n\n            images = images.to(device)\n            labels = labels.to(device)\n\n            outputs = net(images)\n\n            _, predicted = torch.max(outputs, 1)\n\n            y_true.extend(labels.cpu().numpy())\n            y_pred.extend(predicted.cpu().numpy())\n\n    cm = confusion_matrix(y_true, y_pred)\n\n    plt.figure(figsize=(8,6))\n\n    sns.heatmap(\n        cm,\n        annot=True,\n        fmt=\"d\",\n        cmap=\"Blues\",\n        xticklabels=classes,\n        yticklabels=classes\n    )\n\n    plt.title(f\"Confusion Matrix - {opt}\")\n    plt.xlabel(\"Predicted Label\")\n    plt.ylabel(\"True Label\")\n\n    plt.show()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-03-22T05:41:41.213630Z","iopub.execute_input":"2026-03-22T05:41:41.213893Z","iopub.status.idle":"2026-03-22T05:44:39.733005Z","shell.execute_reply.started":"2026-03-22T05:41:41.213873Z","shell.execute_reply":"2026-03-22T05:44:39.731970Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"<div style=\"background-color:#F7F9FF;border-left:6px solid #0321B8;\npadding:12px;border-radius:6px;\">\n\n<p style=\"font-size:14px;color:#333333;\">\n\nThe confusion matrices provide deeper insight into how different optimization algorithms affect the classification behavior of the CNN model on the CIFAR-10 dataset. Each matrix illustrates how often images from a true class are predicted as another class.\n\n</p>\n\n<ul style=\"font-size:14px;color:#333333;\">\n\n<li>\n<b>SGD:</b> The baseline SGD optimizer shows noticeable confusion between visually similar classes such as <b>cat–dog</b>, <b>automobile–truck</b>, and <b>bird–airplane</b>. While the model correctly identifies some categories such as <b>frog</b> and <b>ship</b>, the overall distribution of misclassifications indicates slower convergence and weaker feature separation.\n</li>\n\n<li>\n<b>SGD with Momentum:</b> This optimizer produces the most concentrated diagonal values, meaning most predictions fall on the correct class. Classes such as <b>automobile, frog, ship, and truck</b> show very high correct classification counts. The reduction in off-diagonal errors indicates improved gradient updates and faster convergence.\n</li>\n\n<li>\n<b>SGD with Nesterov Momentum:</b> NAG improves performance compared to vanilla SGD but still exhibits confusion in challenging classes like <b>cat vs dog</b> and <b>bird vs airplane</b>. While diagonal dominance increases, it remains weaker than the momentum variant.\n</li>\n\n<li>\n<b>Adam and AdamW:</b> Both adaptive optimizers demonstrate strong diagonal dominance across most classes. They significantly reduce confusion for <b>deer, frog, ship, and truck</b>. However, some ambiguity remains between <b>cat and dog</b> due to similar visual features in the dataset.\n</li>\n\n<li>\n<b>Adagrad:</b> This optimizer shows moderate performance. While several classes such as <b>automobile, frog, horse, and truck</b> are classified well, confusion persists in complex categories like <b>cat, bird, and dog</b>. The learning rate decay characteristic of Adagrad likely limits later training improvements.\n</li>\n\n<li>\n<b>RMSprop:</b> RMSprop failed to converge properly in this experiment. The confusion matrix shows that almost all samples were predicted as a single class (<b>truck</b>), resulting in near-random classification performance.\n</li>\n\n</ul>\n\n<p style=\"font-size:14px;color:#333333;\">\n\nOverall, the confusion matrices confirm that <b>SGD with Momentum</b> provides the most balanced and accurate classification performance for this CNN architecture. Adaptive optimizers such as <b>Adam</b> and <b>AdamW</b> also perform well, while vanilla SGD and RMSprop show comparatively weaker class separation.\n\n</p>\n\n</div>","metadata":{}},{"cell_type":"markdown","source":"<h2 style=\"background-color:#F1F4FF;color:#4F6BD8;\npadding:6px;border-radius:6px;text-align:center;\">\nConclusion\n</h2>","metadata":{}},{"cell_type":"markdown","source":"<div style=\"background-color:#F7F9FF;border-left:6px solid #0321B8;\npadding:12px;border-radius:6px;\">\n\n<p style=\"font-size:14px;color:#333333;\">\n\nThis study compared multiple optimization algorithms for training a Convolutional Neural Network on the CIFAR-10 image classification dataset. \nThe results demonstrate that optimization strategy plays a crucial role in model convergence, classification accuracy, and overall training stability.\n\n</p>\n\n<ul style=\"font-size:14px;color:#333333;\">\n\n<li>\n<b>SGD with Momentum</b> achieved the best overall performance, reaching the highest accuracy and producing the most balanced confusion matrix across all classes.\n</li>\n\n<li>\nAdaptive optimizers such as <b>Adam</b> and <b>AdamW</b> also showed strong performance with fast convergence and competitive accuracy.\n</li>\n\n<li>\nBasic <b>SGD</b> and <b>Adagrad</b> performed moderately, indicating slower convergence and weaker feature separation.\n</li>\n\n<li>\n<b>RMSprop</b> failed to converge effectively with the chosen hyperparameters, highlighting the importance of careful optimizer tuning.\n</li>\n\n</ul>\n\n<p style=\"font-size:14px;color:#333333;\">\n\nOverall, the experiments show that incorporating <b>momentum-based optimization</b> significantly improves training efficiency and classification performance for CNN models on CIFAR-10. These findings emphasize the importance of selecting an appropriate optimizer when training deep learning models.\n\n</p>\n\n</div>","metadata":{}},{"cell_type":"markdown","source":"<div style=\"width:100%; height:450px; display:flex; justify-content:center; align-items:center; background-color:#F7F9FF; border-radius:12px;\">\n\n<h1 style=\"font-size:100px; color:#0321B8; text-align:center; margin:0; letter-spacing:3px;\">\nTHANK YOU\n</h1>\n\n</div>","metadata":{}}]}