Deep Learning Assignment 1
Deep Learning Assignment 1
BhawnaMehbubani Deep_Learning_Assignments
Code Issues Pull requests Actions Projects Wiki Security Insights Settings
GitHub users are now required to enable two-factor authentication as an additional security measure. Your activity on GitHub
includes you in this requirement. You will need to enable two-factor authentication on your account before September 11, 2025, or be Enable 2FA
restricted from account actions.
Deep_Learning_Assignments / Deep_Learning_Assignment_1.ipynb
BhawnaMehbubani Created using Colab c0b8ee1 · 2 minutes ago
[Link] 1/12
14/08/2025, 00:17 Deep_Learning_Assignments/Deep_Learning_Assignment_1.ipynb at main · BhawnaMehbubani/Deep_Learning_Assignments
Open in Colab
In [1]:
import os
import random
import time
import copy
from itertools import product
import numpy as np
import [Link] as plt
import torch
import [Link] as nn
import [Link] as F
from [Link] import DataLoader, random_split, Subset
import torchvision
from torchvision import datasets, transforms, models
In [2]:
# ----------------------------
# Reproducibility
# ----------------------------
SEED = 42
[Link](SEED)
[Link](SEED)
torch.manual_seed(SEED)
if [Link].is_available():
[Link].manual_seed_all(SEED)
Device: cuda
In [3]:
# ----------------------------
# Config / Paths
# ----------------------------
OUT_DIR = "cifar_experiments"
[Link](OUT_DIR, exist_ok=True)
BEST_MODEL_PATH = [Link](OUT_DIR, "best_model.pth")
In [4]:
# ----------------------------
# Data transforms and loaders
# ----------------------------
# For AlexNet we will resize to 224. For custom CNN we can keep 32 or resize as desired.
transform_train_alex = [Link]([
[Link](224),
[Link](),
[Link](224, padding=4),
[Link](),
[Link]((0.4914, 0.4822, 0.4465),
(0.2470, 0.2435, 0.2616))
])
transform_test_alex = [Link]([
[Link](224),
[Link](),
[Link]((0.4914, 0.4822, 0.4465),
(0.2470, 0.2435, 0.2616))
])
# Download CIFAR-10
dataset_train_full = datasets.CIFAR10(root="./data", train=True, download=True, transform=transform_train)
dataset_test = datasets.CIFAR10(root="./data", train=False, download=True, transform=transform_test)
# We'll create a validation split from the train set (e.g., 45k train + 5k val)
val_size = 5000
train_size = len(dataset_train_full) - val_size
dataset_train, dataset_val = random_split(dataset_train_full, [train_size, val_size], generator=[Link]().
[Link] 2/12
14/08/2025, 00:17 Deep_Learning_Assignments/Deep_Learning_Assignment_1.ipynb at main · BhawnaMehbubani/Deep_Learning_Assignments
100%|██████████| 170M/170M [00:03<00:00, 44.0MB/s]
In [5]:
# Class names
classes = dataset_train_full.classes
num_classes = len(classes)
print("Classes:", classes)
# Pie chart
[Link](figsize=(6,6))
[Link](counts, labels=classes, autopct='%1.1f%%')
[Link]("CIFAR-10 class distribution (training set) - Pie")
plt.tight_layout()
[Link]([Link](OUT_DIR, "class_pie.png"))
[Link]()
plot_class_distribution()
Classes: ['airplane', 'automobile', 'bird', 'cat', 'deer', 'dog', 'frog', 'horse', 'ship', 'truck']
In [6]:
# ----------------------------
# AlexNet implementation (adapted)
# ----------------------------
[Link] 3/12
14/08/2025, 00:17 Deep_Learning_Assignments/Deep_Learning_Assignment_1.ipynb at main · BhawnaMehbubani/Deep_Learning_Assignments
class AlexNetCIFAR([Link]):
def __init__(self, num_classes=10):
super(AlexNetCIFAR, self).__init__()
# Use the torchvision AlexNet but adjusted final classifier for num_classes,
# or implement a smaller variant:
[Link] = [Link](
nn.Conv2d(3, 64, kernel_size=11, stride=4, padding=2), # output ~ (64, 54, 54) for 224 input
[Link](inplace=True),
nn.MaxPool2d(kernel_size=3, stride=2),
nn.Conv2d(64, 192, kernel_size=5, padding=2),
[Link](inplace=True),
nn.MaxPool2d(kernel_size=3, stride=2),
nn.Conv2d(192, 384, kernel_size=3, padding=1),
[Link](inplace=True),
nn.Conv2d(384, 256, kernel_size=3, padding=1),
[Link](inplace=True),
nn.Conv2d(256, 256, kernel_size=3, padding=1),
[Link](inplace=True),
nn.MaxPool2d(kernel_size=3, stride=2),
)
# classifier
[Link] = [Link](
[Link](),
[Link](256 * 6 * 6, 4096), # assumes input 224-> after convs ~6x6
[Link](inplace=True),
[Link](),
[Link](4096, 4096),
[Link](inplace=True),
[Link](4096, num_classes),
)
In [7]:
def train_one_epoch(model, dataloader, criterion, optimizer, device):
[Link]()
running_loss = 0.0
correct = 0
total = 0
for imgs, labels in dataloader:
imgs, labels = [Link](device), [Link](device)
optimizer.zero_grad()
outputs = model(imgs)
loss = criterion(outputs, labels)
[Link]()
[Link]()
@torch.no_grad()
def evaluate(model, dataloader, criterion, device):
[Link]()
running_loss = 0.0
correct = 0
total = 0
all_preds = []
all_labels = []
for imgs, labels in dataloader:
imgs, labels = [Link](device), [Link](device)
outputs = model(imgs)
loss = criterion(outputs, labels)
all_preds.append([Link]().numpy())
all_labels.append([Link]().numpy())
In [8]:
# ----------------------------
# Function to train AlexNet and plot accuracy curves
# ----------------------------
def run_alexnet_experiment(epochs=20, batch_size=128, lr=1e-3, optimizer_name='Adam'):
print("Preparing data loaders for AlexNet...")
train_loader = DataLoader(dataset_train_alex, batch_size=batch_size, shuffle=True, num_workers=4, pin_memory=T
val_loader = DataLoader(dataset_val_alex, batch_size=batch_size, shuffle=False, num_workers=4, pin_memory=True
test_loader = DataLoader(dataset_test_alex, batch_size=batch_size, shuffle=False, num_workers=4, pin_memory=Tr
[Link] 4/12
14/08/2025, 00:17 Deep_Learning_Assignments/Deep_Learning_Assignment_1.ipynb at main · BhawnaMehbubani/Deep_Learning_Assignments
model = AlexNetCIFAR(num_classes=num_classes).to(device)
criterion = [Link]()
if optimizer_name.lower() == 'adam':
optimizer = [Link]([Link](), lr=lr)
else:
optimizer = [Link]([Link](), lr=lr)
best_val_acc = 0.0
best_model_wts = [Link](model.state_dict())
history = {'train_loss':[], 'train_acc':[], 'val_loss':[], 'val_acc':[], 'test_acc':[]}
history['train_loss'].append(train_loss)
history['train_acc'].append(train_acc)
history['val_loss'].append(val_loss)
history['val_acc'].append(val_acc)
history['test_acc'].append(test_acc)
# restore best
model.load_state_dict(best_model_wts)
In [9]:
# ----------------------------
# Build a configurable CNN dynamically
# ----------------------------
class SimpleCNN([Link]):
def __init__(self, in_channels=3, num_classes=10, conv_layers_cfg=[(32,3), (64,3), (128,3)], use_batchnorm=Tru
"""
conv_layers_cfg: list of tuples (num_filters, kernel_size)
pool_every: apply MaxPool after every 'pool_every' conv layers
"""
super(SimpleCNN, self).__init__()
layers = []
channels = in_channels
conv_count = 0
for (out_channels, k) in conv_layers_cfg:
padding = k // 2
[Link](nn.Conv2d(channels, out_channels, kernel_size=k, padding=padding))
if use_batchnorm:
[Link](nn.BatchNorm2d(out_channels))
[Link]([Link](inplace=True))
conv_count += 1
if conv_count % pool_every == 0:
[Link](nn.MaxPool2d(2))
channels = out_channels
self.feature_extractor = [Link](*layers)
[Link] = [Link](
[Link](0.5),
[Link](flattened, 256),
[Link](inplace=True),
[Link](0.5),
[Link](256, num_classes)
)
# ----------------------------
# Hyperparameter tuning routine (simple grid search)
# ----------------------------
def tune_and_train(grid, max_epochs=30, early_stop_patience=6, verbose=True):
"""
grid: dict of lists for parameters:
- conv_layers_options: list of lists e.g. [[(32,3),(64,3),(128,3)], ...]
- batch_size_options: [64,128]
- lr_options: [1e-3, 1e-4]
- optimizer_options: ['Adam','RMSprop']
- epochs_options: [20] (we'll still use max_epochs)
We'll run combinations and pick best by validation accuracy.
"""
best_val = 0.0
best_result = {}
# Pre-create test loader (32x32 transforms)
test_loader = DataLoader(dataset_test, batch_size=256, shuffle=False, num_workers=4, pin_memory=True)
# Dataloaders
train_loader = DataLoader(dataset_train, batch_size=batch_size, shuffle=True, num_workers=4, pin_memory=Tr
val_loader = DataLoader(dataset_val, batch_size=batch_size, shuffle=False, num_workers=4, pin_memory=True)
best_local_val = 0.0
best_local_wts = [Link](model.state_dict())
epochs_no_improve = 0
history['train_acc'].append(train_acc)
history['val_acc'].append(val_acc)
# early stopping
if val_acc > best_local_val + 1e-6:
best_local_val = val_acc
best_local_wts = [Link](model.state_dict())
epochs_no_improve = 0
else:
epochs_no_improve += 1
# Save if best
if val_acc_final > best_val:
best_val = val_acc_final
best_result = {
'conv_cfg': conv_cfg,
'batch_size': batch_size,
'lr': lr,
'optimizer': opt_name,
'epochs_ran': epoch,
'val_acc': val_acc_final,
'test_acc': test_acc_final,
'model_state_dict': [Link](model.state_dict()),
'history': history
}
[Link]({
'model_state_dict': best_result['model_state_dict'],
'config': {
'conv_cfg': conv_cfg,
'batch_size': batch_size,
'lr': lr,
[Link] 6/12
14/08/2025, 00:17 Deep_Learning_Assignments/Deep_Learning_Assignment_1.ipynb at main · BhawnaMehbubani/Deep_Learning_Assignments
'optimizer': opt_name
}
}, BEST_MODEL_PATH)
print("New best saved.")
return best_result
In [10]:
# ----------------------------
# Metrics and final evaluation
# ----------------------------
def compute_metrics(y_true, y_pred):
acc = accuracy_score(y_true, y_pred)
precision_macro = precision_recall_fscore_support(y_true, y_pred, average='macro')[0]
recall_macro = precision_recall_fscore_support(y_true, y_pred, average='macro')[1]
f1_macro = f1_score(y_true, y_pred, average='macro')
precision_weighted = precision_recall_fscore_support(y_true, y_pred, average='weighted')[0]
recall_weighted = precision_recall_fscore_support(y_true, y_pred, average='weighted')[1]
f1_weighted = f1_score(y_true, y_pred, average='weighted')
return {
'accuracy': acc,
'precision_macro': precision_macro,
'recall_macro': recall_macro,
'f1_macro': f1_macro,
'precision_weighted': precision_weighted,
'recall_weighted': recall_weighted,
'f1_weighted': f1_weighted
}
In [ ]:
# ----------------------------
# Putting it all together
# ----------------------------
if __name__ == "__main__":
# 1) Run AlexNet baseline
alex_epochs = 12
alex_batch = 128
alex_lr = 1e-3
alex_optimizer = 'Adam'
print("=== Running AlexNet baseline ===")
alex_model, alex_hist = run_alexnet_experiment(epochs=alex_epochs, batch_size=alex_batch, lr=alex_lr, optimize
# Plot epoch vs training and validation accuracy for best run (if history available)
hist = [Link]('history')
if hist:
epochs_ran = len(hist['train_acc'])
[Link](figsize=(8,5))
[Link](range(1, epochs_ran+1), hist['train_acc'], label='train_acc')
[Link](range(1, epochs_ran+1), hist['val_acc'], label='val_acc')
[Link]("Epoch")
[Link]("Accuracy")
[Link]("Best Tuned CNN - Accuracy curves")
[Link]()
[Link](True)
[Link]([Link](OUT_DIR, "tunedcnn_accuracy_curves.png"))
[Link]()
[Link] 7/12
14/08/2025, 00:17 Deep_Learning_Assignments/Deep_Learning_Assignment_1.ipynb at main · BhawnaMehbubani/Deep_Learning_Assignments
[Link] 9/12
14/08/2025, 00:17 Deep_Learning_Assignments/Deep_Learning_Assignment_1.ipynb at main · BhawnaMehbubani/Deep_Learning_Assignments
[6] Epoch 16/20 - train_acc 0.3992, val_acc 0.5126
[6] Epoch 17/20 - train_acc 0.4017, val_acc 0.5420
[6] Epoch 18/20 - train_acc 0.4058, val_acc 0.4582
[6] Epoch 19/20 - train_acc 0.4103, val_acc 0.5548
[6] Epoch 20/20 - train_acc 0.4162, val_acc 0.5468
Combo 6 finished. val_acc=0.5472, test_acc=0.5717
[Link] 11/12
14/08/2025, 00:17 Deep_Learning_Assignments/Deep_Learning_Assignment_1.ipynb at main · BhawnaMehbubani/Deep_Learning_Assignments
--- Running combo 15/16 ---
conv_cfg: [(32, 3), (64, 3), (128, 3), (128, 3)] batch: 256 lr: 0.0001 opt: Adam epochs: 20
[15] Epoch 1/20 - train_acc 0.3409, val_acc 0.4732
[15] Epoch 2/20 - train_acc 0.4558, val_acc 0.5250
[15] Epoch 3/20 - train_acc 0.5071, val_acc 0.5722
[15] Epoch 4/20 - train_acc 0.5502, val_acc 0.6000
[15] Epoch 5/20 - train_acc 0.5819, val_acc 0.6122
[15] Epoch 6/20 - train_acc 0.6071, val_acc 0.6348
[15] Epoch 7/20 - train_acc 0.6248, val_acc 0.6338
[15] Epoch 8/20 - train_acc 0.6378, val_acc 0.6596
[15] Epoch 9/20 - train_acc 0.6525, val_acc 0.6654
[15] Epoch 10/20 - train_acc 0.6585, val_acc 0.6906
[15] Epoch 11/20 - train_acc 0.6695, val_acc 0.6906
[15] Epoch 12/20 - train_acc 0.6801, val_acc 0.6930
[15] Epoch 13/20 - train_acc 0.6846, val_acc 0.6918
[15] Epoch 14/20 - train_acc 0.6938, val_acc 0.6964
[15] Epoch 15/20 - train_acc 0.6937, val_acc 0.7138
[15] Epoch 16/20 - train_acc 0.7026, val_acc 0.7280
[15] Epoch 17/20 - train_acc 0.7061, val_acc 0.7220
[15] Epoch 18/20 - train_acc 0.7095, val_acc 0.7386
[15] Epoch 19/20 - train_acc 0.7167, val_acc 0.7306
[15] Epoch 20/20 - train_acc 0.7208, val_acc 0.7266
Combo 15 finished. val_acc=0.7274, test_acc=0.7520
[Link] 12/12