EE24M306 - Programming Assignment - 3
EE24M306 - Programming Assignment - 3
ipynb - Colab
Programming assignment - 3
NAME:JWALA RAJANI
ROLL.NO:EE24M306
keyboard_arrow_down Question - 1
Use the perceptron model and verify whether it can classify the given dataset 1 and dataset 2. Choose the hyperparameters - initial
weights, no. of iterations, and learning rate to achieve the classification and report the same. Plot initial and final decision boundaries over
the data samples.
import numpy as np
import matplotlib.pyplot as plt
for _ in range(max_iterations):
for i in range(X_augmented.shape[0]):
# Perceptron update rule
prediction = np.sign(np.dot(X_augmented[i], weights))
error = y[i] - prediction
weights += learning_rate * error * X_augmented[i]
return weights
plt.figure(figsize=(8, 6))
plot_decision_boundary(X_train1, y_train1, np.zeros(X_train1.shape[1] + 1), title='Initial Decision Boundary (Dataset 1)')
plt.figure(figsize=(8, 6))
plot_decision_boundary(X_train1, y_train1, weights1, title='Final Decision Boundary (Dataset 1)')
https://colab.research.google.com/drive/117fmCnbOusTtHwL_eseuesaHT7W4EBsB#scrollTo=BYLcfi2lX9ST&printMode=true 2/31
18/04/2025, 15:41 EE24M306_Programming assignment - 3.ipynb - Colab
https://colab.research.google.com/drive/117fmCnbOusTtHwL_eseuesaHT7W4EBsB#scrollTo=BYLcfi2lX9ST&printMode=true 3/31
18/04/2025, 15:41 EE24M306_Programming assignment - 3.ipynb - Colab
keyboard_arrow_down Question - 2
Design a feed forward neural network (FNN) for a multi class classification task using the datasets and network design choices given
below.
import tensorflow as tf
from tensorflow.keras import layers, models
from tensorflow.keras.datasets import fashion_mnist
from tensorflow.keras.utils import to_categorical
from sklearn.model_selection import train_test_split
from sklearn.metrics import confusion_matrix
import pandas as pd
model = models.Sequential()
model.add(layers.Dense(32, activation='relu'))
model.add(layers.Dense(10, activation='softmax'))
https://colab.research.google.com/drive/117fmCnbOusTtHwL_eseuesaHT7W4EBsB#scrollTo=BYLcfi2lX9ST&printMode=true 4/31
18/04/2025, 15:41 EE24M306_Programming assignment - 3.ipynb - Colab
y
optimizer = tf.keras.optimizers.Adam(learning_rate=learning_rate)
model.compile(optimizer=optimizer, loss='categorical_crossentropy', metrics=['accuracy'])
history = model.fit(X_train, y_train, epochs=epochs, batch_size=batch_size)
test_loss, test_acc = model.evaluate(X_test_split, y_test_split)
print(f"Test accuracy: {test_acc:.4f}")
y_pred = model.predict(X_test_split)
y_pred_classes = tf.argmax(y_pred, axis=1)
y_test_classes = tf.argmax(y_test_split, axis=1)
cm = confusion_matrix(y_test_classes, y_pred_classes)
# Example usage
build_and_train_model_FashionMNIST(learning_rate=0.001, batch_size=128, epochs=10)
import os
import zipfile
import urllib.request
import numpy as np
import pandas as pd
from PIL import Image
from tqdm import tqdm
from sklearn.metrics import confusion_matrix
import tensorflow as tf
from tensorflow.keras import layers, models
from tensorflow.keras.utils import to_categorical
https://colab.research.google.com/drive/117fmCnbOusTtHwL_eseuesaHT7W4EBsB#scrollTo=BYLcfi2lX9ST&printMode=true 5/31
18/04/2025, 15:41 EE24M306_Programming assignment - 3.ipynb - Colab
if split == 'train':
train_dir = os.path.join(TINY_IMAGENET_PATH, 'train')
classes = sorted(os.listdir(train_dir))[:max_classes]
for idx, cls in enumerate(classes):
label_map[cls] = idx
image_dir = os.path.join(train_dir, cls, 'images')
for i, img_file in enumerate(os.listdir(image_dir)):
if i >= max_images_per_class:
break
img_path = os.path.join(image_dir, img_file)
img = Image.open(img_path).resize((64, 64)).convert('RGB')
data.append(np.array(img))
labels.append(idx)
valid_classes = sorted(set(annotations.values()))[:max_classes]
label_map = {cls: idx for idx, cls in enumerate(valid_classes)}
# CNN model
model = models.Sequential([
layers.Conv2D(32, (3, 3), activation='relu', input_shape=(64, 64, 3)),
layers.MaxPooling2D((2, 2)),
layers.Conv2D(64, (3, 3), activation='relu'),
layers.MaxPooling2D((2, 2)),
layers.Conv2D(128, (3, 3), activation='relu'),
layers.MaxPooling2D((2, 2)),
layers.Flatten(),
layers.Dense(256, activation='relu'),
layers.Dropout(0.3),
layers.Dense(10, activation='softmax')
])
model.compile(optimizer=tf.keras.optimizers.Adam(learning_rate=learning_rate),
loss='categorical_crossentropy',
metrics=['accuracy'])
y_pred = model.predict(X_val)
y_pred_classes = tf.argmax(y_pred, axis=1)
y_val_classes = tf.argmax(y_val, axis=1)
cm = confusion_matrix(y_val_classes, y_pred_classes)
cm_df = pd.DataFrame(cm)
cm_df.to_csv("confusion_matrix_TinyImageNet_10_classes_CNN.csv")
print("Confusion matrix saved to 'confusion_matrix_TinyImageNet_10_classes_CNN.csv'")
# Run it
build_and_train_tinyimagenet_cnn_10()
https://colab.research.google.com/drive/117fmCnbOusTtHwL_eseuesaHT7W4EBsB#scrollTo=BYLcfi2lX9ST&printMode=true 6/31
18/04/2025, 15:41 EE24M306_Programming assignment - 3.ipynb - Colab
NOTE:
The Tiny ImageNet dataset contains 200 classes, making full training computationally expensive and slow. To simplify the task and speed up
experimentation, we use only the first 10 classes. This reduces data loading time, training duration, and allows easier debugging.
A. What dimensions will you choose for each hidden layer? Why?
––128 neurons in the first hidden layer to capture fine-grained patterns such as edges, textures, and basic shapes from the flattened 784-
dimensional grayscale clothing images.
––64 neurons in the second layer to combine low-level features into more meaningful mid-level representations like parts of clothing items
(e.g., sleeves, collars).
––32 neurons in the third layer to abstract the information further and distill the essential patterns necessary for final class discrimination
among the 10 fashion categories.
Reason: The chosen dimensions (1024, 512, 256 neurons) are designed to handle the increased complexity of Tiny ImageNet images
(64×64×3). The first layer (1024 neurons) captures rich and detailed spatial features, the second layer (512 neurons) refines the extracted
patterns while managing model size, and the third layer (256 neurons) helps in abstraction and generalization before classification.
The FNN (Feed-Forward Neural Network) is initialized using a Sequential model in Keras. It starts with an InputLayer for 28×28 grayscale
images, followed by a Flatten layer to convert the 2D input into a 1D vector. Several Dense layers are then added to learn abstract
representations. This setup is simple yet effective for the relatively low-resolution and less complex Fashion MNIST images.
The FNN is initialized as a Sequential model in Keras. An InputLayer is used for 64×64×3 RGB images, followed by a Flatten layer to convert
the 3D image into a 1D vector. Dense layers are added to learn complex feature representations. Since Tiny ImageNet images have higher
https://colab.research.google.com/drive/117fmCnbOusTtHwL_eseuesaHT7W4EBsB#scrollTo=BYLcfi2lX9ST&printMode=true 7/31
18/04/2025, 15:41 EE24M306_Programming assignment - 3.ipynb - Colab
resolution and more visual variety, deeper and wider layers are required to effectively capture the data's complexity.
C. What are the choices of activation function? Which activation functions will you use for the hidden layers?
ReLU: Most commonly used in hidden layers. It helps in faster training and reduces vanishing gradients.
Sigmoid & Tanh: Less common in hidden layers due to vanishing gradients.
For hidden layers: ReLU is used because it speeds up training and reduces the vanishing gradient issue.
D. What is the learning rate used to train the FNN? How do you fix it?
The learning rate is 0.001, which is commonly used in deep learning. It controls how much the model's weights are updated during training.
In this case, it's fixed when initializing the Adam optimizer (tf.keras.optimizers.Ada (learning_rate=0.001)). If we change the learning rate to
0.0001, we might observe different results. A smaller learning rate (like 0.0001) will make the training process slower, as the weights are
updated more gradually. This may improve stability but could also increase training time and potentially lead to the model getting stuck in a
local minimum.
With a learning rate of 0.001, the model achieved a test accuracy of 0.8802 after 10 epochs.
With a learning rate of 0.0001, the model achieved a test accuracy of 0.8756 after 10 epochs.
This suggests that a learning rate of 0.001 led to faster convergence and better performance within the 10 epochs. A smaller learning rate
(0.0001) caused the model to update the weights more slowly, leading to a slightly lower accuracy after the same number of epochs.
E. What is the batch size? How does the batch size affect the performance of FNN?
The batch size is set to 128, as specified in the function call (batch_size=128). The batch size determines how many training samples are
processed before the model’s weights are updated.
Small batch sizes lead to more frequent updates, which can result in faster convergence but may also be noisier.
Large batch sizes result in more stable and accurate estimates of the gradient but may require more memory and lead to slower
convergence.
https://colab.research.google.com/drive/117fmCnbOusTtHwL_eseuesaHT7W4EBsB#scrollTo=BYLcfi2lX9ST&printMode=true 8/31
18/04/2025, 15:41 EE24M306_Programming assignment - 3.ipynb - Colab
Observation:batch_size 32,64,128
With a batch size of 32, the model achieved a test accuracy of 0.8802.
With a batch size of 64, the model achieved a test accuracy of 0.8799.
With a batch size of 128, the model achieved a test accuracy of 0.8803.
This suggests that increasing the batch size to 128 slightly improved the model's accuracy, reaching 0.8803.
The optimization technique used is Adam (Adaptive Moment Estimation), specified by tf.keras.optimizers.Adam. Adam is a popular optimizer
because it combines the benefits of two other extensions of stochastic gradient descent, AdaGrad and RMSProp, by maintaining both a
moving average of the gradient and the squared gradient.
G. Compute the evaluation metrics (i) accuracy (ii) precision (iii) recall using the confusion matrix, to assess the performance of the FNN
classification model. Explain the importance of each metric and the inference we draw.
Accuracy gives a quick snapshot but can be misleading when classes are imbalanced.
Precision focuses on minimizing false positives, making it crucial when false alarms are costly.
Recall emphasizes minimizing false negatives, important when missing positive instances is more critical.
https://colab.research.google.com/drive/117fmCnbOusTtHwL_eseuesaHT7W4EBsB#scrollTo=BYLcfi2lX9ST&printMode=true 9/31
18/04/2025, 15:41 EE24M306_Programming assignment - 3.ipynb - Colab
import pandas as pd
import numpy as np
from sklearn.metrics import precision_score, recall_score, accuracy_score
# Compute Accuracy
accuracy = np.trace(confusion_matrix) / np.sum(confusion_matrix)
print(f"Accuracy: {accuracy:.4f}")
precision = np.diagonal(confusion_matrix) / np.sum(confusion_matrix, axis=0)
print(f"Precision for each class: {precision}")
recall = np.diagonal(confusion_matrix) / np.sum(confusion_matrix, axis=1)
print(f"Recall for each class: {recall}")
precision_macro = np.mean(precision)
recall_macro = np.mean(recall)
Accuracy: 0.8799
Precision for each class: [0.79336735 0.99550562 0.83402001 0.88117712 0.72232143 0.96235955
0.78406709 0.95005945 0.98668211 0.92210526]
Recall for each class: [0.8790277 0.96566757 0.78678512 0.88708776 0.89146006 0.96074033
0.61954721 0.90847072 0.93369863 0.96635411]
Macro Precision: 0.8832
Macro Recall: 0.8799
import pandas as pd
import numpy as np
from sklearn.metrics import precision_score, recall_score, accuracy_score
precision_macro = np.mean(precision)
recall_macro = np.mean(recall)
Accuracy: 0.4100
Precision for each class: [0.71428571 0.65306122 0.26666667 0.26086957 0.28571429 0.4
0.28235294 0.66666667 0.53521127 0.33333333]
Recall for each class: [0.8 0.64 0.16 0.24 0.68 0.16 0.48 0.04 0.76 0.14]
Macro Precision: 0.4398
Macro Recall: 0.4100
H. Compute another metric other than the above mentioned 3 metrics using the confusion matrix to assess the performance of the FNN
classification model.
The F1-Score is particularly valuable when both false positives and false negatives carry significant weight, and when dealing with
imbalanced datasets.
import pandas as pd
import numpy as np
https://colab.research.google.com/drive/117fmCnbOusTtHwL_eseuesaHT7W4EBsB#scrollTo=BYLcfi2lX9ST&printMode=true 10/31
18/04/2025, 15:41 EE24M306_Programming assignment - 3.ipynb - Colab
confusion_matrix = cm_df.values
f1_score_macro = np.mean(f1_score)
print(f"Macro F1-Score: {f1_score_macro:.4f}")
F1-Score for each class: [0.8393866 0.97979518 0.80258398 0.88754915 0.79807435 0.95591518
0.63958692 0.93794276 0.96984786 0.95599225]
Macro F1-Score: 0.8767
import pandas as pd
import numpy as np
f1_score_macro = np.mean(f1_score)
print(f"Macro F1-Score: {f1_score_macro:.4f}")
F1-Score for each class: [0.75471698 0.64646465 0.2 0.25 0.40236686 0.22857143
0.35555556 0.0754717 0.62809917 0.1971831 ]
Macro F1-Score: 0.3738
I. For both the datasets, mention the input feature vector dimension and number of classes.
Input Feature Vector Dimension: 784 (each image is 28×28 pixels, flattened into a 1D vector). Number of Classes: 10 (each representing a
clothing category such as T-shirt, trouser, etc.).
Input Feature Vector Dimension: Each image is 64×64 pixels with 3 color channels (RGB), resulting in 64 × 64 × 3 = 12,288 features when
flattened into a 1D vector. Therefore, the input feature vector dimension is 12,288.
Number of Classes: We are using a subset of 10 classes from the Tiny ImageNet dataset for simplified and faster training.
Question - 3
Build a CNN model with LeNet, VGG architectures using library functions to perform classification task. Consider the two image
classification datasets i.e, MNIST digit classification and CIFAR10. Split the entire dataset into Train-validation-Test in the ratio
80%-10%-10%.
https://colab.research.google.com/drive/117fmCnbOusTtHwL_eseuesaHT7W4EBsB#scrollTo=BYLcfi2lX9ST&printMode=true 11/31
18/04/2025, 15:41 EE24M306_Programming assignment - 3.ipynb - Colab
import torchvision
# MNIST transforms
transform = transforms.Compose([
transforms.ToTensor(),
])
# Load dataset
full_dataset = datasets.MNIST(root='./data', train=True, download=True, transform=transform)
test_dataset = datasets.MNIST(root='./data', train=False, download=True, transform=transform)
# Train-validation-test split
train_size = int(0.8 * len(full_dataset))
val_size = int(0.1 * len(full_dataset))
partial_test_size = len(full_dataset) - train_size - val_size
train_data, val_data, _ = random_split(full_dataset, [train_size, val_size, partial_test_size])
test_data = test_dataset
for i in range(conv_layers):
self.conv_layers.append(nn.Conv2d(in_channels, num_filters[i], kernel_size, padding=1))
in_channels = num_filters[i]
https://colab.research.google.com/drive/117fmCnbOusTtHwL_eseuesaHT7W4EBsB#scrollTo=BYLcfi2lX9ST&printMode=true 12/31
18/04/2025, 15:41 EE24M306_Programming assignment - 3.ipynb - Colab
images, labels = images.to(device), labels.to(device)
optimizer.zero_grad()
out = model(images)
loss = criterion(out, labels)
loss.backward()
optimizer.step()
train_loss += loss.item()
model.eval()
val_loss = 0
with torch.no_grad():
for images, labels in val_loader:
images, labels = images.to(device), labels.to(device)
out = model(images)
val_loss += criterion(out, labels).item()
train_losses.append(train_loss / len(train_loader))
val_losses.append(val_loss / len(val_loader))
print(f"Epoch {epoch+1}: Train Loss = {train_losses[-1]}, Val Loss = {val_losses[-1]}")
# Plotting Loss
plt.plot(train_losses, label='Train Loss')
plt.plot(val_losses, label='Validation Loss')
plt.title("Loss Curves")
plt.xlabel("Epoch")
plt.ylabel("Loss")
plt.legend()
plt.show()
plot_filters(model.conv_layers[0])
https://colab.research.google.com/drive/117fmCnbOusTtHwL_eseuesaHT7W4EBsB#scrollTo=BYLcfi2lX9ST&printMode=true 13/31
18/04/2025, 15:41 EE24M306_Programming assignment - 3.ipynb - Colab
C. For a test sample image, display the feature maps produced by each layer
sample_img, _ = test_dataset[0]
visualize_feature_maps(sample_img)
def predict(img):
model.eval()
img = img.unsqueeze(0).to(device)
out = model(img)
probs = torch.softmax(out, dim=1).squeeze().detach().cpu().numpy()
return probs
True Label: 5
Mode: noise
Prediction Probabilities: [1.3102228e-08 7.8930451e-10 1.1436720e-10 7.2339708e-09 7.7014759e-09
9.9976403e-01 1.7280533e-04 1.7906793e-10 6.2076455e-05 1.1256362e-06]
Mode: blur
Prediction Probabilities: [4.4677698e-08 3.1434793e-09 4.1774778e-10 2.3429708e-08 1.5480332e-08
9.9988794e-01 8.9936933e-05 1.8822555e-09 2.0232228e-05 1.7909904e-06]
Mode: rotate
Prediction Probabilities: [1.5248754e-05 2.0697157e-06 1.0765802e-06 9.7494092e-07 2.6310647e-05
7.2298664e-01 2.7679503e-01 2.7336756e-07 7.5871023e-05 9.6558906e-05]
https://colab.research.google.com/drive/117fmCnbOusTtHwL_eseuesaHT7W4EBsB#scrollTo=BYLcfi2lX9ST&printMode=true 15/31
18/04/2025, 15:41 EE24M306_Programming assignment - 3.ipynb - Colab
F. Consider 10 random test samples in each dataset and visualize their corresponding predictions.
show_predictions()
G. Vary the number of convolutional layers, sub-sampling layers, also modify the hyperparameters and report the accuracies for the best
three cases.
import torch
import torch.nn as nn
import torch.nn.functional as F
import torch.optim as optim
from sklearn.metrics import confusion_matrix, accuracy_score
import seaborn as sns
https://colab.research.google.com/drive/117fmCnbOusTtHwL_eseuesaHT7W4EBsB#scrollTo=BYLcfi2lX9ST&printMode=true 16/31
18/04/2025, 15:41 EE24M306_Programming assignment - 3.ipynb - Colab
import matplotlib.pyplot as plt
for i in range(conv_layers):
self.conv_layers.append(nn.Conv2d(in_channels, num_filters[i], kernel_size, padding=1))
in_channels = num_filters[i]
with torch.no_grad():
dummy_input = torch.zeros(1, 1, 28, 28)
x = dummy_input
for conv_layer in self.conv_layers:
x = self.pool(F.relu(conv_layer(x)))
self.flattened_size = x.view(1, -1).size(1)
model = ModifiedLeNet().to(device)
criterion = nn.CrossEntropyLoss()
optimizer = optim.Adam(model.parameters(), lr=lr)
return model, criterion, optimizer
configs = [
{'conv_layers': 3, 'num_filters': [32, 64, 128], 'kernel_size': 3, 'pool_size': 2, 'fc_units': [512, 256], 'lr': 0.0005}
{'conv_layers': 2, 'num_filters': [16, 32], 'kernel_size': 5, 'pool_size': 2, 'fc_units': [256, 128], 'lr': 0.001},
{'conv_layers': 4, 'num_filters': [16, 32, 64, 128], 'kernel_size': 3, 'pool_size': 2, 'fc_units': [512, 256], 'lr': 0.0
]
best_accuracy = 0
best_model_id = -1
https://colab.research.google.com/drive/117fmCnbOusTtHwL_eseuesaHT7W4EBsB#scrollTo=BYLcfi2lX9ST&printMode=true 17/31
18/04/2025, 15:41 EE24M306_Programming assignment - 3.ipynb - Colab
model.eval()
val_loss = 0
with torch.no_grad():
for images, labels in val_loader:
images, labels = images.to(device), labels.to(device)
out = model(images)
val_loss += criterion(out, labels).item()
train_losses.append(train_loss / len(train_loader))
val_losses.append(val_loss / len(val_loader))
print(f"Epoch {epoch+1}: Train Loss = {train_losses[-1]:.4f}, Val Loss = {val_losses[-1]:.4f}")
✅
acc, cm = evaluate(model, test_loader)
print(f" Test Accuracy (Model {idx + 1}): {acc:.4f}")
sns.heatmap(cm, annot=True, fmt='d', cmap='Blues')
plt.title(f"Confusion Matrix (Model {idx+1})")
plt.xlabel("Predicted")
plt.ylabel("True")
plt.show()
https://colab.research.google.com/drive/117fmCnbOusTtHwL_eseuesaHT7W4EBsB#scrollTo=BYLcfi2lX9ST&printMode=true 18/31
18/04/2025, 15:41 EE24M306_Programming assignment - 3.ipynb - Colab
=== Training model 1 with config: {'conv_layers': 3, 'num_filters': [32, 64, 128], 'kernel_size': 3, 'pool_size': 2, 'fc
Epoch 1: Train Loss = 0.2727, Val Loss = 0.0822
Epoch 2: Train Loss = 0.0670, Val Loss = 0.0479
Epoch 3: Train Loss = 0.0429, Val Loss = 0.0441
Epoch 4: Train Loss = 0.0341, Val Loss = 0.0408
Epoch 5: Train Loss = 0.0258, Val Loss = 0.0506
Epoch 6: Train Loss = 0.0208, Val Loss = 0.0313
Epoch 7: Train Loss = 0.0170, Val Loss = 0.0391
Epoch 8: Train Loss = 0.0144, Val Loss = 0.0315
Epoch 9: Train Loss = 0.0123, Val Loss = 0.0337
✅
Epoch 10: Train Loss = 0.0117, Val Loss = 0.0464
Test Accuracy (Model 1): 0.9901
=== Training model 2 with config: {'conv_layers': 2, 'num_filters': [16, 32], 'kernel_size': 5, 'pool_size': 2, 'fc_unit
Epoch 1: Train Loss = 0.2410, Val Loss = 0.0846
Epoch 2: Train Loss = 0.0628, Val Loss = 0.0446
Epoch 3: Train Loss = 0.0427, Val Loss = 0.0418
Epoch 4: Train Loss = 0.0322, Val Loss = 0.0412
Epoch 5: Train Loss = 0.0267, Val Loss = 0.0474
Epoch 6: Train Loss = 0.0204, Val Loss = 0.0505
Epoch 7: Train Loss = 0.0161, Val Loss = 0.0384
Epoch 8: Train Loss = 0.0156, Val Loss = 0.0602
Epoch 9: Train Loss = 0.0131, Val Loss = 0.0395
✅
Epoch 10: Train Loss = 0.0114, Val Loss = 0.0374
Test Accuracy (Model 2): 0.9911
=== Training model 3 with config: {'conv_layers': 4, 'num_filters': [16, 32, 64, 128], 'kernel_size': 3, 'pool_size': 2,
Epoch 1: Train Loss = 0.7847, Val Loss = 0.2519
Epoch 2: Train Loss = 0.1826, Val Loss = 0.1414
Epoch 3: Train Loss = 0.1298, Val Loss = 0.1310
Epoch 4: Train Loss = 0.1064, Val Loss = 0.1115
Epoch 5: Train Loss = 0.0905, Val Loss = 0.0859
Epoch 6: Train Loss = 0.0793, Val Loss = 0.0731
Epoch 7: Train Loss = 0.0722, Val Loss = 0.0851
Epoch 8: Train Loss = 0.0640, Val Loss = 0.0685
Epoch 9: Train Loss = 0.0591, Val Loss = 0.0661
Epoch 10: Train Loss = 0.0518, Val Loss = 0.0709
https://colab.research.google.com/drive/117fmCnbOusTtHwL_eseuesaHT7W4EBsB#scrollTo=BYLcfi2lX9ST&printMode=true 19/31
18/04/2025, 15:41 EE24M306_Programming assignment - 3.ipynb - Colab
✅
Epoch 10: Train Loss 0.0518, Val Loss 0.0709
Test Accuracy (Model 3): 0.9807
keyboard_arrow_down Question - 3
CIFAR10.
import torch
import torch.nn as nn
import torch.nn.functional as F
import torch.optim as optim
from torchvision import datasets, transforms
from torch.utils.data import random_split, DataLoader
import matplotlib.pyplot as plt
import numpy as np
import random
import torchvision
# CIFAR-10 transforms
transform = transforms.Compose([
transforms.ToTensor(),
transforms.Normalize((0.4914, 0.4822, 0.4465),
(0.2470, 0.2435, 0.2616))
])
# Train-validation-test split
train_size = int(0.8 * len(full_dataset))
val_size = int(0.1 * len(full_dataset))
partial_test_size = len(full_dataset) - train_size - val_size
train_data, val_data, _ = random_split(full_dataset, [train_size, val_size, partial_test_size])
test_data = test_dataset
# Data loaders
train_loader = DataLoader(train_data, batch_size=64, shuffle=True)
val_loader = DataLoader(val_data, batch_size=64, shuffle=False)
test_loader = DataLoader(test_data, batch_size=64, shuffle=False)
https://colab.research.google.com/drive/117fmCnbOusTtHwL_eseuesaHT7W4EBsB#scrollTo=BYLcfi2lX9ST&printMode=true 20/31
18/04/2025, 15:41 EE24M306_Programming assignment - 3.ipynb - Colab
import torch
import torch.nn as nn
import torch.optim as optim
import torch.nn.functional as F
import matplotlib.pyplot as plt
model.eval()
val_loss = 0
with torch.no_grad():
for images, labels in val_loader:
images, labels = images.to(device), labels.to(device)
out = model(images)
val_loss += criterion(out, labels).item()
train_losses.append(train_loss / len(train_loader))
val_losses.append(val_loss / len(val_loader))
print(f"Epoch {epoch+1}: Train Loss = {train_losses[-1]}, Val Loss = {val_losses[-1]}")
# Plotting Loss
plt.plot(train_losses, label='Train Loss')
plt.plot(val_losses, label='Validation Loss')
plt.title("Loss Curves")
plt.xlabel("Epoch")
https://colab.research.google.com/drive/117fmCnbOusTtHwL_eseuesaHT7W4EBsB#scrollTo=BYLcfi2lX9ST&printMode=true 21/31
18/04/2025, 15:41 EE24M306_Programming assignment - 3.ipynb - Colab
plt.ylabel("Loss")
plt.legend()
plt.show()
for i, f in enumerate(filters):
if f.shape[0] == 3:
f = f.mean(dim=0)
axes[i].imshow(f.detach().numpy(), cmap='gray')
axes[i].axis('off')
https://colab.research.google.com/drive/117fmCnbOusTtHwL_eseuesaHT7W4EBsB#scrollTo=BYLcfi2lX9ST&printMode=true 22/31
18/04/2025, 15:41 EE24M306_Programming assignment - 3.ipynb - Colab
C. For a test sample image, display the feature maps produced by each layer
import torch
import torch.nn.functional as F
import matplotlib.pyplot as plt
with torch.no_grad():
x = F.relu(model.conv_layers[0](img))
x = model.pool(x)
for i in range(x.shape[1]):
axs[i].imshow(x[0, i].cpu(), cmap='gray')
axs[i].axis('off')
sample_img, _ = test_dataset[0]
visualize_feature_maps(sample_img)
import cv2
import numpy as np
import torch
import torch.nn.functional as F
https://colab.research.google.com/drive/117fmCnbOusTtHwL_eseuesaHT7W4EBsB#scrollTo=BYLcfi2lX9ST&printMode=true 23/31
18/04/2025, 15:41 EE24M306_Programming assignment - 3.ipynb - Colab
from torchvision import transforms
if mode == "noise":
# Add Gaussian noise to a small region of the image
img[10:18, 10:18, :] += 0.4 * np.random.randn(8, 8, 3)
elif mode == "blur":
# Apply Gaussian blur to a region of the image
img[10:18, 10:18, :] = cv2.GaussianBlur(img[10:18, 10:18, :], (3, 3), 0)
elif mode == "rotate":
True Label: 3
Original Image Prediction Probabilities: [1.6800972e-07 6.1611257e-07 8.4793493e-05 9.9465758e-01 1.2911787e-03
2.8534168e-03 1.0606776e-03 5.1260820e-05 7.4985543e-08 1.9104161e-07]
Mode: noise
Prediction Probabilities: [1.7982727e-01 1.7654325e-05 1.0244109e-01 1.3019058e-02 5.8725649e-01
2.9313546e-02 1.1017997e-03 1.3212665e-04 8.3206937e-02 3.6840788e-03]
Mode: blur
Prediction Probabilities: [1.80031568e-01 1.76791855e-05 1.02136604e-01 1.30106555e-02
5.87525189e-01 2.92738657e-02 1.09828799e-03 1.32296831e-04
8.30881745e-02 3.68571328e-03]
Mode: rotate
Prediction Probabilities: [1.8149871e-01 1.7627286e-05 1.0185424e-01 1.2813091e-02 5.8555746e-01
2.9116735e-02 1.0882209e-03 1.3150575e-04 8.4206358e-02 3.7160548e-03]
https://colab.research.google.com/drive/117fmCnbOusTtHwL_eseuesaHT7W4EBsB#scrollTo=BYLcfi2lX9ST&printMode=true 24/31
18/04/2025, 15:41 EE24M306_Programming assignment - 3.ipynb - Colab
# Compute accuracy and confusion matrix
acc = accuracy_score(all_labels, all_preds)
cm = confusion_matrix(all_labels, all_preds)
return acc, cm
F. Consider 10 random test samples in each dataset and visualize their corresponding predictions.
with torch.no_grad():
pred = torch.argmax(model(img_input)).item()
axs[i//5, i%5].imshow(img_np)
axs[i//5, i%5].set_title(f"True: {label}, Pred: {pred}")
axs[i//5, i%5].axis('off')
https://colab.research.google.com/drive/117fmCnbOusTtHwL_eseuesaHT7W4EBsB#scrollTo=BYLcfi2lX9ST&printMode=true 25/31
18/04/2025, 15:41 EE24M306_Programming assignment - 3.ipynb - Colab
WARNING:matplotlib.image:Clipping input data to the valid range for imshow with RGB data ([0..1] for floats or [0..255]
WARNING:matplotlib.image:Clipping input data to the valid range for imshow with RGB data ([0..1] for floats or [0..255]
WARNING:matplotlib.image:Clipping input data to the valid range for imshow with RGB data ([0..1] for floats or [0..255]
WARNING:matplotlib.image:Clipping input data to the valid range for imshow with RGB data ([0..1] for floats or [0..255]
WARNING:matplotlib.image:Clipping input data to the valid range for imshow with RGB data ([0..1] for floats or [0..255]
WARNING:matplotlib.image:Clipping input data to the valid range for imshow with RGB data ([0..1] for floats or [0..255]
WARNING:matplotlib.image:Clipping input data to the valid range for imshow with RGB data ([0..1] for floats or [0..255]
WARNING:matplotlib.image:Clipping input data to the valid range for imshow with RGB data ([0..1] for floats or [0..255]
WARNING:matplotlib.image:Clipping input data to the valid range for imshow with RGB data ([0..1] for floats or [0..255]
WARNING:matplotlib.image:Clipping input data to the valid range for imshow with RGB data ([0..1] for floats or [0..255]
G. Vary the number of convolutional layers, sub-sampling layers, also modify the hyperparameters and report the accuracies for the best
three cases.
import torch
import torch.nn as nn
import torch.nn.functional as F
import torch.optim as optim
import matplotlib.pyplot as plt
import seaborn as sns
from sklearn.metrics import confusion_matrix, accuracy_score
import random
for i in range(conv_layers):
self.conv_layers.append(nn.Conv2d(in_channels, num_filters[i], kernel_size, padding=1))
in_channels = num_filters[i]
https://colab.research.google.com/drive/117fmCnbOusTtHwL_eseuesaHT7W4EBsB#scrollTo=BYLcfi2lX9ST&printMode=true 26/31
18/04/2025, 15:41 EE24M306_Programming assignment - 3.ipynb - Colab
for conv_layer in self.conv_layers:
x = self.pool(F.relu(conv_layer(x)))
x = x.view(-1, self.flattened_size)
x = F.relu(self.fc1(x))
x = F.relu(self.fc2(x))
return self.fc3(x)
model = ModifiedLeNet().to(device)
criterion = nn.CrossEntropyLoss()
optimizer = optim.Adam(model.parameters(), lr=lr)
return model, criterion, optimizer
configs = [
{'conv_layers': 3, 'num_filters': [32, 64, 128], 'kernel_size': 3, 'pool_size': 2, 'fc_units': [512, 256], 'lr': 0.0005}
{'conv_layers': 2, 'num_filters': [16, 32], 'kernel_size': 5, 'pool_size': 2, 'fc_units': [256, 128], 'lr': 0.001},
{'conv_layers': 4, 'num_filters': [16, 32, 64, 128], 'kernel_size': 3, 'pool_size': 2, 'fc_units': [512, 256], 'lr': 0.0
]
best_accuracy = 0
best_model_id = -1
model.eval()
val_loss = 0
with torch.no_grad():
for images, labels in val_loader:
images, labels = images.to(device), labels.to(device)
out = model(images)
val_loss += criterion(out, labels).item()
train_losses.append(train_loss / len(train_loader))
val_losses.append(val_loss / len(val_loader))
print(f"Epoch {epoch+1}: Train Loss = {train_losses[-1]:.4f}, Val Loss = {val_losses[-1]:.4f}")
✅
acc, cm = evaluate(model, test_loader)
print(f" Test Accuracy (Model {idx + 1}): {acc:.4f}")
sns.heatmap(cm, annot=True, fmt='d', cmap='Blues')
plt.title(f"Confusion Matrix (Model {idx+1})")
plt.xlabel("Predicted")
plt.ylabel("True")
plt.show()
https://colab.research.google.com/drive/117fmCnbOusTtHwL_eseuesaHT7W4EBsB#scrollTo=BYLcfi2lX9ST&printMode=true 27/31
18/04/2025, 15:41 EE24M306_Programming assignment - 3.ipynb - Colab
print(f"\n 🏆 Best model is Model {best_model_id} with accuracy: {best_accuracy:.4f}")
https://colab.research.google.com/drive/117fmCnbOusTtHwL_eseuesaHT7W4EBsB#scrollTo=BYLcfi2lX9ST&printMode=true 28/31
18/04/2025, 15:41 EE24M306_Programming assignment - 3.ipynb - Colab
=== Training model 1 with config: {'conv_layers': 3, 'num_filters': [32, 64, 128], 'kernel_size': 3, 'pool_size': 2, 'fc
Epoch 1: Train Loss = 1.5049, Val Loss = 1.2024
Epoch 2: Train Loss = 1.0885, Val Loss = 0.9798
Epoch 3: Train Loss = 0.8811, Val Loss = 0.8805
Epoch 4: Train Loss = 0.7294, Val Loss = 0.8168
Epoch 5: Train Loss = 0.6098, Val Loss = 0.7791
Epoch 6: Train Loss = 0.5063, Val Loss = 0.7410
Epoch 7: Train Loss = 0.4013, Val Loss = 0.8177
Epoch 8: Train Loss = 0.3080, Val Loss = 0.8581
Epoch 9: Train Loss = 0.2239, Val Loss = 0.9416
✅
Epoch 10: Train Loss = 0.1572, Val Loss = 1.0282
Test Accuracy (Model 1): 0.7450
=== Training model 2 with config: {'conv_layers': 2, 'num_filters': [16, 32], 'kernel_size': 5, 'pool_size': 2, 'fc_unit
Epoch 1: Train Loss = 1.5156, Val Loss = 1.2191
Epoch 2: Train Loss = 1.1273, Val Loss = 1.0878
Epoch 3: Train Loss = 0.9578, Val Loss = 0.9795
Epoch 4: Train Loss = 0.8278, Val Loss = 0.9674
Epoch 5: Train Loss = 0.7187, Val Loss = 0.9315
Epoch 6: Train Loss = 0.6231, Val Loss = 0.9855
Epoch 7: Train Loss = 0.5389, Val Loss = 0.9852
Epoch 8: Train Loss = 0.4502, Val Loss = 1.0727
Epoch 9: Train Loss = 0.3815, Val Loss = 1.1674
✅
Epoch 10: Train Loss = 0.3162, Val Loss = 1.2403
Test Accuracy (Model 2): 0.6775
=== Training model 3 with config: {'conv_layers': 4, 'num_filters': [16, 32, 64, 128], 'kernel_size': 3, 'pool_size': 2,
Epoch 1: Train Loss = 1.8493, Val Loss = 1.6419
Epoch 2: Train Loss = 1.5716, Val Loss = 1.5152
Epoch 3: Train Loss = 1.4698, Val Loss = 1.4160
Epoch 4: Train Loss = 1.3935, Val Loss = 1.3476
Epoch 5: Train Loss = 1.3230, Val Loss = 1.3299
Epoch 6: Train Loss = 1.2658, Val Loss = 1.2370
Epoch 7: Train Loss = 1.2152, Val Loss = 1.2022
Epoch 8: Train Loss = 1.1727, Val Loss = 1.1651
Epoch 9: Train Loss = 1.1280, Val Loss = 1.1706
Epoch 10: Train Loss = 1.0877, Val Loss = 1.1514
https://colab.research.google.com/drive/117fmCnbOusTtHwL_eseuesaHT7W4EBsB#scrollTo=BYLcfi2lX9ST&printMode=true 29/31
18/04/2025, 15:41 EE24M306_Programming assignment - 3.ipynb - Colab
✅
Epoch 10: Train Loss 1.0877, Val Loss 1.1514
Test Accuracy (Model 3): 0.5906
import tensorflow as tf
from tensorflow.keras import layers, models
from tensorflow.keras.datasets import mnist
from tensorflow.keras.utils import to_categorical
from sklearn.model_selection import train_test_split
from sklearn.metrics import confusion_matrix
import pandas as pd
import matplotlib.pyplot as plt
model = models.Sequential()
model.add(layers.InputLayer(input_shape=(784,)))
model.add(layers.Dense(512, activation='relu'))
model.add(layers.Dense(256, activation='relu'))
model.add(layers.Dense(128, activation='relu'))
model.add(layers.Dense(10, activation='softmax'))
optimizer = tf.keras.optimizers.Adam(learning_rate=learning_rate)
model.compile(optimizer=optimizer, loss='categorical_crossentropy', metrics=['accuracy'])
history = model.fit(X_train, y_train, epochs=epochs, batch_size=batch_size, validation_data=(X_test, y_test))
https://colab.research.google.com/drive/117fmCnbOusTtHwL_eseuesaHT7W4EBsB#scrollTo=BYLcfi2lX9ST&printMode=true 30/31
18/04/2025, 15:41 EE24M306_Programming assignment - 3.ipynb - Colab
# Plot training and testing loss curves
plt.figure(figsize=(10, 6))
plt.plot(history.history['loss'], label='Training Loss')
plt.plot(history.history['val_loss'], label='Testing Loss')
plt.title('Training and Testing Loss Curves')
plt.xlabel('Epochs')
plt.ylabel('Loss')
plt.legend()
plt.grid(True)
plt.show()
https://colab.research.google.com/drive/117fmCnbOusTtHwL_eseuesaHT7W4EBsB#scrollTo=BYLcfi2lX9ST&printMode=true 31/31