Iteration and Experimentation

This notebook contains my process of systematic iteration and experimentation.

# @title
%%capture

# Install packages
!pip install torchvision;
!pip install segmentation-models-pytorch;
!pip install albumentationsx;

# Imports
from google.colab import drive
import os
import pandas as pd
from PIL import Image
import matplotlib.pyplot as plt
from ipywidgets import interactive, Dropdown, SelectMultiple, VBox, HBox
import torch
from torch.utils.data import Dataset, DataLoader
from torchvision.transforms import ToTensor
import torch.optim as optim
import numpy as np
import segmentation_models_pytorch as smp
from segmentation_models_pytorch.losses import DiceLoss, FocalLoss, SoftBCEWithLogitsLoss, SoftCrossEntropyLoss, JaccardLoss, TverskyLoss, LovaszLoss
from segmentation_models_pytorch.metrics import get_stats, iou_score, accuracy, f1_score
import albumentations as A

# Load the data from google drive
drive.mount("/mnt/drive")

images_path = "/mnt/drive/MyDrive/dida/images"
labels_path = "/mnt/drive/MyDrive/dida/labels"
to_predict = "/mnt/drive/MyDrive/dida/to_predict"

# Create the DataSet
class SegmentationDataset(Dataset):
    def __init__(self, image_dir, label_dir):
        self.image_dir = image_dir
        self.label_dir = label_dir
        self.common_filenames = sorted(f for f in os.listdir(image_dir) if f in os.listdir(label_dir))

    def __len__(self):
        return len(self.common_filenames)

    def __getitem__(self, idx):
        image_path = os.path.join(self.image_dir, self.common_filenames[idx])
        label_path = os.path.join(self.label_dir, self.common_filenames[idx])

        image_pil = Image.open(image_path)
        label_pil = Image.open(label_path)

        image_tensor = ToTensor()(image_pil)
        label_tensor = ToTensor()(label_pil)

        return image_tensor, label_tensor

ds = SegmentationDataset(images_path, labels_path)

train_size = 20
val_size = 5
train_dataset, val_dataset = torch.utils.data.random_split(ds, [train_size, val_size])

train_loader = DataLoader(train_dataset, batch_size=20, shuffle=True)
val_loader = DataLoader(val_dataset, batch_size=20, shuffle=False)

The following function encapsulates some of the choices we could make for our model.

It accepts as parameters: - number of epochs: The number of epochs to train for. During testing, I kept this set to 250. - patience: An optional parameter for early stopping if the F1 score does not improve. I created this since in early experiments, the F1 score would start to decrease as the model appeared to overfit. A default value of zero ignores this setting. - model architecture: The model architecture, https://smp.readthedocs.io/en/latest/models.html. - model encoder: The model encoder, https://smp.readthedocs.io/en/latest/encoders.html. - encoder weights: Pretrained encoder weights, https://smp.readthedocs.io/en/latest/encoders.html. - optimizer: The optimizer, https://docs.pytorch.org/docs/stable/optim.html. - learning rate: The learning rate. - loss function: The loss function for the segmentation task, imported from the SMP library https://smp.readthedocs.io/en/latest/losses.html. - verbose (true/false): A setting for whether to print metrics every 10 epochs or not.

It returns the full training / validation records of several loss functions and metrics:

Note to self: clarify when a good score is higher / lower!

# @title
# Define the device
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
print(f"Using device: {device}")

def train_model(num_epochs, patience, model_name, encoder_name, encoder_weights, optimizer_type, lr, loss_function_type, verbose=False):
    # Define the model
    if model_name == "Unet":
        model = smp.Unet(encoder_name=encoder_name, encoder_weights=encoder_weights, in_channels=4, classes=1, activation='sigmoid')
    elif model_name == "UnetPlusPlus":
        model = smp.UnetPlusPlus(encoder_name=encoder_name, encoder_weights=encoder_weights, in_channels=4, classes=1, activation='sigmoid')
    elif model_name == "FPN":
        model = smp.FPN(encoder_name=encoder_name, encoder_weights=encoder_weights, in_channels=4, classes=1, activation='sigmoid')
    elif model_name == "PSPNet":
        model = smp.PSPNet(encoder_name=encoder_name, encoder_weights=encoder_weights, in_channels=4, classes=1, activation='sigmoid')
    elif model_name == "DeepLabV3":
        model = smp.DeepLabV3(encoder_name=encoder_name, encoder_weights=encoder_weights, in_channels=4, classes=1, activation='sigmoid')
    elif model_name == "DeepLabV3Plus":
        model = smp.DeepLabV3Plus(encoder_name=encoder_name, encoder_weights=encoder_weights, in_channels=4, classes=1, activation='sigmoid')
    elif model_name == "Linknet":
        model = smp.Linknet(encoder_name=encoder_name, encoder_weights=encoder_weights, in_channels=4, classes=1, activation='sigmoid')
    elif model_name == "MAnet":
        model = smp.MAnet(encoder_name=encoder_name, encoder_weights=encoder_weights, in_channels=4, classes=1, activation='sigmoid')
    elif model_name == "PAN":
        model = smp.PAN(encoder_name=encoder_name, encoder_weights=encoder_weights, in_channels=4, classes=1, activation='sigmoid')
    elif model_name == "UPerNet":
        model = smp.UPerNet(encoder_name=encoder_name, encoder_weights=encoder_weights, in_channels=4, classes=1, activation='sigmoid')
    elif model_name == "Segformer":
        model = smp.Segformer(encoder_name=encoder_name, encoder_weights=encoder_weights, in_channels=4, classes=1, activation='sigmoid')
    elif model_name == "DPT":
        model = smp.DPT(encoder_name=encoder_name, encoder_weights=encoder_weights, in_channels=4, classes=1, activation='sigmoid')
    else:
        raise ValueError(f"Unsupported model name: {model_name}")

    # Move the model to the device
    model.to(device)

    # Define the optimizer
    if optimizer_type == "Adadelta":
        optimizer = optim.Adadelta(model.parameters(), lr=lr)
    elif optimizer_type == "Adafactor":
        optimizer = optim.Adafactor(model.parameters(), lr=lr)
    elif optimizer_type == 'Adagrad':
        optimizer = optim.Adagrad(model.parameters(), lr=lr)
    elif optimizer_type == 'Adam':
        optimizer = optim.Adam(model.parameters(), lr=lr)
    elif optimizer_type == 'AdamW':
        optimizer = optim.AdamW(model.parameters(), lr=lr)
    elif optimizer_type == 'Adamax':
        optimizer = optim.Adamax(model.parameters(), lr=lr)
    elif optimizer_type == 'ASGD':
        optimizer = optim.ASGD(model.parameters(), lr=lr)
    elif optimizer_type == 'NAdam':
        optimizer = optim.NAdam(model.parameters(), lr=lr)
    elif optimizer_type == 'RAdam':
        optimizer = optim.RAdam(model.parameters(), lr=lr)
    elif optimizer_type == 'RMSprop':
        optimizer = optim.RMSprop(model.parameters(), lr=lr)
    elif optimizer_type == 'Rprop':
        optimizer = optim.Rprop(model.parameters(), lr=lr)
    elif optimizer_type == 'SGD':
        optimizer = optim.SGD(model.parameters(), lr=lr)
    else:
        raise ValueError(f"Unsupported optimizer type: {optimizer_type}")

    # Define the loss function
    if loss_function_type == 'FocalLoss':
        loss_function = FocalLoss(mode="binary")
    elif loss_function_type == 'DiceLoss':
        loss_function = DiceLoss(mode="binary")
    elif loss_function_type == 'LogDiceLoss':
        loss_function = DiceLoss(mode="binary", log_loss=True)
    elif loss_function_type == 'SoftBCEWithLogitsLoss':
        loss_function = SoftBCEWithLogitsLoss()
    elif loss_function_type == 'IOULoss':
        loss_function = JaccardLoss(mode="binary")
    elif loss_function_type == 'TverskyLoss':
        loss_function = TverskyLoss(mode="binary")
    elif loss_function_type == "LovaszLoss":
        loss_function = LovaszLoss(mode="binary")
    elif loss_function_type == 'CombinedLoss':
        bce_loss = SoftBCEWithLogitsLoss()
        log_dice_loss = DiceLoss(mode="binary", log_loss=True)
        loss_function = lambda outputs, labels: bce_loss(outputs, labels) + log_dice_loss(outputs, labels)
    else:
        raise ValueError(f"Unsupported loss function type: {loss_function_type}")

    print("-" * 50)
    print(f"Training with Model Architecture: {model_name}, Encoder: {encoder_name}, Weight: {encoder_weights}, Optimizer: {optimizer_type}, LR: {lr}, Loss Function: {loss_function_type}")

    # Early stopping parameters based on F1
    best_val_f1 = float('-inf')
    epochs_no_improve = 0

    train_losses = []
    train_dices = []
    train_focals = []
    train_bce = []
    train_accuracies = []
    train_f1_scores = []

    val_losses = []
    val_dices = []
    val_focals = []
    val_bce = []
    val_accuracies = []
    val_f1_scores = []

    for epoch in range(num_epochs):
        # Set the model to training mode
        model.train()

        running_loss = 0.0
        running_dice = 0.0
        running_focal = 0.0
        running_bce = 0.0
        running_accuracy = 0.0
        running_f1 = 0.0

        for i, (images, labels) in enumerate(train_loader):
            # Move data to the device
            images = images.to(device)
            labels = labels.to(device)

            # Zero the parameter gradients
            optimizer.zero_grad()

            # Forward pass
            outputs = model(images)

            # Calculate the loss
            loss = loss_function(outputs, labels)

            # Calculate other metrics (assuming these are still desired)
            # These metrics are independent of the chosen main loss function
            batch_dice = 1.0 - DiceLoss(mode="binary")(outputs, labels)
            batch_focal = FocalLoss(mode="binary")(outputs, labels)
            batch_bce = SoftBCEWithLogitsLoss()(outputs, labels)

            labels_long = labels.long()
            tp, fp, fn, tn = get_stats(outputs, labels_long, mode="binary", threshold=0.5)
            batch_accuracy = accuracy(tp, fp, fn, tn).mean()
            batch_f1 = f1_score(tp, fp, fn, tn).mean()

            # Backward pass and optimize
            loss.backward()
            optimizer.step()

            # Update running metrics
            running_loss += loss.item()
            running_focal += batch_focal.item()
            running_bce += batch_bce.item()
            running_dice += batch_dice.item()
            running_accuracy += batch_accuracy.item()
            running_f1 += batch_f1.item()


        train_losses.append(running_loss / len(train_loader))
        train_focals.append(running_focal / len(train_loader))
        train_bce.append(running_bce / len(train_loader))
        train_dices.append(running_dice / len(train_loader))
        train_accuracies.append(running_accuracy / len(train_loader))
        train_f1_scores.append(running_f1 / len(train_loader))


        # Print metrics
        if verbose and (epoch + 1) % 10 == 0:
            print(f'Epoch [{epoch+1}/{num_epochs}] finished. Training Loss: {train_losses[-1]:.4f}, Training Dice: {train_dices[-1]:.4f}, Training Focals: {train_focals[-1]:.4f}, Training BCE: {train_bce[-1]:.4f}, Training Accuracy: {train_accuracies[-1]:.4f}, Training F1: {train_f1_scores[-1]:.4f}')

        # Evaluation loop after each epoch
        # Set the model to evaluation mode
        model.eval()
        validation_loss = 0.0
        validation_dice = 0.0
        validation_focal = 0.0
        validation_bce = 0.0
        validation_accuracy = 0.0
        validation_f1 = 0.0


        # Disable gradient calculation for evaluation
        with torch.no_grad():
            for images, labels in val_loader:
                # Move data to the device
                images = images.to(device)
                labels = labels.to(device)

                # Forward pass
                outputs = model(images)

                # Calculate the loss
                loss = loss_function(outputs, labels)

                # Calculate other metrics
                batch_dice = 1.0 - DiceLoss(mode="binary")(outputs, labels)
                batch_focal = FocalLoss(mode="binary")(outputs, labels)
                batch_bce = SoftBCEWithLogitsLoss()(outputs, labels)

                labels_long = labels.long()
                tp, fp, fn, tn = get_stats(outputs, labels_long, mode="binary", threshold=0.5)
                batch_accuracy = accuracy(tp, fp, fn, tn).mean()
                batch_f1 = f1_score(tp, fp, fn, tn).mean()

                # Update running metrics
                validation_loss += loss.item()
                validation_dice += batch_dice.item()
                validation_focal += batch_focal.item()
                validation_bce += batch_bce.item()
                validation_accuracy += batch_accuracy.item()
                validation_f1 += batch_f1.item()

        average_validation_loss = validation_loss / len(val_loader)
        average_validation_dice = validation_dice / len(val_loader)
        average_validation_focal = validation_focal / len(val_loader)
        average_validation_bce = validation_bce / len(val_loader)
        average_validation_accuracy = validation_accuracy / len(val_loader)
        average_validation_f1 = validation_f1 / len(val_loader)

        val_losses.append(average_validation_loss)
        val_dices.append(average_validation_dice)
        val_focals.append(average_validation_focal)
        val_bce.append(average_validation_bce)
        val_accuracies.append(average_validation_accuracy)
        val_f1_scores.append(average_validation_f1)


        # Print metrics
        if verbose and (epoch + 1) % 10 == 0:
            print(f'Epoch [{epoch+1}/{num_epochs}] finished. Validation Loss: {val_losses[-1]:.4f}, Validation Dice: {val_dices[-1]:.4f}, Validation Focal: {val_focals[-1]:.4f}, Validation BCE: {val_bce[-1]:.4f}, Validation Accuracy: {val_accuracies[-1]:.4f}, Validation F1: {val_f1_scores[-1]:.4f}')


        if patience != 0:
            # Early stopping check
            if average_validation_f1 > best_val_f1:
                best_val_f1 = average_validation_f1
                epochs_no_improve = 0
            else:
                epochs_no_improve += 1
                if epochs_no_improve == patience:
                    print(f'Early stopping after {epoch+1} epochs.')
                    break # Stop training loop


    print('Finished Training')
    print(f'Training Loss:   {train_losses[-1]:.4f}, Training Dice:   {train_dices[-1]:.4f}, Training Focals:   {train_focals[-1]:.4f}, Training BCE:   {train_bce[-1]:.4f}, Training Accuracy:   {train_accuracies[-1]:.4f}, Training F1:   {train_f1_scores[-1]:.4f}')
    print(f'Validation Loss: {val_losses[-1]:.4f}, Validation Dice: {val_dices[-1]:.4f}, Validation Focals: {val_focals[-1]:.4f}, Validation BCE: {val_bce[-1]:.4f}, Validation Accuracy: {val_accuracies[-1]:.4f}, Validation F1: {val_f1_scores[-1]:.4f}')

    # Return the trained model and metrics
    return model, train_losses, train_dices, train_focals, train_bce, train_accuracies, train_f1_scores, val_losses, val_dices, val_focals, val_bce, val_accuracies, val_f1_scores
Using device: cuda

I define a helper function for plotting the various metrics. It takes as input a user selection of the model training data. In doing so, the plots for different choices can be visually inspected and analyzed.

# @title
def plot_selected(results, selected, plot_loss=True):
    if plot_loss:
        metrics = [['train_losses', 'val_losses'], ['train_dices', 'val_dices'], ['train_focals', 'val_focals'], ['train_bce', 'val_bce'], ['train_accuracies', 'val_accuracies'], ['train_f1_scores', 'val_f1_scores']]
    else:
        metrics = [['train_dices', 'val_dices'], ['train_focals', 'val_focals'], ['train_bce', 'val_bce'], ['train_accuracies', 'val_accuracies'], ['train_f1_scores', 'val_f1_scores']]
    for train_val_pair in metrics:
        plt.figure(figsize=(8, 4))
        for metric in train_val_pair:
            for combination in selected:
                plt.plot(results[combination][metric], label=f'{combination} - {metric.replace("_", " ").title()}')
        plt.xlabel("epoch")
        plt.ylabel("metric value")
        plt.title("metric")
        plt.legend()
        plt.grid(True)
        plt.show()

1 Encoder and Weights

I begin by training and testing a selection of model encoders and pretrained weights.

I then plot the results interactively. By pressing ‘Control+LeftClick’ you can select multiple encoder/weight combinations to visibly compare.

# @title
encoder_weight_results = {}

encoder_weight_pairs = [
    ("resnet34", "imagenet"),
    ("resnet152", "imagenet"),
    ("resnext101_32x8d", "imagenet"),
    ("dpn107", "imagenet+5k"),
    ("dpn131", "imagenet"),
    ("vgg19", "imagenet"),
    ("vgg19_bn", "imagenet"),
    ("senet154", "imagenet"),
    ("inceptionresnetv2", "imagenet"),
    ("inceptionresnetv2", "imagenet+background"),
    ("efficientnet-b7", "imagenet"),
    ("efficientnet-b7", "advprop"),
    ("timm-efficientnet-b8", "imagenet"),
    ("timm-efficientnet-b8", "advprop"),
    ("mit_b5", "imagenet"),
]

for encoder, weight in encoder_weight_pairs:
        model, train_losses, train_dices, train_focals, train_bce, train_accuracies, train_f1_scores, val_losses, val_dices, val_focals, val_bce, val_accuracies, val_f1_scores = train_model(
            num_epochs=250,
            patience=0,
            model_name="Unet",
            encoder_name=encoder,
            encoder_weights=weight,
            optimizer_type="Adam",
            lr=1e-4,
            loss_function_type="DiceLoss"
        )
        encoder_weight_results[f'{encoder}_{weight}'] = {
            'train_losses': train_losses,
            'train_dices': train_dices,
            'train_focals': train_focals,
            'train_bce': train_bce,
            'train_accuracies': train_accuracies,
            'train_f1_scores': train_f1_scores,
            'val_losses': val_losses,
            'val_dices': val_dices,
            'val_focals': val_focals,
            'val_bce': val_bce,
            'val_accuracies': val_accuracies,
            'val_f1_scores': val_f1_scores
        }
/usr/local/lib/python3.12/dist-packages/huggingface_hub/utils/_auth.py:94: UserWarning: 
The secret `HF_TOKEN` does not exist in your Colab secrets.
To authenticate with the Hugging Face Hub, create a token in your settings tab (https://huggingface.co/settings/tokens), set it as secret in your Google Colab and restart your session.
You will be able to reuse this secret in all of your notebooks.
Please note that authentication is recommended but still optional to access public models or datasets.
  warnings.warn(
--------------------------------------------------
Training with Model Architecture: Unet, Encoder: resnet34, Weight: imagenet, Optimizer: Adam, LR: 0.0001, Loss Function: DiceLoss
Finished Training
Training Loss:   0.7043, Training Dice:   0.2957, Training Focals:   0.1746, Training BCE:   0.6774, Training Accuracy:   0.9735, Training F1:   0.8963
Validation Loss: 0.7096, Validation Dice: 0.2904, Validation Focals: 0.1949, Validation BCE: 0.7225, Validation Accuracy: 0.8407, Validation F1: 0.1857
--------------------------------------------------
Training with Model Architecture: Unet, Encoder: resnet152, Weight: imagenet, Optimizer: Adam, LR: 0.0001, Loss Function: DiceLoss
Finished Training
Training Loss:   0.7085, Training Dice:   0.2915, Training Focals:   0.1887, Training BCE:   0.6991, Training Accuracy:   0.9741, Training F1:   0.8985
Validation Loss: 0.7000, Validation Dice: 0.3000, Validation Focals: 0.2072, Validation BCE: 0.7371, Validation Accuracy: 0.8606, Validation F1: 0.3658
--------------------------------------------------
Training with Model Architecture: Unet, Encoder: resnext101_32x8d, Weight: imagenet, Optimizer: Adam, LR: 0.0001, Loss Function: DiceLoss
Finished Training
Training Loss:   0.7096, Training Dice:   0.2904, Training Focals:   0.1921, Training BCE:   0.7042, Training Accuracy:   0.9726, Training F1:   0.8934
Validation Loss: 0.7078, Validation Dice: 0.2922, Validation Focals: 0.2029, Validation BCE: 0.7342, Validation Accuracy: 0.8507, Validation F1: 0.2514
--------------------------------------------------
Training with Model Architecture: Unet, Encoder: dpn107, Weight: imagenet+5k, Optimizer: Adam, LR: 0.0001, Loss Function: DiceLoss
Finished Training
Training Loss:   0.7081, Training Dice:   0.2919, Training Focals:   0.1873, Training BCE:   0.6970, Training Accuracy:   0.9737, Training F1:   0.8971
Validation Loss: 0.6933, Validation Dice: 0.3067, Validation Focals: 0.2031, Validation BCE: 0.7274, Validation Accuracy: 0.8650, Validation F1: 0.4719
--------------------------------------------------
Training with Model Architecture: Unet, Encoder: dpn131, Weight: imagenet, Optimizer: Adam, LR: 0.0001, Loss Function: DiceLoss
Finished Training
Training Loss:   0.7059, Training Dice:   0.2941, Training Focals:   0.1797, Training BCE:   0.6854, Training Accuracy:   0.9740, Training F1:   0.8981
Validation Loss: 0.7002, Validation Dice: 0.2998, Validation Focals: 0.1963, Validation BCE: 0.7207, Validation Accuracy: 0.8612, Validation F1: 0.3457
--------------------------------------------------
Training with Model Architecture: Unet, Encoder: vgg19, Weight: imagenet, Optimizer: Adam, LR: 0.0001, Loss Function: DiceLoss
Finished Training
Training Loss:   0.7060, Training Dice:   0.2940, Training Focals:   0.1802, Training BCE:   0.6862, Training Accuracy:   0.9750, Training F1:   0.9020
Validation Loss: 0.6896, Validation Dice: 0.3104, Validation Focals: 0.2003, Validation BCE: 0.7208, Validation Accuracy: 0.8615, Validation F1: 0.4960
--------------------------------------------------
Training with Model Architecture: Unet, Encoder: vgg19_bn, Weight: imagenet, Optimizer: Adam, LR: 0.0001, Loss Function: DiceLoss
Finished Training
Training Loss:   0.7069, Training Dice:   0.2931, Training Focals:   0.1810, Training BCE:   0.6876, Training Accuracy:   0.9738, Training F1:   0.8970
Validation Loss: 0.7032, Validation Dice: 0.2968, Validation Focals: 0.1981, Validation BCE: 0.7257, Validation Accuracy: 0.8582, Validation F1: 0.3114
--------------------------------------------------
Training with Model Architecture: Unet, Encoder: senet154, Weight: imagenet, Optimizer: Adam, LR: 0.0001, Loss Function: DiceLoss
Finished Training
Training Loss:   0.7069, Training Dice:   0.2931, Training Focals:   0.1831, Training BCE:   0.6904, Training Accuracy:   0.9720, Training F1:   0.8913
Validation Loss: 0.6820, Validation Dice: 0.3180, Validation Focals: 0.2048, Validation BCE: 0.7255, Validation Accuracy: 0.8810, Validation F1: 0.6122
--------------------------------------------------
Training with Model Architecture: Unet, Encoder: inceptionresnetv2, Weight: imagenet, Optimizer: Adam, LR: 0.0001, Loss Function: DiceLoss
Finished Training
Training Loss:   0.7038, Training Dice:   0.2962, Training Focals:   0.1722, Training BCE:   0.6737, Training Accuracy:   0.9741, Training F1:   0.8986
Validation Loss: 0.6965, Validation Dice: 0.3035, Validation Focals: 0.1919, Validation BCE: 0.7120, Validation Accuracy: 0.8551, Validation F1: 0.4254
--------------------------------------------------
Training with Model Architecture: Unet, Encoder: inceptionresnetv2, Weight: imagenet+background, Optimizer: Adam, LR: 0.0001, Loss Function: DiceLoss
Finished Training
Training Loss:   0.7088, Training Dice:   0.2912, Training Focals:   0.1898, Training BCE:   0.7005, Training Accuracy:   0.9709, Training F1:   0.8876
Validation Loss: 0.7028, Validation Dice: 0.2972, Validation Focals: 0.2017, Validation BCE: 0.7303, Validation Accuracy: 0.8504, Validation F1: 0.3043
--------------------------------------------------
Training with Model Architecture: Unet, Encoder: efficientnet-b7, Weight: imagenet, Optimizer: Adam, LR: 0.0001, Loss Function: DiceLoss
Finished Training
Training Loss:   0.7012, Training Dice:   0.2988, Training Focals:   0.1646, Training BCE:   0.6611, Training Accuracy:   0.9714, Training F1:   0.8891
Validation Loss: 0.6681, Validation Dice: 0.3319, Validation Focals: 0.2194, Validation BCE: 0.7311, Validation Accuracy: 0.8264, Validation F1: 0.5728
--------------------------------------------------
Training with Model Architecture: Unet, Encoder: efficientnet-b7, Weight: advprop, Optimizer: Adam, LR: 0.0001, Loss Function: DiceLoss
Finished Training
Training Loss:   0.7057, Training Dice:   0.2943, Training Focals:   0.1786, Training BCE:   0.6831, Training Accuracy:   0.9687, Training F1:   0.8801
Validation Loss: 0.6680, Validation Dice: 0.3320, Validation Focals: 0.1995, Validation BCE: 0.7110, Validation Accuracy: 0.8827, Validation F1: 0.6622
--------------------------------------------------
Training with Model Architecture: Unet, Encoder: timm-efficientnet-b8, Weight: imagenet, Optimizer: Adam, LR: 0.0001, Loss Function: DiceLoss
Finished Training
Training Loss:   0.7059, Training Dice:   0.2941, Training Focals:   0.1800, Training BCE:   0.6852, Training Accuracy:   0.9680, Training F1:   0.8782
Validation Loss: 0.6708, Validation Dice: 0.3292, Validation Focals: 0.1971, Validation BCE: 0.7088, Validation Accuracy: 0.8835, Validation F1: 0.6499
--------------------------------------------------
Training with Model Architecture: Unet, Encoder: timm-efficientnet-b8, Weight: advprop, Optimizer: Adam, LR: 0.0001, Loss Function: DiceLoss
Finished Training
Training Loss:   0.7040, Training Dice:   0.2960, Training Focals:   0.1727, Training BCE:   0.6742, Training Accuracy:   0.9714, Training F1:   0.8898
Validation Loss: 0.6712, Validation Dice: 0.3288, Validation Focals: 0.1862, Validation BCE: 0.6952, Validation Accuracy: 0.8937, Validation F1: 0.6494
--------------------------------------------------
Training with Model Architecture: Unet, Encoder: mit_b5, Weight: imagenet, Optimizer: Adam, LR: 0.0001, Loss Function: DiceLoss
Finished Training
Training Loss:   0.7045, Training Dice:   0.2955, Training Focals:   0.1747, Training BCE:   0.6773, Training Accuracy:   0.9711, Training F1:   0.8887
Validation Loss: 0.6740, Validation Dice: 0.3260, Validation Focals: 0.1907, Validation BCE: 0.7017, Validation Accuracy: 0.8889, Validation F1: 0.6362
# @title
%matplotlib inline
options_encoder_weights = list(encoder_weight_results.keys())
encoder_weights_dropdown = SelectMultiple(options=options_encoder_weights, value=[options_encoder_weights[0]], description='Encoders + Weights:')
def plot_selected_encoder_weights(selected):
    plot_selected(encoder_weight_results, selected)
encoder_weights_plot = interactive(plot_selected_encoder_weights, selected=encoder_weights_dropdown)
encoder_weights_plot

1.1 Conclusions - Model Encoder and Weights

We test the model encoder and encoder weight pairs with the following fixed choices: Architecture: Unet, Optimizer: Adam, LR: 1e-4, Loss Function: Dice Loss

From inspection, the best performing model encoder / weights pairs were: - senet154 / imagenet - good results initially but surpassed with further training by other encoder/weight pairs - efficientnet-b7 / advprop - a slower initial curve than the pair efficientnet-b7 / imagenet, but surpassed with enough epochs. Performed worse initially for accuracy and F1 scores. - timm_efficientnet-b8 / advprop - some of the best results but with a curve that slows, possible with further epochs would be surpassed by efficientnet-b7 / advprop - mit_b5 - performed well across the board, but surpassed at later epochs. Of particular note, the training and validation scores stayed consistently close.

We further observe: - resnet34 / imagenet, resnet152 / imagenet, resnest101_32x8d / imagenet - The validation scores for multiple metrics decreases with further epochs, suggestive of overfitting

The two best performers appeared to be timm_ifficientnet-b8 / advprop and mit_b5 / imagenet. From the first pass, mit_b5 was the most consistent baseline, so I will use that to test the other model choices and perhaps revisit after further testing.

2 Model Architecture

# @title
model_architecture_results = {}

model_architectures = ['Unet', 'FPN', 'PSPNet', 'DeepLabV3', 'DeepLabV3Plus', 'MAnet', 'PAN', 'UPerNet', 'Segformer']
# incompatible with mit_b5: UnetPlusPlus, Linknet, DPT

for model_architecture in model_architectures:
        model, train_losses, train_dices, train_focals, train_bce, train_accuracies, train_f1_scores, val_losses, val_dices, val_focals, val_bce, val_accuracies, val_f1_scores = train_model(
            num_epochs=250,
            patience=0,
            model_name=model_architecture,
            encoder_name="mit_b5",
            encoder_weights="imagenet",
            optimizer_type="Adam",
            lr=1e-4,
            loss_function_type="DiceLoss"
        )
        model_architecture_results[model_architecture] = {
            'train_losses': train_losses,
            'train_dices': train_dices,
            'train_focals': train_focals,
            'train_bce': train_bce,
            'train_accuracies': train_accuracies,
            'train_f1_scores': train_f1_scores,
            'val_losses': val_losses,
            'val_dices': val_dices,
            'val_focals': val_focals,
            'val_bce': val_bce,
            'val_accuracies': val_accuracies,
            'val_f1_scores': val_f1_scores
        }
--------------------------------------------------
Training with Model Architecture: Unet, Encoder: mit_b5, Weight: imagenet, Optimizer: Adam, LR: 0.0001, Loss Function: DiceLoss
Finished Training
Training Loss:   0.7043, Training Dice:   0.2957, Training Focals:   0.1713, Training BCE:   0.6724, Training Accuracy:   0.9724, Training F1:   0.8927
Validation Loss: 0.6687, Validation Dice: 0.3313, Validation Focals: 0.1920, Validation BCE: 0.7003, Validation Accuracy: 0.8883, Validation F1: 0.6722
--------------------------------------------------
Training with Model Architecture: FPN, Encoder: mit_b5, Weight: imagenet, Optimizer: Adam, LR: 0.0001, Loss Function: DiceLoss
Finished Training
Training Loss:   0.6985, Training Dice:   0.3015, Training Focals:   0.1592, Training BCE:   0.6508, Training Accuracy:   0.9674, Training F1:   0.8780
Validation Loss: 0.6618, Validation Dice: 0.3382, Validation Focals: 0.1780, Validation BCE: 0.6760, Validation Accuracy: 0.8896, Validation F1: 0.6770
--------------------------------------------------
Training with Model Architecture: PSPNet, Encoder: mit_b5, Weight: imagenet, Optimizer: Adam, LR: 0.0001, Loss Function: DiceLoss
Finished Training
Training Loss:   0.6992, Training Dice:   0.3008, Training Focals:   0.1612, Training BCE:   0.6537, Training Accuracy:   0.9629, Training F1:   0.8632
Validation Loss: 0.6732, Validation Dice: 0.3268, Validation Focals: 0.1788, Validation BCE: 0.6818, Validation Accuracy: 0.8774, Validation F1: 0.6059
--------------------------------------------------
Training with Model Architecture: DeepLabV3, Encoder: mit_b5, Weight: imagenet, Optimizer: Adam, LR: 0.0001, Loss Function: DiceLoss
Finished Training
Training Loss:   0.7014, Training Dice:   0.2986, Training Focals:   0.1667, Training BCE:   0.6627, Training Accuracy:   0.9605, Training F1:   0.8540
Validation Loss: 0.6661, Validation Dice: 0.3339, Validation Focals: 0.1868, Validation BCE: 0.6901, Validation Accuracy: 0.8791, Validation F1: 0.6467
--------------------------------------------------
Training with Model Architecture: DeepLabV3Plus, Encoder: mit_b5, Weight: imagenet, Optimizer: Adam, LR: 0.0001, Loss Function: DiceLoss
Finished Training
Training Loss:   0.7032, Training Dice:   0.2968, Training Focals:   0.1731, Training BCE:   0.6719, Training Accuracy:   0.9531, Training F1:   0.8306
Validation Loss: 0.6687, Validation Dice: 0.3313, Validation Focals: 0.2019, Validation BCE: 0.7115, Validation Accuracy: 0.8626, Validation F1: 0.6182
--------------------------------------------------
Training with Model Architecture: MAnet, Encoder: mit_b5, Weight: imagenet, Optimizer: Adam, LR: 0.0001, Loss Function: DiceLoss
Finished Training
Training Loss:   0.7038, Training Dice:   0.2962, Training Focals:   0.1728, Training BCE:   0.6740, Training Accuracy:   0.9703, Training F1:   0.8861
Validation Loss: 0.6738, Validation Dice: 0.3262, Validation Focals: 0.1910, Validation BCE: 0.7010, Validation Accuracy: 0.8819, Validation F1: 0.6212
--------------------------------------------------
Training with Model Architecture: PAN, Encoder: mit_b5, Weight: imagenet, Optimizer: Adam, LR: 0.0001, Loss Function: DiceLoss
Finished Training
Training Loss:   0.6991, Training Dice:   0.3009, Training Focals:   0.1602, Training BCE:   0.6526, Training Accuracy:   0.9656, Training F1:   0.8707
Validation Loss: 0.6662, Validation Dice: 0.3338, Validation Focals: 0.1883, Validation BCE: 0.6904, Validation Accuracy: 0.8678, Validation F1: 0.6262
--------------------------------------------------
Training with Model Architecture: UPerNet, Encoder: mit_b5, Weight: imagenet, Optimizer: Adam, LR: 0.0001, Loss Function: DiceLoss
Finished Training
Training Loss:   0.6981, Training Dice:   0.3019, Training Focals:   0.1577, Training BCE:   0.6495, Training Accuracy:   0.9720, Training F1:   0.8928
Validation Loss: 0.6635, Validation Dice: 0.3365, Validation Focals: 0.1774, Validation BCE: 0.6769, Validation Accuracy: 0.8933, Validation F1: 0.6824
--------------------------------------------------
Training with Model Architecture: Segformer, Encoder: mit_b5, Weight: imagenet, Optimizer: Adam, LR: 0.0001, Loss Function: DiceLoss
Finished Training
Training Loss:   0.6988, Training Dice:   0.3012, Training Focals:   0.1602, Training BCE:   0.6525, Training Accuracy:   0.9668, Training F1:   0.8747
Validation Loss: 0.6695, Validation Dice: 0.3305, Validation Focals: 0.1814, Validation BCE: 0.6834, Validation Accuracy: 0.8764, Validation F1: 0.6282
# @title
%matplotlib inline

model_architecture_combinations = list(model_architecture_results.keys())
model_architecture_dropdown = SelectMultiple(options=model_architecture_combinations, value=[model_architecture_combinations[0]], description='Optimizers + LRs:')
def plot_selected_model(selected):
    plot_selected(model_architecture_results, selected)
model_architecture_plot = interactive(plot_selected_model, selected=model_architecture_dropdown)
model_architecture_plot

2.1 Conclusion - Model Architecture

We test the model architecture with the following fixed choices: Model encoder / weights: mit_b5 / imagenet, Optimizer: Adam, LR: 1e-4, Loss Function: Dice Loss

We observer: - The best performers were FPN (although a bit noisy), UPerNet, Segformer - DeepLabV3 outperformed DeepLabV3 slightly.

Overall best appears to be UPerNet. In particular, for the given choices the curves were generally smoother with less variance.

3 Optimizers

# @title
optimizer_results = {}

optimizers = ['Adadelta', 'Adafactor', 'Adagrad', 'Adam', 'AdamW', 'Adamax', 'ASGD', 'NAdam', 'RAdam', 'RMSprop', 'Rprop', 'SGD']

for optimizer_type in optimizers:
        model, train_losses, train_dices, train_focals, train_bce, train_accuracies, train_f1_scores, val_losses, val_dices, val_focals, val_bce, val_accuracies, val_f1_scores = train_model(
            num_epochs=250,
            patience=0,
            model_name="UPerNet",
            encoder_name="mit_b5",
            encoder_weights="imagenet",
            optimizer_type=optimizer_type,
            lr=1e-4,
            loss_function_type="DiceLoss"
        )
        optimizer_results[optimizer_type] = {
            'train_losses': train_losses,
            'train_dices': train_dices,
            'train_focals': train_focals,
            'train_bce': train_bce,
            'train_accuracies': train_accuracies,
            'train_f1_scores': train_f1_scores,
            'val_losses': val_losses,
            'val_dices': val_dices,
            'val_focals': val_focals,
            'val_bce': val_bce,
            'val_accuracies': val_accuracies,
            'val_f1_scores': val_f1_scores
        }
--------------------------------------------------
Training with Model Architecture: UPerNet, Encoder: mit_b5, Weight: imagenet, Optimizer: Adadelta, LR: 0.0001, Loss Function: DiceLoss
Finished Training
Training Loss:   0.7756, Training Dice:   0.2244, Training Focals:   0.2684, Training BCE:   0.8249, Training Accuracy:   0.7863, Training F1:   0.0766
Validation Loss: 0.7135, Validation Dice: 0.2865, Validation Focals: 0.2667, Validation BCE: 0.8181, Validation Accuracy: 0.7354, Validation F1: 0.1240
--------------------------------------------------
Training with Model Architecture: UPerNet, Encoder: mit_b5, Weight: imagenet, Optimizer: Adafactor, LR: 0.0001, Loss Function: DiceLoss
Finished Training
Training Loss:   0.7041, Training Dice:   0.2959, Training Focals:   0.1804, Training BCE:   0.6790, Training Accuracy:   0.9315, Training F1:   0.7806
Validation Loss: 0.6713, Validation Dice: 0.3287, Validation Focals: 0.1911, Validation BCE: 0.6969, Validation Accuracy: 0.8680, Validation F1: 0.6122
--------------------------------------------------
Training with Model Architecture: UPerNet, Encoder: mit_b5, Weight: imagenet, Optimizer: Adagrad, LR: 0.0001, Loss Function: DiceLoss
Finished Training
Training Loss:   0.7053, Training Dice:   0.2947, Training Focals:   0.1869, Training BCE:   0.6862, Training Accuracy:   0.9207, Training F1:   0.8119
Validation Loss: 0.6743, Validation Dice: 0.3257, Validation Focals: 0.1891, Validation BCE: 0.6958, Validation Accuracy: 0.8658, Validation F1: 0.5929
--------------------------------------------------
Training with Model Architecture: UPerNet, Encoder: mit_b5, Weight: imagenet, Optimizer: Adam, LR: 0.0001, Loss Function: DiceLoss
Finished Training
Training Loss:   0.6981, Training Dice:   0.3019, Training Focals:   0.1572, Training BCE:   0.6488, Training Accuracy:   0.9731, Training F1:   0.8969
Validation Loss: 0.6609, Validation Dice: 0.3391, Validation Focals: 0.1750, Validation BCE: 0.6729, Validation Accuracy: 0.8967, Validation F1: 0.6951
--------------------------------------------------
Training with Model Architecture: UPerNet, Encoder: mit_b5, Weight: imagenet, Optimizer: AdamW, LR: 0.0001, Loss Function: DiceLoss
Finished Training
Training Loss:   0.6979, Training Dice:   0.3021, Training Focals:   0.1567, Training BCE:   0.6482, Training Accuracy:   0.9738, Training F1:   0.8977
Validation Loss: 0.6642, Validation Dice: 0.3358, Validation Focals: 0.1780, Validation BCE: 0.6775, Validation Accuracy: 0.8897, Validation F1: 0.6719
--------------------------------------------------
Training with Model Architecture: UPerNet, Encoder: mit_b5, Weight: imagenet, Optimizer: Adamax, LR: 0.0001, Loss Function: DiceLoss
Finished Training
Training Loss:   0.6998, Training Dice:   0.3002, Training Focals:   0.1624, Training BCE:   0.6559, Training Accuracy:   0.9644, Training F1:   0.8667
Validation Loss: 0.6675, Validation Dice: 0.3325, Validation Focals: 0.1834, Validation BCE: 0.6859, Validation Accuracy: 0.8799, Validation F1: 0.6440
--------------------------------------------------
Training with Model Architecture: UPerNet, Encoder: mit_b5, Weight: imagenet, Optimizer: ASGD, LR: 0.0001, Loss Function: DiceLoss
Finished Training
Training Loss:   0.7642, Training Dice:   0.2358, Training Focals:   0.3555, Training BCE:   0.9220, Training Accuracy:   0.4656, Training F1:   0.2447
Validation Loss: 0.7032, Validation Dice: 0.2968, Validation Focals: 0.3583, Validation BCE: 0.9171, Validation Accuracy: 0.4056, Validation F1: 0.2895
--------------------------------------------------
Training with Model Architecture: UPerNet, Encoder: mit_b5, Weight: imagenet, Optimizer: NAdam, LR: 0.0001, Loss Function: DiceLoss
Finished Training
Training Loss:   0.6989, Training Dice:   0.3011, Training Focals:   0.1621, Training BCE:   0.6548, Training Accuracy:   0.9612, Training F1:   0.8574
Validation Loss: 0.6624, Validation Dice: 0.3376, Validation Focals: 0.1771, Validation BCE: 0.6761, Validation Accuracy: 0.8938, Validation F1: 0.6845
--------------------------------------------------
Training with Model Architecture: UPerNet, Encoder: mit_b5, Weight: imagenet, Optimizer: RAdam, LR: 0.0001, Loss Function: DiceLoss
Finished Training
Training Loss:   0.7029, Training Dice:   0.2971, Training Focals:   0.1750, Training BCE:   0.6718, Training Accuracy:   0.9410, Training F1:   0.8184
Validation Loss: 0.6706, Validation Dice: 0.3294, Validation Focals: 0.1907, Validation BCE: 0.6967, Validation Accuracy: 0.8695, Validation F1: 0.6217
--------------------------------------------------
Training with Model Architecture: UPerNet, Encoder: mit_b5, Weight: imagenet, Optimizer: RMSprop, LR: 0.0001, Loss Function: DiceLoss
Finished Training
Training Loss:   0.6980, Training Dice:   0.3020, Training Focals:   0.1566, Training BCE:   0.6480, Training Accuracy:   0.9742, Training F1:   0.8985
Validation Loss: 0.6655, Validation Dice: 0.3345, Validation Focals: 0.1813, Validation BCE: 0.6817, Validation Accuracy: 0.8804, Validation F1: 0.6443
--------------------------------------------------
Training with Model Architecture: UPerNet, Encoder: mit_b5, Weight: imagenet, Optimizer: Rprop, LR: 0.0001, Loss Function: DiceLoss
Finished Training
Training Loss:   0.6975, Training Dice:   0.3025, Training Focals:   0.1562, Training BCE:   0.6470, Training Accuracy:   0.9736, Training F1:   0.8976
Validation Loss: 0.6663, Validation Dice: 0.3337, Validation Focals: 0.1726, Validation BCE: 0.6716, Validation Accuracy: 0.8966, Validation F1: 0.6773
--------------------------------------------------
Training with Model Architecture: UPerNet, Encoder: mit_b5, Weight: imagenet, Optimizer: SGD, LR: 0.0001, Loss Function: DiceLoss
Finished Training
Training Loss:   0.7642, Training Dice:   0.2358, Training Focals:   0.3692, Training BCE:   0.9369, Training Accuracy:   0.4159, Training F1:   0.2425
Validation Loss: 0.7048, Validation Dice: 0.2952, Validation Focals: 0.3484, Validation BCE: 0.9070, Validation Accuracy: 0.4362, Validation F1: 0.2807
# @title
%matplotlib inline

optimizer_combinations = list(optimizer_results.keys())
optimizers_dropdown = SelectMultiple(options=optimizer_combinations, value=[optimizer_combinations[0]], description='Optimizers:')
def plot_selected_optimizers(selected):
    plot_selected(optimizer_results, selected)
optimizers_plot = interactive(plot_selected_optimizers, selected=optimizers_dropdown)
optimizers_plot

3.1 Conclusions - Optimizers

We test the optimizers with the following fixed choices: Model Architecture: UPerNet, Model encoder / weights: mit_b5 / imagenet, LR: 1e-4, Loss Function: Dice Loss

We observe: - Adadelta, ASGD, SGD - the validation curves showed minimal improvement and were noisy. I would suspect further hyperparameter tweaks would be necessary for these optimizers. - Adam, AdamW - Quite comparable curves and performance, with the edge to Adam.

The best optimizers appeared to be Adam and Rprop.

4 Loss functions

# @title
loss_results = {}

loss_functions = ['FocalLoss', 'DiceLoss', 'SoftBCEWithLogitsLoss', 'IOULoss', 'TverskyLoss', 'LovaszLoss', 'CombinedLoss']

for loss_function in loss_functions:
    model, train_losses, train_dices, train_focals, train_bce, train_accuracies, train_f1_scores, val_losses, val_dices, val_focals, val_bce, val_accuracies, val_f1_scores = train_model(
        num_epochs=250,
        patience=0,
        model_name="UPerNet",
        encoder_name="mit_b5",
        encoder_weights="imagenet",
        optimizer_type="Adam",
        lr=1e-4,
        loss_function_type=loss_function
    )
    loss_results[loss_function] = {
        'train_losses': train_losses,
        'train_dices': train_dices,
        'train_focals': train_focals,
        'train_bce': train_bce,
        'train_accuracies': train_accuracies,
        'train_f1_scores': train_f1_scores,
        'val_losses': val_losses,
        'val_dices': val_dices,
        'val_focals': val_focals,
        'val_bce': val_bce,
        'val_accuracies': val_accuracies,
        'val_f1_scores': val_f1_scores
    }
--------------------------------------------------
Training with Model Architecture: UPerNet, Encoder: mit_b5, Weight: imagenet, Optimizer: Adam, LR: 0.0001, Loss Function: FocalLoss
Finished Training
Training Loss:   0.1567, Training Dice:   0.2973, Training Focals:   0.1567, Training BCE:   0.6499, Training Accuracy:   0.9835, Training F1:   0.9313
Validation Loss: 0.1730, Validation Dice: 0.3325, Validation Focals: 0.1730, Validation BCE: 0.6739, Validation Accuracy: 0.9040, Validation F1: 0.6948
--------------------------------------------------
Training with Model Architecture: UPerNet, Encoder: mit_b5, Weight: imagenet, Optimizer: Adam, LR: 0.0001, Loss Function: DiceLoss
Finished Training
Training Loss:   0.6983, Training Dice:   0.3017, Training Focals:   0.1586, Training BCE:   0.6506, Training Accuracy:   0.9704, Training F1:   0.8880
Validation Loss: 0.6638, Validation Dice: 0.3362, Validation Focals: 0.1776, Validation BCE: 0.6774, Validation Accuracy: 0.8915, Validation F1: 0.6757
--------------------------------------------------
Training with Model Architecture: UPerNet, Encoder: mit_b5, Weight: imagenet, Optimizer: Adam, LR: 0.0001, Loss Function: SoftBCEWithLogitsLoss
Finished Training
Training Loss:   0.6490, Training Dice:   0.2987, Training Focals:   0.1564, Training BCE:   0.6490, Training Accuracy:   0.9822, Training F1:   0.9263
Validation Loss: 0.6786, Validation Dice: 0.3261, Validation Focals: 0.1752, Validation BCE: 0.6786, Validation Accuracy: 0.8907, Validation F1: 0.6356
--------------------------------------------------
Training with Model Architecture: UPerNet, Encoder: mit_b5, Weight: imagenet, Optimizer: Adam, LR: 0.0001, Loss Function: IOULoss
Finished Training
Training Loss:   0.8222, Training Dice:   0.3019, Training Focals:   0.1575, Training BCE:   0.6493, Training Accuracy:   0.9724, Training F1:   0.8931
Validation Loss: 0.7968, Validation Dice: 0.3377, Validation Focals: 0.1749, Validation BCE: 0.6732, Validation Accuracy: 0.8961, Validation F1: 0.6918
--------------------------------------------------
Training with Model Architecture: UPerNet, Encoder: mit_b5, Weight: imagenet, Optimizer: Adam, LR: 0.0001, Loss Function: TverskyLoss
Finished Training
Training Loss:   0.6983, Training Dice:   0.3017, Training Focals:   0.1585, Training BCE:   0.6505, Training Accuracy:   0.9707, Training F1:   0.8894
Validation Loss: 0.6641, Validation Dice: 0.3359, Validation Focals: 0.1759, Validation BCE: 0.6754, Validation Accuracy: 0.8943, Validation F1: 0.6780
--------------------------------------------------
Training with Model Architecture: UPerNet, Encoder: mit_b5, Weight: imagenet, Optimizer: Adam, LR: 0.0001, Loss Function: LovaszLoss
Finished Training
Training Loss:   0.8903, Training Dice:   0.2961, Training Focals:   0.1568, Training BCE:   0.6503, Training Accuracy:   0.9851, Training F1:   0.9372
Validation Loss: 1.0255, Validation Dice: 0.3335, Validation Focals: 0.1722, Validation BCE: 0.6725, Validation Accuracy: 0.9064, Validation F1: 0.7019
--------------------------------------------------
Training with Model Architecture: UPerNet, Encoder: mit_b5, Weight: imagenet, Optimizer: Adam, LR: 0.0001, Loss Function: CombinedLoss
Finished Training
Training Loss:   1.8479, Training Dice:   0.3015, Training Focals:   0.1570, Training BCE:   0.6489, Training Accuracy:   0.9759, Training F1:   0.9051
Validation Loss: 1.7742, Validation Dice: 0.3341, Validation Focals: 0.1777, Validation BCE: 0.6780, Validation Accuracy: 0.8895, Validation F1: 0.6712
# @title
%matplotlib inline

options_loss_functions = list(loss_results.keys())
loss_functions_dropdown = SelectMultiple(options=options_loss_functions, value=[options_loss_functions[0]], description='Loss Functions:')
def plot_selected_loss(selected):
    plot_selected(loss_results, selected, plot_loss=False)
loss_plot = interactive(plot_selected_loss, selected=loss_functions_dropdown)
loss_plot

4.1 Conclusions - Loss Functions

The loss functions generally yielded similar results, without much differentiaton. This may in part be due to the fact that the other optimizations have made it hard to distinguish differences at this scale.

As it stands, I think that the combined loss function is a very reasonable choice.

5 Results:

  • Model Encoder and Encoder Weights: mit_b5 / imagenet
  • Model Architecture: UPerNet
  • Optimizer: Adam
  • Learning Rate: 1e-4
  • Loss Function: Combined Loss (Focal + LogDice)