Fixel Algorithms

Regularized Training#

Notebook by:

Revision History#

Version

Date

User

Content / Changes

1.0.000

04/07/2024

Royi Avital

First version

Open In Colab

# Import Packages

# General Tools
import numpy as np
import scipy as sp
import pandas as pd

# Machine Learning
from sklearn.metrics import confusion_matrix, ConfusionMatrixDisplay
from sklearn.model_selection import ParameterGrid

# Deep Learning
import torch
import torch.nn            as nn
import torch.nn.functional as F
from torch.optim.optimizer import Optimizer
from torch.optim.lr_scheduler import LRScheduler
from torch.utils.data import DataLoader
from torch.utils.tensorboard import SummaryWriter
import torchinfo
from torchmetrics.classification import MulticlassAccuracy
import torchvision
from torchvision.transforms import v2 as TorchVisionTrns

# Miscellaneous
import copy
from enum import auto, Enum, unique
import math
import os
from platform import python_version
import random
import shutil
import time

# Typing
from typing import Callable, Dict, Generator, List, Optional, Self, Set, Tuple, Union

# Visualization
import matplotlib as mpl
import matplotlib.pyplot as plt
import seaborn as sns

# Jupyter
from IPython import get_ipython
from IPython.display import HTML, Image
from IPython.display import display
from ipywidgets import Dropdown, FloatSlider, interact, IntSlider, Layout, SelectionSlider
from ipywidgets import interact
2024-06-14 06:48:47.888745: I tensorflow/core/platform/cpu_feature_guard.cc:182] This TensorFlow binary is optimized to use available CPU instructions in performance-critical operations.
To enable the following instructions: SSE4.1 SSE4.2 AVX AVX2 FMA, in other operations, rebuild TensorFlow with the appropriate compiler flags.

Notations#

  • (?) Question to answer interactively.

  • (!) Simple task to add code for the notebook.

  • (@) Optional / Extra self practice.

  • (#) Note / Useful resource / Food for thought.

Code Notations:

someVar    = 2; #<! Notation for a variable
vVector    = np.random.rand(4) #<! Notation for 1D array
mMatrix    = np.random.rand(4, 3) #<! Notation for 2D array
tTensor    = np.random.rand(4, 3, 2, 3) #<! Notation for nD array (Tensor)
tuTuple    = (1, 2, 3) #<! Notation for a tuple
lList      = [1, 2, 3] #<! Notation for a list
dDict      = {1: 3, 2: 2, 3: 1} #<! Notation for a dictionary
oObj       = MyClass() #<! Notation for an object
dfData     = pd.DataFrame() #<! Notation for a data frame
dsData     = pd.Series() #<! Notation for a series
hObj       = plt.Axes() #<! Notation for an object / handler / function handler

Code Exercise#

  • Single line fill

vallToFill = ???
  • Multi Line to Fill (At least one)

# You need to start writing
????
  • Section to Fill

#===========================Fill This===========================#
# 1. Explanation about what to do.
# !! Remarks to follow / take under consideration.
mX = ???

???
#===============================================================#
# Configuration
# %matplotlib inline

seedNum = 512
np.random.seed(seedNum)
random.seed(seedNum)

# Matplotlib default color palette
lMatPltLibclr = ['#1f77b4', '#ff7f0e', '#2ca02c', '#d62728', '#9467bd', '#8c564b', '#e377c2', '#7f7f7f', '#bcbd22', '#17becf']
# sns.set_theme() #>! Apply SeaBorn theme

runInGoogleColab = 'google.colab' in str(get_ipython())

# Improve performance by benchmarking
torch.backends.cudnn.benchmark = True

# Reproducibility (Per PyTorch Version on the same device)
# torch.manual_seed(seedNum)
# torch.backends.cudnn.deterministic = True
# torch.backends.cudnn.benchmark     = False #<! Makes things slower
# Constants

FIG_SIZE_DEF    = (8, 8)
ELM_SIZE_DEF    = 50
CLASS_COLOR     = ('b', 'r')
EDGE_COLOR      = 'k'
MARKER_SIZE_DEF = 10
LINE_WIDTH_DEF  = 2

DATA_SET_FILE_NAME      = 'archive.zip'
DATA_SET_FOLDER_NAME    = 'IntelImgCls'

D_CLASSES  = {0: 'Airplane', 1: 'Automobile', 2: 'Bird', 3: 'Cat', 4: 'Deer', 5: 'Dog', 6: 'Frog', 7: 'Horse', 8: 'Ship', 9: 'Truck'}
L_CLASSES  = ['Airplane', 'Automobile', 'Bird', 'Cat', 'Deer', 'Dog', 'Frog', 'Horse', 'Ship', 'Truck']
T_IMG_SIZE = (32, 32, 3)

DATA_FOLDER_PATH    = 'Data'
TENSOR_BOARD_BASE   = 'TB'
# Download Auxiliary Modules for Google Colab
if runInGoogleColab:
    !wget https://raw.githubusercontent.com/FixelAlgorithmsTeam/FixelCourses/master/AIProgram/2024_02/DataManipulation.py
    !wget https://raw.githubusercontent.com/FixelAlgorithmsTeam/FixelCourses/master/AIProgram/2024_02/DataVisualization.py
    !wget https://raw.githubusercontent.com/FixelAlgorithmsTeam/FixelCourses/master/AIProgram/2024_02/DeepLearningPyTorch.py
# Courses Packages
import sys
sys.path.append('../../utils')
sys.path.append('/home/vlad/utils')
from DataVisualization import PlotLabelsHistogram, PlotMnistImages
from DeepLearningPyTorch import ResidualBlock, TBLogger, TestDataSet
from DeepLearningPyTorch import GenDataLoaders, InitWeightsKaiNorm, TrainModel, TrainModelSch
# General Auxiliary Functions

def GenResNetModel( trainedModel: bool, numCls: int, resNetDepth: int = 18 ) -> nn.Module:
    # Read on the API change at: How to Train State of the Art Models Using TorchVision’s Latest Primitives
    # https://pytorch.org/blog/how-to-train-state-of-the-art-models-using-torchvision-latest-primitives

    if (resNetDepth == 18):
        modelFun = torchvision.models.resnet18
        modelWeights = torchvision.models.ResNet18_Weights.IMAGENET1K_V1
    elif (resNetDepth == 34):
        modelFun = torchvision.models.resnet34
        modelWeights = torchvision.models.ResNet34_Weights.IMAGENET1K_V1
    else:
        raise ValueError(f'The `resNetDepth`: {resNetDepth} is invalid!')

    if trainedModel:
        oModel = modelFun(weights = modelWeights)
        numFeaturesIn   = oModel.fc.in_features
        # Assuming numCls << 100
        oModel.fc       = nn.Sequential(
            nn.Linear(numFeaturesIn, 128), nn.ReLU(),
            nn.Linear(128, numCls),
        )
    else:
        oModel = modelFun(weights = None, num_classes = numCls)

    return oModel

Regularized Training#

This notebook combines several regularization methods in order to maximize the validation score.

This notebook demonstrate:

  • Using data augmentation using CutMix.

  • Using Label Smoothing.


# Parameters

# Data

# Model
dropP = 0.5 #<! Dropout Layer

# Training
batchSize   = 256
numWorkers  = 4 #<! Number of workers
numEpochs   = 35
ϵ = 0.1 #<! Label Smoothing

# Visualization
numImg = 3

Generate / Load Data#

Load the CIFAR 10 Data Set.
It is composed of 60,000 RGB images of size 32x32 with 10 classes uniformly spread.

  • (#) The dataset is retrieved using Torch Vision’s built in datasets.

# Load Data

dsTrain = torchvision.datasets.CIFAR10(root = DATA_FOLDER_PATH, train = True,  download = True, transform = torchvision.transforms.ToTensor())
dsVal   = torchvision.datasets.CIFAR10(root = DATA_FOLDER_PATH, train = False, download = True, transform = torchvision.transforms.ToTensor())
lClass  = dsTrain.classes


print(f'The training data set data shape: {dsTrain.data.shape}')
print(f'The test data set data shape: {dsVal.data.shape}')
print(f'The unique values of the labels: {np.unique(lClass)}')
Files already downloaded and verified
Files already downloaded and verified
The training data set data shape: (50000, 32, 32, 3)
The test data set data shape: (10000, 32, 32, 3)
The unique values of the labels: ['airplane' 'automobile' 'bird' 'cat' 'deer' 'dog' 'frog' 'horse' 'ship'
 'truck']
  • (#) The dataset is indexible (Subscriptable). It returns a tuple of the features and the label.

  • (#) While data is arranged as H x W x C the transformer, when accessing the data, will convert it into C x H x W.

# Element of the Data Set

mX, valY = dsTrain[0]

print(f'The features shape: {mX.shape}')
print(f'The label value: {valY}')
The features shape: torch.Size([3, 32, 32])
The label value: 6

Plot the Data#

# Extract Data

tX = dsTrain.data #<! NumPy Tensor (NDarray)
mX = np.reshape(tX, (tX.shape[0], -1))
vY = dsTrain.targets #<! NumPy Vector
# Plot the Data

hF = PlotMnistImages(mX, vY, numImg, tuImgSize = T_IMG_SIZE)
../../../_images/9492485648ba13026794f13c42e8f98fa63a693e4e8dc14c30375ba15737fa97.png
# Histogram of Labels

hA = PlotLabelsHistogram(vY, lClass = L_CLASSES)
plt.show()
../../../_images/3558e430ae83021682b92156eed7e0205ea9686c04c2d3a55cf23a0bd066b42d.png
  • (?) If data is converted into grayscale, how would it effect the performance of the classifier? Explain.
    You may assume the conversion is done using the mean value of the RGB pixel.

Pre Process Data#

This section normalizes the data to have zero mean and unit variance per channel.
It is required to calculate:

  • The average pixel value per channel.

  • The standard deviation per channel.


  • (#) The values calculated on the train set and applied to both sets.

  • (#) The the data will be used to pre process the image on loading by the transformer.

  • (#) There packages which specializes in transforms: Kornia, Albumentations.
    They are commonly used for Data Augmentation at scale.

# Calculate the Standardization Parameters
vMean = np.mean(dsTrain.data / 255.0, axis = (0, 1, 2))
vStd  = np.std(dsVal.data / 255.0, axis = (0, 1, 2))

print('µ =', vMean)
print('σ =', vStd)
µ = [0.49139968 0.48215841 0.44653091]
σ = [0.24665252 0.24289226 0.26159238]
# Update Transformer

oTrnsTrain = TorchVisionTrns.Compose([
    TorchVisionTrns.RandomHorizontalFlip(), #<! Can be done in UINT8 for faster performance
    TorchVisionTrns.AutoAugment(policy = TorchVisionTrns.AutoAugmentPolicy.CIFAR10), #<! Requires `UINT8`
    TorchVisionTrns.ToImage(),
    TorchVisionTrns.ToDtype(torch.float32, scale = True),
    TorchVisionTrns.Normalize(vMean, vStd)
])

oTrnsInfer = TorchVisionTrns.Compose([
    TorchVisionTrns.ToImage(),
    TorchVisionTrns.ToDtype(torch.float32, scale = True),
    TorchVisionTrns.Normalize(vMean, vStd)
])

# Update the DS transformer
dsTrain.transform   = oTrnsTrain
dsVal.transform     = oTrnsInfer
# "Normalized" Image

imgIdx = 5


N, H, W, C = dsTrain.data.shape
hF, vHA = plt.subplots(2, 3, figsize = (8, 4))
vHA = vHA.flat
for hA in vHA:
    mX, valY = dsTrain[imgIdx] #<! Random
    mX = torch.permute(mX, (1, 2, 0))
    hA.imshow(torch.clip(mX * vStd[None, None, :] + vMean[None, None, :], min = 0.0, max = 1.0))
    hA.set_title(f'True label: {L_CLASSES[valY]}')
    
hF.tight_layout()
../../../_images/b201c8018f6d1ccc3d96ec2d5fd79a74c9fdd4abcb11df37d877e8619430047c.png

Data Loaders#

This section defines the data loaded.

# Data Loader

dlTrain = torch.utils.data.DataLoader(dsTrain, shuffle = True, batch_size = 1 * batchSize, num_workers = 2, drop_last = True, persistent_workers = True)
dlVal   = torch.utils.data.DataLoader(dsVal, shuffle = False, batch_size = 2 * batchSize, num_workers = 2, persistent_workers = True)

# dlTrain = torch.utils.data.DataLoader(dsTrain, shuffle = True, batch_size = 1 * batchSize, num_workers = 0, drop_last = True)
# dlVal   = torch.utils.data.DataLoader(dsVal, shuffle = False, batch_size = 2 * batchSize, num_workers = 0)
# Iterate on the Loader
# The first batch.
tX, vY = next(iter(dlTrain)) #<! PyTorch Tensors

print(f'The batch features dimensions: {tX.shape}')
print(f'The batch labels dimensions: {vY.shape}')
The batch features dimensions: torch.Size([256, 3, 32, 32])
The batch labels dimensions: torch.Size([256])
# Looping
# for ii, (tX, vY) in zip(range(1), dlVal): #<! https://stackoverflow.com/questions/36106712
#     print(f'The batch features dimensions: {tX.shape}')
#     print(f'The batch labels dimensions: {vY.shape}')

Load the Model#

This section loads the model.
The number of outputs is adjusted to match the number of classes in the data.

# Loading a Pre Defined Model
oModel = GenResNetModel(trainedModel = False, numCls = len(L_CLASSES))
# oModel.apply(InitWeightsKaiNorm)
# Model Information - Pre Defined
# Pay attention to the layers name.
torchinfo.summary(oModel, (batchSize, *(T_IMG_SIZE[::-1])), col_names = ['kernel_size', 'output_size', 'num_params'], device = 'cpu', row_settings = ['depth', 'var_names'])
========================================================================================================================
Layer (type (var_name):depth-idx)             Kernel Shape              Output Shape              Param #
========================================================================================================================
ResNet (ResNet)                               --                        [256, 10]                 --
├─Conv2d (conv1): 1-1                         [7, 7]                    [256, 64, 16, 16]         9,408
├─BatchNorm2d (bn1): 1-2                      --                        [256, 64, 16, 16]         128
├─ReLU (relu): 1-3                            --                        [256, 64, 16, 16]         --
├─MaxPool2d (maxpool): 1-4                    3                         [256, 64, 8, 8]           --
├─Sequential (layer1): 1-5                    --                        [256, 64, 8, 8]           --
│    └─BasicBlock (0): 2-1                    --                        [256, 64, 8, 8]           --
│    │    └─Conv2d (conv1): 3-1               [3, 3]                    [256, 64, 8, 8]           36,864
│    │    └─BatchNorm2d (bn1): 3-2            --                        [256, 64, 8, 8]           128
│    │    └─ReLU (relu): 3-3                  --                        [256, 64, 8, 8]           --
│    │    └─Conv2d (conv2): 3-4               [3, 3]                    [256, 64, 8, 8]           36,864
│    │    └─BatchNorm2d (bn2): 3-5            --                        [256, 64, 8, 8]           128
│    │    └─ReLU (relu): 3-6                  --                        [256, 64, 8, 8]           --
│    └─BasicBlock (1): 2-2                    --                        [256, 64, 8, 8]           --
│    │    └─Conv2d (conv1): 3-7               [3, 3]                    [256, 64, 8, 8]           36,864
│    │    └─BatchNorm2d (bn1): 3-8            --                        [256, 64, 8, 8]           128
│    │    └─ReLU (relu): 3-9                  --                        [256, 64, 8, 8]           --
│    │    └─Conv2d (conv2): 3-10              [3, 3]                    [256, 64, 8, 8]           36,864
│    │    └─BatchNorm2d (bn2): 3-11           --                        [256, 64, 8, 8]           128
│    │    └─ReLU (relu): 3-12                 --                        [256, 64, 8, 8]           --
├─Sequential (layer2): 1-6                    --                        [256, 128, 4, 4]          --
│    └─BasicBlock (0): 2-3                    --                        [256, 128, 4, 4]          --
│    │    └─Conv2d (conv1): 3-13              [3, 3]                    [256, 128, 4, 4]          73,728
│    │    └─BatchNorm2d (bn1): 3-14           --                        [256, 128, 4, 4]          256
│    │    └─ReLU (relu): 3-15                 --                        [256, 128, 4, 4]          --
│    │    └─Conv2d (conv2): 3-16              [3, 3]                    [256, 128, 4, 4]          147,456
│    │    └─BatchNorm2d (bn2): 3-17           --                        [256, 128, 4, 4]          256
│    │    └─Sequential (downsample): 3-18     --                        [256, 128, 4, 4]          8,448
│    │    └─ReLU (relu): 3-19                 --                        [256, 128, 4, 4]          --
│    └─BasicBlock (1): 2-4                    --                        [256, 128, 4, 4]          --
│    │    └─Conv2d (conv1): 3-20              [3, 3]                    [256, 128, 4, 4]          147,456
│    │    └─BatchNorm2d (bn1): 3-21           --                        [256, 128, 4, 4]          256
│    │    └─ReLU (relu): 3-22                 --                        [256, 128, 4, 4]          --
│    │    └─Conv2d (conv2): 3-23              [3, 3]                    [256, 128, 4, 4]          147,456
│    │    └─BatchNorm2d (bn2): 3-24           --                        [256, 128, 4, 4]          256
│    │    └─ReLU (relu): 3-25                 --                        [256, 128, 4, 4]          --
├─Sequential (layer3): 1-7                    --                        [256, 256, 2, 2]          --
│    └─BasicBlock (0): 2-5                    --                        [256, 256, 2, 2]          --
│    │    └─Conv2d (conv1): 3-26              [3, 3]                    [256, 256, 2, 2]          294,912
│    │    └─BatchNorm2d (bn1): 3-27           --                        [256, 256, 2, 2]          512
│    │    └─ReLU (relu): 3-28                 --                        [256, 256, 2, 2]          --
│    │    └─Conv2d (conv2): 3-29              [3, 3]                    [256, 256, 2, 2]          589,824
│    │    └─BatchNorm2d (bn2): 3-30           --                        [256, 256, 2, 2]          512
│    │    └─Sequential (downsample): 3-31     --                        [256, 256, 2, 2]          33,280
│    │    └─ReLU (relu): 3-32                 --                        [256, 256, 2, 2]          --
│    └─BasicBlock (1): 2-6                    --                        [256, 256, 2, 2]          --
│    │    └─Conv2d (conv1): 3-33              [3, 3]                    [256, 256, 2, 2]          589,824
│    │    └─BatchNorm2d (bn1): 3-34           --                        [256, 256, 2, 2]          512
│    │    └─ReLU (relu): 3-35                 --                        [256, 256, 2, 2]          --
│    │    └─Conv2d (conv2): 3-36              [3, 3]                    [256, 256, 2, 2]          589,824
│    │    └─BatchNorm2d (bn2): 3-37           --                        [256, 256, 2, 2]          512
│    │    └─ReLU (relu): 3-38                 --                        [256, 256, 2, 2]          --
├─Sequential (layer4): 1-8                    --                        [256, 512, 1, 1]          --
│    └─BasicBlock (0): 2-7                    --                        [256, 512, 1, 1]          --
│    │    └─Conv2d (conv1): 3-39              [3, 3]                    [256, 512, 1, 1]          1,179,648
│    │    └─BatchNorm2d (bn1): 3-40           --                        [256, 512, 1, 1]          1,024
│    │    └─ReLU (relu): 3-41                 --                        [256, 512, 1, 1]          --
│    │    └─Conv2d (conv2): 3-42              [3, 3]                    [256, 512, 1, 1]          2,359,296
│    │    └─BatchNorm2d (bn2): 3-43           --                        [256, 512, 1, 1]          1,024
│    │    └─Sequential (downsample): 3-44     --                        [256, 512, 1, 1]          132,096
│    │    └─ReLU (relu): 3-45                 --                        [256, 512, 1, 1]          --
│    └─BasicBlock (1): 2-8                    --                        [256, 512, 1, 1]          --
│    │    └─Conv2d (conv1): 3-46              [3, 3]                    [256, 512, 1, 1]          2,359,296
│    │    └─BatchNorm2d (bn1): 3-47           --                        [256, 512, 1, 1]          1,024
│    │    └─ReLU (relu): 3-48                 --                        [256, 512, 1, 1]          --
│    │    └─Conv2d (conv2): 3-49              [3, 3]                    [256, 512, 1, 1]          2,359,296
│    │    └─BatchNorm2d (bn2): 3-50           --                        [256, 512, 1, 1]          1,024
│    │    └─ReLU (relu): 3-51                 --                        [256, 512, 1, 1]          --
├─AdaptiveAvgPool2d (avgpool): 1-9            --                        [256, 512, 1, 1]          --
├─Linear (fc): 1-10                           --                        [256, 10]                 5,130
========================================================================================================================
Total params: 11,181,642
Trainable params: 11,181,642
Non-trainable params: 0
Total mult-adds (Units.GIGABYTES): 9.48
========================================================================================================================
Input size (MB): 3.15
Forward/backward pass size (MB): 207.64
Params size (MB): 44.73
Estimated Total Size (MB): 255.51
========================================================================================================================
  • (?) Does the last (Head) dense layer includes a bias? Explain.

Train the Model#

This section trains the model.
It compares results with and without Label Smoothing.

  • (#) The objective is to show how to apply Label Smoothing.

CutMix#

There are 2 options to incorporate the CutMix (Or MixUp):

  1. The Training Loop.

  2. The Data Loader.

The (1) option requires adapting the training loop after fetching the batch.
The (2) option works with no change of the training loop.

This section implements the (2) option.
This requires altering the collate_fn of the data loader.
The collate_fn takes a list of items where each item is a single output of DataSet object. For example, in image classification the output of the DataSet is usually a tuple of (imge, label).
Hence the input to collate_fn is a list (Length of batchSize) of such tuples and the output is a tuple of 2 tensors.

# Update the Collate Function

from torch.utils.data import default_collate
α = 0.5
numCls = len(L_CLASSES)

oCutMix = TorchVisionTrns.CutMix(alpha = α, num_classes = numCls) #<! `num_classes` must be defined for integer label

def CutMixColateFun( lBatch: List[Tuple] ) -> Tuple[torch.Tensor, torch.Tensor]:

    return oCutMix(*default_collate(lBatch))
    
# Generate the Data Loaders
# Custom collate function seems to not work with `numWorkers > 0` on Windows.
dlTrain, dlVal = GenDataLoaders(dsTrain, dsVal, batchSize, numWorkers = 0, CollateFn = CutMixColateFun)
# Iterate on the Loader
# The first batch.
tX, mY = next(iter(dlTrain)) #<! PyTorch Tensors

print(f'The batch features dimensions: {tX.shape}')
print(f'The batch labels dimensions: {vY.shape}')
The batch features dimensions: torch.Size([256, 3, 32, 32])
The batch labels dimensions: torch.Size([256])
# Data from Data Loader

hF, vHA = plt.subplots(2, 3, figsize = (8, 4))
vHA = vHA.flat
for hA, mXX, vYY in zip(vHA, tX, mY):
    valY = torch.argmax(vYY)
    mX = torch.permute(mXX, (1, 2, 0))
    hA.imshow(torch.clip(mX * vStd[None, None, :] + vMean[None, None, :], min = 0.0, max = 1.0))
    hA.set_title(f'True label: {L_CLASSES[valY]}')
    
hF.tight_layout()
../../../_images/74d3e3663c94e379292339939dd3ceceec68fbd5c85f55f72177b79c255d12bf.png
# Run Device

runDevice = torch.device('cuda:0' if torch.cuda.is_available() else 'cpu') #<! The 1st CUDA device
# Loss and Score Function

hL = nn.CrossEntropyLoss(label_smoothing = ϵ)
# The Score
# Adjusting the score to support the labels in a form od discrete distribution

def hS( mZ: torch.Tensor, mY: torch.Tensor ):

    numDim = mY.ndim

    vZ = torch.argmax(mZ, dim = 1)
    if numDim > 1: #<! Discrete Distribution
        vY = torch.argmax(mY, dim = 1)
    else: #<! Label as an integer
        vY = mY

    return torch.sum(torch.eq(vZ, vY)) / vZ.shape[0]
# Training Loop

oModel = oModel.to(runDevice)
oOpt = torch.optim.AdamW(oModel.parameters(), lr = 1e-3, betas = (0.9, 0.99), weight_decay = 1e-2) #<! Define optimizer
oSch = torch.optim.lr_scheduler.OneCycleLR(oOpt, max_lr = 5e-2, total_steps = numEpochs)
_, lTrainLoss, lTrainScore, lValLoss, lValScore, lLearnRate = TrainModel(oModel, dlTrain, dlVal, oOpt, numEpochs, hL, hS, oSch = oSch)
Epoch    1 / 35 | Train Loss:  2.179 | Val Loss:  1.734 | Train Score:  0.242 | Val Score:  0.443 | Epoch Time: 69.53 | <-- Checkpoint! |
Epoch    2 / 35 | Train Loss:  2.049 | Val Loss:  1.625 | Train Score:  0.331 | Val Score:  0.517 | Epoch Time: 40.20 | <-- Checkpoint! |
Epoch    3 / 35 | Train Loss:  2.039 | Val Loss:  2.568 | Train Score:  0.342 | Val Score:  0.482 | Epoch Time: 45.42 |
Epoch    4 / 35 | Train Loss:  2.024 | Val Loss:  1.547 | Train Score:  0.352 | Val Score:  0.539 | Epoch Time: 41.74 | <-- Checkpoint! |
Epoch    5 / 35 | Train Loss:  1.956 | Val Loss:  1.498 | Train Score:  0.386 | Val Score:  0.558 | Epoch Time: 45.16 | <-- Checkpoint! |
Epoch    6 / 35 | Train Loss:  1.941 | Val Loss:  1.427 | Train Score:  0.402 | Val Score:  0.604 | Epoch Time: 41.91 | <-- Checkpoint! |
Epoch    7 / 35 | Train Loss:  1.937 | Val Loss:  1.494 | Train Score:  0.405 | Val Score:  0.586 | Epoch Time: 47.90 |
Epoch    8 / 35 | Train Loss:  1.911 | Val Loss:  1.472 | Train Score:  0.419 | Val Score:  0.573 | Epoch Time: 41.30 |
Epoch    9 / 35 | Train Loss:  1.879 | Val Loss:  1.383 | Train Score:  0.439 | Val Score:  0.620 | Epoch Time: 45.40 | <-- Checkpoint! |
Epoch   10 / 35 | Train Loss:  1.884 | Val Loss:  1.433 | Train Score:  0.437 | Val Score:  0.594 | Epoch Time: 41.98 |
Epoch   11 / 35 | Train Loss:  1.827 | Val Loss:  1.377 | Train Score:  0.464 | Val Score:  0.614 | Epoch Time: 45.77 |
Epoch   12 / 35 | Train Loss:  1.818 | Val Loss:  1.309 | Train Score:  0.484 | Val Score:  0.656 | Epoch Time: 42.45 | <-- Checkpoint! |
Epoch   13 / 35 | Train Loss:  1.825 | Val Loss:  1.334 | Train Score:  0.479 | Val Score:  0.660 | Epoch Time: 45.92 | <-- Checkpoint! |
Epoch   14 / 35 | Train Loss:  1.791 | Val Loss:  1.264 | Train Score:  0.496 | Val Score:  0.672 | Epoch Time: 41.98 | <-- Checkpoint! |
Epoch   15 / 35 | Train Loss:  1.794 | Val Loss:  1.268 | Train Score:  0.491 | Val Score:  0.691 | Epoch Time: 45.79 | <-- Checkpoint! |
Epoch   16 / 35 | Train Loss:  1.772 | Val Loss:  1.259 | Train Score:  0.505 | Val Score:  0.703 | Epoch Time: 42.26 | <-- Checkpoint! |
Epoch   17 / 35 | Train Loss:  1.772 | Val Loss:  1.185 | Train Score:  0.506 | Val Score:  0.708 | Epoch Time: 46.34 | <-- Checkpoint! |
Epoch   18 / 35 | Train Loss:  1.747 | Val Loss:  1.147 | Train Score:  0.524 | Val Score:  0.742 | Epoch Time: 41.50 | <-- Checkpoint! |
Epoch   19 / 35 | Train Loss:  1.723 | Val Loss:  1.158 | Train Score:  0.533 | Val Score:  0.748 | Epoch Time: 45.79 | <-- Checkpoint! |
Epoch   20 / 35 | Train Loss:  1.687 | Val Loss:  1.119 | Train Score:  0.549 | Val Score:  0.742 | Epoch Time: 41.87 |
Epoch   21 / 35 | Train Loss:  1.686 | Val Loss:  1.138 | Train Score:  0.547 | Val Score:  0.735 | Epoch Time: 45.76 |
Epoch   22 / 35 | Train Loss:  1.720 | Val Loss:  1.133 | Train Score:  0.541 | Val Score:  0.743 | Epoch Time: 46.07 |
Epoch   23 / 35 | Train Loss:  1.678 | Val Loss:  1.095 | Train Score:  0.557 | Val Score:  0.758 | Epoch Time: 45.89 | <-- Checkpoint! |
Epoch   24 / 35 | Train Loss:  1.687 | Val Loss:  1.076 | Train Score:  0.547 | Val Score:  0.774 | Epoch Time: 45.05 | <-- Checkpoint! |
Epoch   25 / 35 | Train Loss:  1.651 | Val Loss:  1.067 | Train Score:  0.571 | Val Score:  0.780 | Epoch Time: 42.50 | <-- Checkpoint! |
Epoch   26 / 35 | Train Loss:  1.608 | Val Loss:  1.023 | Train Score:  0.586 | Val Score:  0.789 | Epoch Time: 46.18 | <-- Checkpoint! |
Epoch   27 / 35 | Train Loss:  1.591 | Val Loss:  1.021 | Train Score:  0.591 | Val Score:  0.798 | Epoch Time: 42.52 | <-- Checkpoint! |
Epoch   28 / 35 | Train Loss:  1.591 | Val Loss:  1.020 | Train Score:  0.600 | Val Score:  0.797 | Epoch Time: 46.23 |
Epoch   29 / 35 | Train Loss:  1.569 | Val Loss:  1.012 | Train Score:  0.606 | Val Score:  0.808 | Epoch Time: 42.52 | <-- Checkpoint! |
Epoch   30 / 35 | Train Loss:  1.552 | Val Loss:  0.977 | Train Score:  0.611 | Val Score:  0.814 | Epoch Time: 42.29 | <-- Checkpoint! |
Epoch   31 / 35 | Train Loss:  1.536 | Val Loss:  0.961 | Train Score:  0.623 | Val Score:  0.820 | Epoch Time: 44.93 | <-- Checkpoint! |
Epoch   32 / 35 | Train Loss:  1.553 | Val Loss:  0.969 | Train Score:  0.615 | Val Score:  0.824 | Epoch Time: 45.74 | <-- Checkpoint! |
Epoch   33 / 35 | Train Loss:  1.579 | Val Loss:  0.966 | Train Score:  0.611 | Val Score:  0.825 | Epoch Time: 41.65 | <-- Checkpoint! |
Epoch   34 / 35 | Train Loss:  1.534 | Val Loss:  0.941 | Train Score:  0.634 | Val Score:  0.824 | Epoch Time: 47.07 |
Epoch   35 / 35 | Train Loss:  1.572 | Val Loss:  0.953 | Train Score:  0.609 | Val Score:  0.825 | Epoch Time: 41.96 | <-- Checkpoint! |
# Plot Training Phase

hF, vHa = plt.subplots(nrows = 1, ncols = 3, figsize = (12, 5))
vHa = np.ravel(vHa)

hA = vHa[0]
hA.plot(lTrainLoss, lw = 2, label = 'Train')
hA.plot(lValLoss, lw = 2, label = 'Validation')
hA.set_title('Binary Cross Entropy Loss')
hA.set_xlabel('Epoch')
hA.set_ylabel('Loss')
hA.legend()

hA = vHa[1]
hA.plot(lTrainScore, lw = 2, label = 'Train')
hA.plot(lValScore, lw = 2, label = 'Validation')
hA.set_title('Accuracy Score')
hA.set_xlabel('Epoch')
hA.set_ylabel('Score')
hA.legend()

hA = vHa[2]
hA.plot(lLearnRate, lw = 2)
hA.set_title('Learn Rate Scheduler')
hA.set_xlabel('Epoch')
hA.set_ylabel('Learn Rate')
Text(0, 0.5, 'Learn Rate')
../../../_images/2e5bd052f2f9f6133fa9fd1feca8e70a2a24ab2e1e84000cdb67a4e2651e1839.png
  • (?) Explain the training loss vs. the validation loss.

  • (!) Replace the augmentation with MixUp.

  • (@) Train a model based on self implementation of ResNet / ResNeXt (Use ResidualBlock).

  • (@) Implement “Test Time” augmentation.