Open In Colab

Deep Learning Models: A collection of various deep learning architectures, models, & their implementations (PyTorch or TensorFlow) in Jupyter Notebooks.

  • Author: Chizoba Obasi
  • Github Repo: https://github.com/chizkidd/deep-learning-models
InĀ [1]:
!pip install watermark
Requirement already satisfied: watermark in /usr/local/lib/python3.12/dist-packages (2.5.1)
Requirement already satisfied: ipython>=6.0 in /usr/local/lib/python3.12/dist-packages (from watermark) (7.34.0)
Requirement already satisfied: importlib-metadata>=1.4 in /usr/local/lib/python3.12/dist-packages (from watermark) (8.7.0)
Requirement already satisfied: setuptools in /usr/local/lib/python3.12/dist-packages (from watermark) (75.2.0)
Requirement already satisfied: zipp>=3.20 in /usr/local/lib/python3.12/dist-packages (from importlib-metadata>=1.4->watermark) (3.23.0)
Requirement already satisfied: jedi>=0.16 in /usr/local/lib/python3.12/dist-packages (from ipython>=6.0->watermark) (0.19.2)
Requirement already satisfied: decorator in /usr/local/lib/python3.12/dist-packages (from ipython>=6.0->watermark) (4.4.2)
Requirement already satisfied: pickleshare in /usr/local/lib/python3.12/dist-packages (from ipython>=6.0->watermark) (0.7.5)
Requirement already satisfied: traitlets>=4.2 in /usr/local/lib/python3.12/dist-packages (from ipython>=6.0->watermark) (5.7.1)
Requirement already satisfied: prompt-toolkit!=3.0.0,!=3.0.1,<3.1.0,>=2.0.0 in /usr/local/lib/python3.12/dist-packages (from ipython>=6.0->watermark) (3.0.52)
Requirement already satisfied: pygments in /usr/local/lib/python3.12/dist-packages (from ipython>=6.0->watermark) (2.19.2)
Requirement already satisfied: backcall in /usr/local/lib/python3.12/dist-packages (from ipython>=6.0->watermark) (0.2.0)
Requirement already satisfied: matplotlib-inline in /usr/local/lib/python3.12/dist-packages (from ipython>=6.0->watermark) (0.2.1)
Requirement already satisfied: pexpect>4.3 in /usr/local/lib/python3.12/dist-packages (from ipython>=6.0->watermark) (4.9.0)
Requirement already satisfied: parso<0.9.0,>=0.8.4 in /usr/local/lib/python3.12/dist-packages (from jedi>=0.16->ipython>=6.0->watermark) (0.8.5)
Requirement already satisfied: ptyprocess>=0.5 in /usr/local/lib/python3.12/dist-packages (from pexpect>4.3->ipython>=6.0->watermark) (0.7.0)
Requirement already satisfied: wcwidth in /usr/local/lib/python3.12/dist-packages (from prompt-toolkit!=3.0.0,!=3.0.1,<3.1.0,>=2.0.0->ipython>=6.0->watermark) (0.2.14)
InĀ [2]:
!pip install torchinfo
Requirement already satisfied: torchinfo in /usr/local/lib/python3.12/dist-packages (1.8.0)
InĀ [3]:
%load_ext watermark
# %reload_ext watermark
%watermark -a 'Chizoba Obasi' -v -p torch
Author: Chizoba Obasi

Python implementation: CPython
Python version       : 3.12.12
IPython version      : 7.34.0

torch: 2.9.0+cu126

AlexNet Classifier on CIFAR-10¶

Network Architecture:

AlexNet

Source

REFERENCES:

  1. Krizhevsky, Alex, Ilya Sutskever, and Geoffrey E. Hinton. "ImageNet Classification with Deep Convolutional Neural Networks." Advances in Neural Information Processing Systems (NIPS), 2012.
  2. Johnson, J. (2022, February 2). Lecture 8: CNN Architectures [PowerPoint Slides]. University of Michigan EECS 498/598: Deep Learning for Computer Vision. pp 26-51. https://web.eecs.umich.edu/~justincj/slides/eecs498/WI2022/598_WI2022_lecture08.pdf
InĀ [4]:
import torch
import torch.nn as nn
import torch.nn.functional as F
import torch.optim as optim
from torch.utils.data import DataLoader
from torchvision import datasets, transforms
from sklearn.model_selection import train_test_split

from torchinfo import summary

import matplotlib.image as mpimg
import matplotlib.pyplot as plt
%matplotlib inline

import pandas as pd
import numpy as np
import math
import time
import os
import random

if torch.cuda.is_available():
    torch.backends.cudnn.deterministic = True
InĀ [5]:
def set_all_seeds(seed):
    os.environ["PL_GLOBAL_SEED"] = str(seed)
    random.seed(seed)
    np.random.seed(seed)
    torch.manual_seed(seed)
    torch.cuda.manual_seed_all(seed)
InĀ [6]:
def set_deterministic():
    if torch.cuda.is_available():
        torch.backends.cudnn.benchmark = False
        torch.backends.cudnn.deterministic = True
    torch.set_deterministic(True)
InĀ [7]:
# Check if GPU is available and set the device
if torch.cuda.is_available():
    num_gpus = torch.cuda.device_count()
    print("Num GPUs Available: ", num_gpus)
    for i in range(num_gpus):
        gpu_name = torch.cuda.get_device_name(i)
        print(f"GPU {i}: {gpu_name}")
else:
    print("No GPU available.")
Num GPUs Available:  1
GPU 0: Tesla T4

0. Model Hyperparameters¶


InĀ [8]:
##########################
### SETTINGS
##########################

# Hyperparameters
RANDOM_SEED = 123
BATCH_SIZE = 128 #256
LEARNING_RATE = 0.001
NUM_EPOCHS = 50
INPUT_SIZE = 32 # CIFAR-10 is 32x32
NUM_CLASSES = 10

# Set device
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
print(device)
cuda
InĀ [9]:
set_all_seeds(RANDOM_SEED)

1. Data Preparation & Loading¶


InĀ [10]:
# Mean and Std Dev for CIFAR-10 (3 channels)
CIFAR_MEAN = (0.4914, 0.4822, 0.4465)
CIFAR_STD = (0.2471, 0.2435, 0.2616)

train_transforms = transforms.Compose([
    transforms.RandomRotation(15),
    transforms.RandomCrop(32, padding=4, padding_mode='reflect'),
    transforms.RandomHorizontalFlip(),
    transforms.ToTensor(),
    transforms.Normalize(CIFAR_MEAN, CIFAR_STD)
])

test_transforms = transforms.Compose([
    transforms.ToTensor(),
    transforms.Normalize(CIFAR_MEAN, CIFAR_STD)
])

# Load Datasets
train_dataset = datasets.CIFAR10(root='./data', train=True, download=True, transform=train_transforms)
test_dataset = datasets.CIFAR10(root='./data', train=False, download=True, transform=test_transforms)

# Split training set into training and validation sets
train_size = int(0.9 * len(train_dataset))
val_size = len(train_dataset) - train_size
train_subset, val_subset = torch.utils.data.random_split(train_dataset, [train_size, val_size])

# Create DataLoaders
train_loader = DataLoader(train_subset, batch_size=BATCH_SIZE, shuffle=True)
val_loader = DataLoader(val_subset, batch_size=BATCH_SIZE, shuffle=False)
test_loader = DataLoader(test_dataset, batch_size=BATCH_SIZE, shuffle=False)

2. Model Creation¶


InĀ [11]:
class AlexNet(nn.Module):
    def __init__(self, num_classes=10):
        super(AlexNet, self).__init__()

        self.features = nn.Sequential(
            # Layer 1: Smaller kernel (3x3) and stride (1) for 32x32 images
            nn.Conv2d(3, 64, kernel_size=3, stride=1, padding=1),
            nn.BatchNorm2d(64),
            nn.ReLU(inplace=True),
            nn.MaxPool2d(kernel_size=2, stride=2), # 32 -> 16

            # Layer 2
            nn.Conv2d(64, 192, kernel_size=3, padding=1),
            nn.BatchNorm2d(192),
            nn.ReLU(inplace=True),
            nn.MaxPool2d(kernel_size=2, stride=2), # 16 -> 8

            # Layer 3
            nn.Conv2d(192, 384, kernel_size=3, padding=1),
            nn.BatchNorm2d(384),
            nn.ReLU(inplace=True),

            # Layer 4
            nn.Conv2d(384, 256, kernel_size=3, padding=1),
            nn.BatchNorm2d(256),
            nn.ReLU(inplace=True),

            # Layer 5
            nn.Conv2d(256, 256, kernel_size=3, padding=1),
            nn.BatchNorm2d(256),
            nn.ReLU(inplace=True),
            nn.MaxPool2d(kernel_size=2, stride=2)  # 8 -> 4
        )

        self.classifier = nn.Sequential(
            nn.Dropout(0.5),
            # After 3 MaxPools (32/2/2/2), spatial size is 4x4
            nn.Linear(256 * 4 * 4, 4096),
            nn.ReLU(inplace=True),
            nn.Dropout(0.5),
            nn.Linear(4096, 4096),
            nn.ReLU(inplace=True),
            nn.Linear(4096, num_classes)
        )

    def forward(self, x):
        x = self.features(x)
        x = torch.flatten(x, 1)
        x = self.classifier(x)
        return x
InĀ [12]:
torch.manual_seed(RANDOM_SEED)
model = AlexNet(num_classes=NUM_CLASSES).to(device)
InĀ [13]:
# Model parameter details
summary(model,
        input_size=(BATCH_SIZE, 3, INPUT_SIZE, INPUT_SIZE),
        # verbose=1,
        col_names=["input_size", "output_size", "num_params", "kernel_size", "mult_adds"]
       )
Out[13]:
=====================================================================================================================================================================
Layer (type:depth-idx)                   Input Shape               Output Shape              Param #                   Kernel Shape              Mult-Adds
=====================================================================================================================================================================
AlexNet                                  [128, 3, 32, 32]          [128, 10]                 --                        --                        --
ā”œā”€Sequential: 1-1                        [128, 3, 32, 32]          [128, 256, 4, 4]          --                        --                        --
│    └─Conv2d: 2-1                       [128, 3, 32, 32]          [128, 64, 32, 32]         1,792                     [3, 3]                    234,881,024
│    └─BatchNorm2d: 2-2                  [128, 64, 32, 32]         [128, 64, 32, 32]         128                       --                        16,384
│    └─ReLU: 2-3                         [128, 64, 32, 32]         [128, 64, 32, 32]         --                        --                        --
│    └─MaxPool2d: 2-4                    [128, 64, 32, 32]         [128, 64, 16, 16]         --                        2                         --
│    └─Conv2d: 2-5                       [128, 64, 16, 16]         [128, 192, 16, 16]        110,784                   [3, 3]                    3,630,170,112
│    └─BatchNorm2d: 2-6                  [128, 192, 16, 16]        [128, 192, 16, 16]        384                       --                        49,152
│    └─ReLU: 2-7                         [128, 192, 16, 16]        [128, 192, 16, 16]        --                        --                        --
│    └─MaxPool2d: 2-8                    [128, 192, 16, 16]        [128, 192, 8, 8]          --                        2                         --
│    └─Conv2d: 2-9                       [128, 192, 8, 8]          [128, 384, 8, 8]          663,936                   [3, 3]                    5,438,963,712
│    └─BatchNorm2d: 2-10                 [128, 384, 8, 8]          [128, 384, 8, 8]          768                       --                        98,304
│    └─ReLU: 2-11                        [128, 384, 8, 8]          [128, 384, 8, 8]          --                        --                        --
│    └─Conv2d: 2-12                      [128, 384, 8, 8]          [128, 256, 8, 8]          884,992                   [3, 3]                    7,249,854,464
│    └─BatchNorm2d: 2-13                 [128, 256, 8, 8]          [128, 256, 8, 8]          512                       --                        65,536
│    └─ReLU: 2-14                        [128, 256, 8, 8]          [128, 256, 8, 8]          --                        --                        --
│    └─Conv2d: 2-15                      [128, 256, 8, 8]          [128, 256, 8, 8]          590,080                   [3, 3]                    4,833,935,360
│    └─BatchNorm2d: 2-16                 [128, 256, 8, 8]          [128, 256, 8, 8]          512                       --                        65,536
│    └─ReLU: 2-17                        [128, 256, 8, 8]          [128, 256, 8, 8]          --                        --                        --
│    └─MaxPool2d: 2-18                   [128, 256, 8, 8]          [128, 256, 4, 4]          --                        2                         --
ā”œā”€Sequential: 1-2                        [128, 4096]               [128, 10]                 --                        --                        --
│    └─Dropout: 2-19                     [128, 4096]               [128, 4096]               --                        --                        --
│    └─Linear: 2-20                      [128, 4096]               [128, 4096]               16,781,312                --                        2,148,007,936
│    └─ReLU: 2-21                        [128, 4096]               [128, 4096]               --                        --                        --
│    └─Dropout: 2-22                     [128, 4096]               [128, 4096]               --                        --                        --
│    └─Linear: 2-23                      [128, 4096]               [128, 4096]               16,781,312                --                        2,148,007,936
│    └─ReLU: 2-24                        [128, 4096]               [128, 4096]               --                        --                        --
│    └─Linear: 2-25                      [128, 4096]               [128, 10]                 40,970                    --                        5,244,160
=====================================================================================================================================================================
Total params: 35,857,482
Trainable params: 35,857,482
Non-trainable params: 0
Total mult-adds (Units.GIGABYTES): 25.69
=====================================================================================================================================================================
Input size (MB): 1.57
Forward/backward pass size (MB): 360.72
Params size (MB): 143.43
Estimated Total Size (MB): 505.72
=====================================================================================================================================================================

3. Model Training, Testing & Evaluation¶


InĀ [14]:
criterion = nn.CrossEntropyLoss()
optimizer = optim.Adam(model.parameters(), lr=LEARNING_RATE)
scheduler = optim.lr_scheduler.ReduceLROnPlateau(optimizer, mode='min', factor=0.1, patience=5)
scheduler = optim.lr_scheduler.ReduceLROnPlateau(optimizer, mode='min', factor=0.2, patience=2)
InĀ [15]:
# Function to calculate accuracy
def calculate_accuracy(loader):
    model.eval()
    correct = 0
    total = 0
    with torch.no_grad():
        for inputs, labels in loader:
            inputs, labels = inputs.to(device), labels.to(device)
            outputs = model(inputs)
            _, predicted = torch.max(outputs.data, 1)
            total += labels.size(0)
            correct += (predicted == labels).sum().item()
    return 100 * correct / total

# Training Loop
start_time = time.time()
history = {'train_loss': [], 'val_loss': [], 'train_acc': [], 'val_acc': [], 'lrs': []}

print(f"Starting training on {device}...")

for epoch in range(NUM_EPOCHS):
    model.train()
    running_loss = 0.0
    for i, (inputs, labels) in enumerate(train_loader):
        inputs, labels = inputs.to(device), labels.to(device)

        optimizer.zero_grad()
        outputs = model(inputs)
        loss = criterion(outputs, labels)
        loss.backward()
        optimizer.step()

        running_loss += loss.item() * inputs.size(0)

    train_loss = running_loss / len(train_subset)
    train_acc = calculate_accuracy(train_loader)

    # Calculate validation loss and accuracy
    model.eval()
    val_loss = 0.0
    with torch.no_grad():
        for inputs, labels in val_loader:
            inputs, labels = inputs.to(device), labels.to(device)
            outputs = model(inputs)
            loss = criterion(outputs, labels)
            val_loss += loss.item() * inputs.size(0)

    val_loss /= len(val_subset)
    val_acc = calculate_accuracy(val_loader)

    scheduler.step(val_loss)
    current_lr = optimizer.param_groups[0]['lr']

    history['train_loss'].append(train_loss)
    history['val_loss'].append(val_loss)
    history['train_acc'].append(train_acc)
    history['val_acc'].append(val_acc)
    history['lrs'].append(current_lr)

    print(f'Epoch {epoch + 1}/{NUM_EPOCHS} | '
          f'Train Loss: {train_loss:.5f}, '
          f'Train Accuracy: {train_acc:.2f}% | '
          f'Val Loss: {val_loss:.5f}, '
          f'Val Accuracy: {val_acc:.2f}% | '
          f'Learning Rate: {current_lr:.8f}')

print('\nTotal Training Time: %.2f min' % ((time.time() - start_time)/60))

# Final Evaluation
test_accuracy = calculate_accuracy(test_loader)
print(f'\nTest Accuracy: {test_accuracy:.2f}%')
Starting training on cuda...
Epoch 1/50 | Train Loss: 1.92219, Train Accuracy: 41.64% | Val Loss: 1.60936, Val Accuracy: 40.52% | Learning Rate: 0.00100000
Epoch 2/50 | Train Loss: 1.50805, Train Accuracy: 48.07% | Val Loss: 1.47960, Val Accuracy: 47.94% | Learning Rate: 0.00100000
Epoch 3/50 | Train Loss: 1.34305, Train Accuracy: 57.97% | Val Loss: 1.26625, Val Accuracy: 56.72% | Learning Rate: 0.00100000
Epoch 4/50 | Train Loss: 1.20994, Train Accuracy: 59.37% | Val Loss: 1.20361, Val Accuracy: 58.26% | Learning Rate: 0.00100000
Epoch 5/50 | Train Loss: 1.09782, Train Accuracy: 60.37% | Val Loss: 1.21342, Val Accuracy: 58.80% | Learning Rate: 0.00100000
Epoch 6/50 | Train Loss: 1.01083, Train Accuracy: 66.57% | Val Loss: 1.05796, Val Accuracy: 64.46% | Learning Rate: 0.00100000
Epoch 7/50 | Train Loss: 0.94668, Train Accuracy: 66.62% | Val Loss: 1.04106, Val Accuracy: 64.36% | Learning Rate: 0.00100000
Epoch 8/50 | Train Loss: 0.88794, Train Accuracy: 71.11% | Val Loss: 0.95675, Val Accuracy: 69.12% | Learning Rate: 0.00100000
Epoch 9/50 | Train Loss: 0.84568, Train Accuracy: 74.78% | Val Loss: 0.83785, Val Accuracy: 72.50% | Learning Rate: 0.00100000
Epoch 10/50 | Train Loss: 0.78362, Train Accuracy: 71.78% | Val Loss: 0.90728, Val Accuracy: 70.42% | Learning Rate: 0.00100000
Epoch 11/50 | Train Loss: 0.74492, Train Accuracy: 74.01% | Val Loss: 0.83622, Val Accuracy: 71.92% | Learning Rate: 0.00100000
Epoch 12/50 | Train Loss: 0.71585, Train Accuracy: 77.91% | Val Loss: 0.81024, Val Accuracy: 75.04% | Learning Rate: 0.00100000
Epoch 13/50 | Train Loss: 0.67643, Train Accuracy: 78.39% | Val Loss: 0.76244, Val Accuracy: 74.76% | Learning Rate: 0.00100000
Epoch 14/50 | Train Loss: 0.64610, Train Accuracy: 78.82% | Val Loss: 0.73822, Val Accuracy: 76.20% | Learning Rate: 0.00100000
Epoch 15/50 | Train Loss: 0.60984, Train Accuracy: 79.70% | Val Loss: 0.71437, Val Accuracy: 76.74% | Learning Rate: 0.00100000
Epoch 16/50 | Train Loss: 0.57914, Train Accuracy: 81.32% | Val Loss: 0.66627, Val Accuracy: 77.36% | Learning Rate: 0.00100000
Epoch 17/50 | Train Loss: 0.55511, Train Accuracy: 81.41% | Val Loss: 0.68106, Val Accuracy: 77.34% | Learning Rate: 0.00100000
Epoch 18/50 | Train Loss: 0.53187, Train Accuracy: 83.01% | Val Loss: 0.64319, Val Accuracy: 78.78% | Learning Rate: 0.00100000
Epoch 19/50 | Train Loss: 0.51162, Train Accuracy: 83.55% | Val Loss: 0.61278, Val Accuracy: 78.38% | Learning Rate: 0.00100000
Epoch 20/50 | Train Loss: 0.48928, Train Accuracy: 85.81% | Val Loss: 0.54708, Val Accuracy: 81.16% | Learning Rate: 0.00100000
Epoch 21/50 | Train Loss: 0.46527, Train Accuracy: 85.68% | Val Loss: 0.56080, Val Accuracy: 80.32% | Learning Rate: 0.00100000
Epoch 22/50 | Train Loss: 0.44597, Train Accuracy: 86.24% | Val Loss: 0.53667, Val Accuracy: 81.56% | Learning Rate: 0.00100000
Epoch 23/50 | Train Loss: 0.42798, Train Accuracy: 87.59% | Val Loss: 0.53315, Val Accuracy: 82.08% | Learning Rate: 0.00100000
Epoch 24/50 | Train Loss: 0.41808, Train Accuracy: 88.16% | Val Loss: 0.50200, Val Accuracy: 82.84% | Learning Rate: 0.00100000
Epoch 25/50 | Train Loss: 0.40105, Train Accuracy: 87.71% | Val Loss: 0.52321, Val Accuracy: 81.82% | Learning Rate: 0.00100000
Epoch 26/50 | Train Loss: 0.38924, Train Accuracy: 88.94% | Val Loss: 0.50891, Val Accuracy: 83.08% | Learning Rate: 0.00100000
Epoch 27/50 | Train Loss: 0.37043, Train Accuracy: 88.25% | Val Loss: 0.53573, Val Accuracy: 82.08% | Learning Rate: 0.00020000
Epoch 28/50 | Train Loss: 0.28329, Train Accuracy: 92.10% | Val Loss: 0.42437, Val Accuracy: 85.24% | Learning Rate: 0.00020000
Epoch 29/50 | Train Loss: 0.26330, Train Accuracy: 92.55% | Val Loss: 0.42226, Val Accuracy: 85.68% | Learning Rate: 0.00020000
Epoch 30/50 | Train Loss: 0.25189, Train Accuracy: 92.79% | Val Loss: 0.42765, Val Accuracy: 85.56% | Learning Rate: 0.00020000
Epoch 31/50 | Train Loss: 0.24167, Train Accuracy: 92.97% | Val Loss: 0.42900, Val Accuracy: 85.36% | Learning Rate: 0.00020000
Epoch 32/50 | Train Loss: 0.23674, Train Accuracy: 93.31% | Val Loss: 0.41064, Val Accuracy: 85.08% | Learning Rate: 0.00020000
Epoch 33/50 | Train Loss: 0.22717, Train Accuracy: 93.71% | Val Loss: 0.40974, Val Accuracy: 85.60% | Learning Rate: 0.00020000
Epoch 34/50 | Train Loss: 0.22440, Train Accuracy: 93.96% | Val Loss: 0.43866, Val Accuracy: 86.20% | Learning Rate: 0.00020000
Epoch 35/50 | Train Loss: 0.21838, Train Accuracy: 93.85% | Val Loss: 0.42298, Val Accuracy: 86.38% | Learning Rate: 0.00020000
Epoch 36/50 | Train Loss: 0.20828, Train Accuracy: 94.16% | Val Loss: 0.43576, Val Accuracy: 85.68% | Learning Rate: 0.00004000
Epoch 37/50 | Train Loss: 0.19306, Train Accuracy: 94.64% | Val Loss: 0.43047, Val Accuracy: 86.26% | Learning Rate: 0.00004000
Epoch 38/50 | Train Loss: 0.18735, Train Accuracy: 94.64% | Val Loss: 0.40721, Val Accuracy: 86.76% | Learning Rate: 0.00004000
Epoch 39/50 | Train Loss: 0.18747, Train Accuracy: 94.70% | Val Loss: 0.42041, Val Accuracy: 86.40% | Learning Rate: 0.00004000
Epoch 40/50 | Train Loss: 0.18568, Train Accuracy: 94.66% | Val Loss: 0.41652, Val Accuracy: 87.02% | Learning Rate: 0.00004000
Epoch 41/50 | Train Loss: 0.18339, Train Accuracy: 94.74% | Val Loss: 0.43617, Val Accuracy: 86.00% | Learning Rate: 0.00000800
Epoch 42/50 | Train Loss: 0.18042, Train Accuracy: 94.74% | Val Loss: 0.42460, Val Accuracy: 86.72% | Learning Rate: 0.00000800
Epoch 43/50 | Train Loss: 0.18080, Train Accuracy: 94.71% | Val Loss: 0.41118, Val Accuracy: 86.58% | Learning Rate: 0.00000800
Epoch 44/50 | Train Loss: 0.17540, Train Accuracy: 94.89% | Val Loss: 0.43749, Val Accuracy: 86.44% | Learning Rate: 0.00000160
Epoch 45/50 | Train Loss: 0.17682, Train Accuracy: 94.97% | Val Loss: 0.40380, Val Accuracy: 85.82% | Learning Rate: 0.00000160
Epoch 46/50 | Train Loss: 0.17344, Train Accuracy: 94.94% | Val Loss: 0.41878, Val Accuracy: 86.72% | Learning Rate: 0.00000160
Epoch 47/50 | Train Loss: 0.17779, Train Accuracy: 94.86% | Val Loss: 0.43236, Val Accuracy: 86.40% | Learning Rate: 0.00000160
Epoch 48/50 | Train Loss: 0.17454, Train Accuracy: 94.87% | Val Loss: 0.42398, Val Accuracy: 86.60% | Learning Rate: 0.00000032
Epoch 49/50 | Train Loss: 0.17700, Train Accuracy: 94.93% | Val Loss: 0.42537, Val Accuracy: 86.98% | Learning Rate: 0.00000032
Epoch 50/50 | Train Loss: 0.17079, Train Accuracy: 94.95% | Val Loss: 0.43266, Val Accuracy: 86.82% | Learning Rate: 0.00000032

Total Training Time: 72.64 min

Test Accuracy: 89.17%
InĀ [16]:
def plot_history(history):
    """
    Plots the training and validation loss, accuracy, and learning rate
    from a PyTorch history dictionary.

    Args:
        history (dict): Dictionary containing training metrics.
                        Expected keys: 'train_loss', 'val_loss', 'train_acc', 'val_acc', 'lrs'.
    """
    epochs = range(len(history['train_loss']))

    plt.figure(figsize=(18, 5))

    # Plot 1: Loss
    plt.subplot(1, 3, 1)
    plt.plot(epochs, history['train_loss'], label='Training Loss')
    plt.plot(epochs, history['val_loss'], label='Validation Loss')
    plt.title('Loss')
    plt.xlabel('Epochs')
    plt.ylabel('Loss')
    plt.legend()
    # plt.grid(True)

    # Plot 2: Accuracy
    plt.subplot(1, 3, 2)
    plt.plot(epochs, history['train_acc'], label='Training Accuracy')
    plt.plot(epochs, history['val_acc'], label='Validation Accuracy')
    plt.title('Accuracy')
    plt.xlabel('Epochs')
    plt.ylabel('Accuracy')
    plt.legend()
    # plt.grid(True)

    # Plot 3: Learning Rate
    plt.subplot(1, 3, 3)
    plt.plot(epochs, history['lrs'], label='Learning Rate', color='orange')
    plt.title('Learning Rate')
    plt.xlabel('Epochs')
    plt.ylabel('Learning Rate')
    plt.legend()
    # plt.grid(True)

    plt.tight_layout()
    plt.show()
    # plt.savefig()
InĀ [17]:
plot_history(history)
No description has been provided for this image
InĀ [18]:
%watermark -iv
matplotlib : 3.10.0
numpy      : 2.0.2
pandas     : 2.2.2
sklearn    : 1.6.1
torch      : 2.9.0+cu126
torchinfo  : 1.8.0
torchvision: 0.24.0+cu126