src.train

  1import matplotlib.pyplot as plt
  2import numpy as np
  3import torch
  4from rich import print
  5from rich.progress import track
  6from torch import nn
  7from torch.nn import MSELoss
  8from torch.optim import Optimizer
  9from torch.optim import SGD
 10from torch.utils.data import DataLoader
 11from torch.utils.tensorboard.writer import SummaryWriter
 12
 13
 14def training_iteration(
 15    model: nn.Module,
 16    loss_fn: nn.Module,
 17    optimizer: Optimizer,
 18    dataloader_train: DataLoader,
 19    global_step: int,
 20    writer: SummaryWriter,
 21) -> np.floating:
 22    """Perform a single training iteration on the DataLoader.  Average losses are recorded and saved to Tensorboard logs.
 23
 24    Args:
 25        model (nn.Module): Torch model.
 26        loss_fn (nn.Module): Torch loss.
 27        optimizer (Optimizer): Torch optimizer.
 28        dataloader_train (DataLoader): DataLoader that outputs `(x, y)` where `x` is input and `y` is the true label.
 29        global_step (int): The global step for tracking this training iteration.
 30        writer (SummaryWriter): Tensorboard writer.
 31
 32    Returns:
 33        np.floating: Average training loss for this iteration.
 34    """
 35    # Initialization
 36    train_losses = []
 37
 38    for x, y in track(dataloader_train, description="training"):
 39        # fmt: off
 40        y_hat, _ = model(x)                 # predict
 41        loss = loss_fn(y_hat, y.long())     # calculate loss
 42        optimizer.zero_grad()               # zero the gradients
 43        loss.backward()                     # backpropagation
 44        optimizer.step()                    # update the weights
 45        train_losses.append(loss.item())    # save off the loss
 46        # fmt: on
 47
 48    # Record the average training loss for this training iteration
 49    avg_train_loss = np.average(train_losses)
 50    writer.add_scalar(tag="Loss/train", scalar_value=avg_train_loss, global_step=global_step)
 51
 52    return avg_train_loss
 53
 54
 55def generate_canocial(
 56    model: nn.Module,
 57    model_weights_path: str,
 58    n_epochs: int = 10,
 59    n_steps: int = 100,
 60):
 61    r"""The idea behind a canocial input is that it should be the input that maximizes the predicted value of a network.  Think of this as `inverse` training rather than standard training.  You want to specify an output and ask the network what is the corresponding input.
 62
 63    The way to achieve this is by freezing all of the layers of a network and setting $y_{true}$ to your target class.  When performing backpropagation via $loss=\hat{y} - y_{true}$ you backpropagate the gradients all the way to the input.
 64
 65    The theory is that once the losses converge to zero, the input should represent the maximum values needed to push the predictions of your neural network to the maximum for a certain class.
 66
 67    Args:
 68        model (nn.Module): Torch model
 69        model_weights_path (str): Path to model saved weights.
 70        n_epochs (int, optional): Number of epochs to perform training. Defaults to 10.
 71        n_steps (int, optional): Number of steps within an epoch. Defaults to 100.
 72    """
 73
 74    # Create an image to start inverse training
 75    input = torch.rand((1, 28, 28))  # assume 28x28 image
 76    input.requires_grad = True  # set to make sure input can be adjusted
 77
 78    # Create embedding visualization
 79    model.load_state_dict(torch.load(model_weights_path))
 80
 81    # Freeze all parameters in the network
 82    for param in model.parameters():
 83        param.requires_grad = False
 84
 85    # Setup optimizer
 86    optimizer = SGD([input], lr=0.001)
 87    loss_fn = MSELoss()
 88
 89    target = torch.Tensor([10, -10, -10, -10, -10, -10, -10, -10, -10, -10])
 90    images = []
 91
 92    # Perform training epochs
 93    for ii in range(0, n_epochs):
 94        losses = []
 95        for jj in range(0, n_steps):
 96            pred, _ = model(input)
 97            loss = loss_fn(pred, target)
 98            optimizer.zero_grad()
 99            loss.backward()
100            optimizer.step()
101            losses.append(loss.item())
102
103        image = input.squeeze().clone().detach().numpy()
104        images.append(image)
105        print(f"Generative loss: {np.mean(losses)}")
106
107    # Draw images
108    for ii in range(1, len(images)):
109        ax = plt.subplot(1, len(images), ii)
110        ax.imshow(images[ii])
def training_iteration( model: torch.nn.modules.module.Module, loss_fn: torch.nn.modules.module.Module, optimizer: torch.optim.optimizer.Optimizer, dataloader_train: torch.utils.data.dataloader.DataLoader, global_step: int, writer: torch.utils.tensorboard.writer.SummaryWriter) -> numpy.floating:
15def training_iteration(
16    model: nn.Module,
17    loss_fn: nn.Module,
18    optimizer: Optimizer,
19    dataloader_train: DataLoader,
20    global_step: int,
21    writer: SummaryWriter,
22) -> np.floating:
23    """Perform a single training iteration on the DataLoader.  Average losses are recorded and saved to Tensorboard logs.
24
25    Args:
26        model (nn.Module): Torch model.
27        loss_fn (nn.Module): Torch loss.
28        optimizer (Optimizer): Torch optimizer.
29        dataloader_train (DataLoader): DataLoader that outputs `(x, y)` where `x` is input and `y` is the true label.
30        global_step (int): The global step for tracking this training iteration.
31        writer (SummaryWriter): Tensorboard writer.
32
33    Returns:
34        np.floating: Average training loss for this iteration.
35    """
36    # Initialization
37    train_losses = []
38
39    for x, y in track(dataloader_train, description="training"):
40        # fmt: off
41        y_hat, _ = model(x)                 # predict
42        loss = loss_fn(y_hat, y.long())     # calculate loss
43        optimizer.zero_grad()               # zero the gradients
44        loss.backward()                     # backpropagation
45        optimizer.step()                    # update the weights
46        train_losses.append(loss.item())    # save off the loss
47        # fmt: on
48
49    # Record the average training loss for this training iteration
50    avg_train_loss = np.average(train_losses)
51    writer.add_scalar(tag="Loss/train", scalar_value=avg_train_loss, global_step=global_step)
52
53    return avg_train_loss

Perform a single training iteration on the DataLoader. Average losses are recorded and saved to Tensorboard logs.

Arguments:
  • model (nn.Module): Torch model.
  • loss_fn (nn.Module): Torch loss.
  • optimizer (Optimizer): Torch optimizer.
  • dataloader_train (DataLoader): DataLoader that outputs (x, y) where x is input and y is the true label.
  • global_step (int): The global step for tracking this training iteration.
  • writer (SummaryWriter): Tensorboard writer.
Returns:

np.floating: Average training loss for this iteration.

def generate_canocial( model: torch.nn.modules.module.Module, model_weights_path: str, n_epochs: int = 10, n_steps: int = 100):
 56def generate_canocial(
 57    model: nn.Module,
 58    model_weights_path: str,
 59    n_epochs: int = 10,
 60    n_steps: int = 100,
 61):
 62    r"""The idea behind a canocial input is that it should be the input that maximizes the predicted value of a network.  Think of this as `inverse` training rather than standard training.  You want to specify an output and ask the network what is the corresponding input.
 63
 64    The way to achieve this is by freezing all of the layers of a network and setting $y_{true}$ to your target class.  When performing backpropagation via $loss=\hat{y} - y_{true}$ you backpropagate the gradients all the way to the input.
 65
 66    The theory is that once the losses converge to zero, the input should represent the maximum values needed to push the predictions of your neural network to the maximum for a certain class.
 67
 68    Args:
 69        model (nn.Module): Torch model
 70        model_weights_path (str): Path to model saved weights.
 71        n_epochs (int, optional): Number of epochs to perform training. Defaults to 10.
 72        n_steps (int, optional): Number of steps within an epoch. Defaults to 100.
 73    """
 74
 75    # Create an image to start inverse training
 76    input = torch.rand((1, 28, 28))  # assume 28x28 image
 77    input.requires_grad = True  # set to make sure input can be adjusted
 78
 79    # Create embedding visualization
 80    model.load_state_dict(torch.load(model_weights_path))
 81
 82    # Freeze all parameters in the network
 83    for param in model.parameters():
 84        param.requires_grad = False
 85
 86    # Setup optimizer
 87    optimizer = SGD([input], lr=0.001)
 88    loss_fn = MSELoss()
 89
 90    target = torch.Tensor([10, -10, -10, -10, -10, -10, -10, -10, -10, -10])
 91    images = []
 92
 93    # Perform training epochs
 94    for ii in range(0, n_epochs):
 95        losses = []
 96        for jj in range(0, n_steps):
 97            pred, _ = model(input)
 98            loss = loss_fn(pred, target)
 99            optimizer.zero_grad()
100            loss.backward()
101            optimizer.step()
102            losses.append(loss.item())
103
104        image = input.squeeze().clone().detach().numpy()
105        images.append(image)
106        print(f"Generative loss: {np.mean(losses)}")
107
108    # Draw images
109    for ii in range(1, len(images)):
110        ax = plt.subplot(1, len(images), ii)
111        ax.imshow(images[ii])

The idea behind a canocial input is that it should be the input that maximizes the predicted value of a network. Think of this as inverse training rather than standard training. You want to specify an output and ask the network what is the corresponding input.

The way to achieve this is by freezing all of the layers of a network and setting $y_{true}$ to your target class. When performing backpropagation via $loss=\hat{y} - y_{true}$ you backpropagate the gradients all the way to the input.

The theory is that once the losses converge to zero, the input should represent the maximum values needed to push the predictions of your neural network to the maximum for a certain class.

Arguments:
  • model (nn.Module): Torch model
  • model_weights_path (str): Path to model saved weights.
  • n_epochs (int, optional): Number of epochs to perform training. Defaults to 10.
  • n_steps (int, optional): Number of steps within an epoch. Defaults to 100.