Assignment3 AL
Assignment3 AL
If you want to use GPU, google collab provides one gpu for free. For that you will need to import this notebook into google collab. Make sure
that you transfer all your data and model to GPU. After completing the assignment, you can export the file back to Jupyter Notebook,
Note: Submit the jupyter notebook and its pdf export. Before uploading to Canvas, make sure that all commands in your jupyter notebook are
executed, and outputs, plots, and figures are visible.
import numpy as np
import matplotlib
import matplotlib.pyplot as plt
import torchvision
import torchvision.transforms as transforms
from torch.utils.data import Dataset, DataLoader
Dataset
a) Download Rotated-Images dataset from Kaggle https://www.kaggle.com/datasets/shivajbd/imagerotation. Create two folders, train and
test, and copy first half of the dataset to training and remaining to test.
In [6]: import os
import shutil
def __len__(self):
return len(self.images)
mean /= num_images
std_dev /= num_images
c) Implement the custom dataset class for training and test. For training, do the following transforms:
(i) In the init method, store the path to the images and labels. You can use any data structure of your choice, e.g., list/nested list, dictionary, or
pandas dataframe.
(ii) in the getitem method, use the path stored at position idx to load the image. Return image and its label.
In [1]: import os
import torch
import torchvision
import torchvision.transforms as transforms
from torch.utils.data import DataLoader, random_split
from PIL import Image
# Define paths
data_dir = 'images'
train_dir = 'train'
test_dir = 'test'
# Define the transforms for training and testing
train_transform = transforms.Compose([
transforms.Resize((32, 32)),
transforms.ToTensor(),
transforms.Normalize((0.4538, 0.4538, 0.4214), (0.2296, 0.2316, 0.2516))
])
test_transform = transforms.Compose([
transforms.Resize((32, 32)),
transforms.ToTensor(),
transforms.Normalize((0.4538, 0.4538, 0.4214), (0.2296, 0.2316, 0.2516))
])
def __len__(self):
return len(self.images)
In [3]: # Partition the training dataset into training and validation sets
train_size = int(0.8 * len(train_dataset))
val_size = len(train_dataset) - train_size
train_data, val_data = random_split(train_dataset, [train_size, val_size])
def imshow(img):
img = img.numpy().transpose((1, 2, 0))
mean = np.array([0.4538, 0.4538, 0.4214])
std = np.array([0.2296, 0.2316, 0.2516])
img = std * img + mean
img = np.clip(img, 0, 1)
plt.imshow(img)
plt.axis('off')
plt.show()
Q1. CNN
a) Build a NN network specified in the figure below and initialize the parameters.
1. Convolution layer: 16 3x3 filters. Convolution is followed by BatchNorm and ReLu Activation fuction.
2. Residual block: first layer of the block has 32 number of 3x3 filters with stride=2 and second layer has 32 number of 3x3 filters. Use 1x1
filters in the shortcut path to make the output sizes of the two branches same. BatchNorm and ReLu follows convolution.
3. Maxpool with 2x2 filters and stride = 2
4. Convolution layer: 64 3x3 filters. Convolution is followed by BatchNorm and ReLu Activation fuction.
5. FC layer with 20 neurons and Dropout of p=0.1.
6. output layer.
Note: select padding of the convolution input such that output height and width are an integer division of input size. Use residual block from
ResNet18 as a reference.
In [103… import torch
import torch.nn as nn
import torch.optim as optim
import torch.nn.functional as F
class CNN(nn.Module):
def __init__(self, num_classes=10):
super(CNN, self).__init__()
# Convolution layer 1
self.conv1 = nn.Conv2d(3, 16, kernel_size=3, padding=1)
self.bn1 = nn.BatchNorm2d(16)
self.relu = nn.ReLU()
# Residual block
self.conv2_1 = nn.Conv2d(16, 32, kernel_size=3, stride=2, padding=1)
self.bn2_1 = nn.BatchNorm2d(32)
self.conv2_2 = nn.Conv2d(32, 32, kernel_size=3, padding=1)
self.bn2_2 = nn.BatchNorm2d(32)
self.shortcut = nn.Sequential(
nn.Conv2d(16, 32, kernel_size=1, stride=2, bias=False),
nn.BatchNorm2d(32)
)
# Maxpool layer
self.maxpool = nn.MaxPool2d(kernel_size=2, stride=2)
# Convolution layer 3
self.conv3 = nn.Conv2d(32, 1024, kernel_size=3, padding=1)
self.bn3 = nn.BatchNorm2d(1024)
# Dropout layer
self.dropout = nn.Dropout(p=0.1)
# Residual block
residual = self.shortcut(out)
out = self.bn2_1(self.conv2_1(out))
out = self.relu(out)
out = self.bn2_2(self.conv2_2(out))
out += residual
out = self.relu(out)
# Maxpool layer
out = self.maxpool(out)
# Convolution layer 3
out = self.relu(self.bn3(self.conv3(out)))
return out
b) Create a model
In [104… num_classes = 1
cnn_model = CNN(num_classes)
c) Do forward propagation for a minibatch and verify that the output shape equals the number of samples in a minibatch by the number of
classes.
torch.Size([16, 1])
d) Set up the loss and optimizer. Train using Stochastic gradient descent with momentum for 1 epoch with a learning rate of 0.01, momentum
of 0.9, and weight_decay of 1e − 8.
e) Do the training and validation. Follow the instructions in the code block to complete this part.
epochs = 1
# Training loop
for epoch in range(epochs):
cnn_model.train()
for batch_idx, (data, target) in enumerate(train_loader):
optimizer.zero_grad()
output = cnn_model(data)
loss = loss_fn(output, target)
loss.backward()
optimizer.step()
if batch_idx == 0:
print(f"Epoch {epoch}, Training Loss: {loss.item()}")
# Validation loop
cnn_model.eval()
val_loss = 0.0
correct = 0
total = 0
with torch.no_grad():
for val_data, val_target in val_loader:
val_output = cnn_model(val_data)
val_loss += loss_fn(val_output, val_target).item()
_, predicted = torch.max(val_output, 1)
total += val_target.size(0)
correct += (predicted == val_target).sum().item()
val_loss /= len(val_loader)
val_accuracy = 100.0 * correct / total
print(f"Epoch {epoch+1} - Validation Loss: {val_loss:.4f}, Validation Accuracy: {val_accuracy:.2f}%")
You need to use nested loop. Run each experiment for two epochs.
# Training loop
training_losses = [] # Store training losses for plotting
for epoch in range(epochs):
cnn_model.train()
for batch_idx, (data, target) in enumerate(train_loader):
optimizer.zero_grad()
output = cnn_model(data)
loss = loss_fn(output, target)
loss.backward()
optimizer.step()
b) Plot the training loss. Label each line with corresponding parameters (lr, momentum, and weight decay). Pick the set of parameters that
yields the best loss.
plt.xlabel('Iterations')
plt.ylabel('Training Loss')
plt.title('Training Loss vs Iterations')
plt.legend()
plt.show()
Q3. Training and Evaluation
a) Use the hyperparamters selected in the previous stage to train the model for 50 epochs. Track validation accuracy and save the model
whenever validation accuracy is higher.
In [66]: import torch
import torch.nn as nn
from torch.utils.data import DataLoader
import torch.optim as optim
import matplotlib.pyplot as plt
# Define hyperparameters
lr = 1e-3 # Learning rate
momentum = 0.9 # Momentum
weight_decay = 1e-4 # Weight decay
epochs = 50 # Number of epochs
# Training loop
for epoch in range(epochs):
cnn_model.train()
total_train_loss = 0.0
correct_train = 0
total_train = 0
for batch_idx, (data, target) in enumerate(train_loader):
optimizer.zero_grad()
output = cnn_model(data)
loss = loss_fn(output, target)
loss.backward()
optimizer.step()
total_train_loss += loss.item()
_, predicted_train = torch.max(output, 1)
correct_train += (predicted_train == target).sum().item()
total_train += target.size(0)
avg_train_loss = total_train_loss / len(train_loader)
train_losses.append(avg_train_loss)
train_accuracy = correct_train / total_train
# Validation loop
cnn_model.eval()
total_val_loss = 0.0
correct_val = 0
total_val = 0
with torch.no_grad():
for val_data, val_target in val_loader:
val_output = cnn_model(val_data)
val_loss = loss_fn(val_output, val_target)
total_val_loss += val_loss.item()
_, predicted_val = torch.max(val_output, 1)
correct_val += (predicted_val == val_target).sum().item()
total_val += val_target.size(0)
avg_val_loss = total_val_loss / len(val_loader)
val_losses.append(avg_val_loss)
val_accuracy = correct_val / total_val
val_accuracies.append(val_accuracy)
d) Use the loaded model to calculate loss and coefficient of determination (R for test data.
2
In [ ]: