GAN Specialization Notes
  • GANs
  • Apply Generative Adversial Networks (GANs)
    • GAN Applications
  • Building Basic Generative Adversial Networks (GANs)
    • Generative Adversial Networks
  • Building Better Generative Adversial Networks (GANs)
    • Building Better GANs
  • Notebooks
    • Components of BigGAN
    • Your First GAN
    • Wasserstein GAN with Gradient Penalty (WGAN-GP)
    • Build a Conditional GAN
    • Controllable Generation
    • Deep Convolutional GAN (DCGAN)
    • Evaluating GANs
    • Neural Radiance Fields (NeRF)
    • Bias
    • Components of StyleGAN
    • Data Augmentation
    • U-Net
    • U-Net
    • Pix2Pix
    • CycleGAN
    • Perceptual Path Length (PPL)
    • Spectrally Normalized Generative Adversarial Networks (SN-GAN)
    • StyleGAN2
  • Previous
  • Next
  • Build a Conditional GAN
    • Getting Started
    • Class Input
    • Training
    • Exploration

Build a Conditional GAN¶

Goals¶

In this notebook, you're going to make a conditional GAN in order to generate hand-written images of digits, conditioned on the digit to be generated (the class vector). This will let you choose what digit you want to generate.

You'll then do some exploration of the generated images to visualize what the noise and class vectors mean.

Learning Objectives¶

  1. Learn the technical difference between a conditional and unconditional GAN.
  2. Understand the distinction between the class and noise vector in a conditional GAN.

Getting Started¶

For this assignment, you will be using the MNIST dataset again, but there's nothing stopping you from applying this generator code to produce images of animals conditioned on the species or pictures of faces conditioned on facial characteristics.

Note that this assignment requires no changes to the architectures of the generator or discriminator, only changes to the data passed to both. The generator will no longer take z_dim as an argument, but input_dim instead, since you need to pass in both the noise and class vectors. In addition to good variable naming, this also means that you can use the generator and discriminator code you have previously written with different parameters.

You will begin by importing the necessary libraries and building the generator and discriminator.

Packages and Visualization¶

In [1]:
Copied!
import torch
from torch import nn
from tqdm.auto import tqdm
from torchvision import transforms
from torchvision.datasets import MNIST
from torchvision.utils import make_grid
from torch.utils.data import DataLoader
import matplotlib.pyplot as plt
torch.manual_seed(0) # Set for our testing purposes, please do not change!

def show_tensor_images(image_tensor, num_images=25, size=(1, 28, 28), nrow=5, show=True):
    '''
    Function for visualizing images: Given a tensor of images, number of images, and
    size per image, plots and prints the images in an uniform grid.
    '''
    image_tensor = (image_tensor + 1) / 2
    image_unflat = image_tensor.detach().cpu()
    image_grid = make_grid(image_unflat[:num_images], nrow=nrow)
    plt.imshow(image_grid.permute(1, 2, 0).squeeze())
    if show:
        plt.show()
import torch from torch import nn from tqdm.auto import tqdm from torchvision import transforms from torchvision.datasets import MNIST from torchvision.utils import make_grid from torch.utils.data import DataLoader import matplotlib.pyplot as plt torch.manual_seed(0) # Set for our testing purposes, please do not change! def show_tensor_images(image_tensor, num_images=25, size=(1, 28, 28), nrow=5, show=True): ''' Function for visualizing images: Given a tensor of images, number of images, and size per image, plots and prints the images in an uniform grid. ''' image_tensor = (image_tensor + 1) / 2 image_unflat = image_tensor.detach().cpu() image_grid = make_grid(image_unflat[:num_images], nrow=nrow) plt.imshow(image_grid.permute(1, 2, 0).squeeze()) if show: plt.show()

Generator and Noise¶

In [2]:
Copied!
class Generator(nn.Module):
    '''
    Generator Class
    Values:
        input_dim: the dimension of the input vector, a scalar
        im_chan: the number of channels in the images, fitted for the dataset used, a scalar
              (MNIST is black-and-white, so 1 channel is your default)
        hidden_dim: the inner dimension, a scalar
    '''
    def __init__(self, input_dim=10, im_chan=1, hidden_dim=64):
        super(Generator, self).__init__()
        self.input_dim = input_dim
        # Build the neural network
        self.gen = nn.Sequential(
            self.make_gen_block(input_dim, hidden_dim * 4),
            self.make_gen_block(hidden_dim * 4, hidden_dim * 2, kernel_size=4, stride=1),
            self.make_gen_block(hidden_dim * 2, hidden_dim),
            self.make_gen_block(hidden_dim, im_chan, kernel_size=4, final_layer=True),
        )

    def make_gen_block(self, input_channels, output_channels, kernel_size=3, stride=2, final_layer=False):
        '''
        Function to return a sequence of operations corresponding to a generator block of DCGAN;
        a transposed convolution, a batchnorm (except in the final layer), and an activation.
        Parameters:
            input_channels: how many channels the input feature representation has
            output_channels: how many channels the output feature representation should have
            kernel_size: the size of each convolutional filter, equivalent to (kernel_size, kernel_size)
            stride: the stride of the convolution
            final_layer: a boolean, true if it is the final layer and false otherwise 
                      (affects activation and batchnorm)
        '''
        if not final_layer:
            return nn.Sequential(
                nn.ConvTranspose2d(input_channels, output_channels, kernel_size, stride),
                nn.BatchNorm2d(output_channels),
                nn.ReLU(inplace=True),
            )
        else:
            return nn.Sequential(
                nn.ConvTranspose2d(input_channels, output_channels, kernel_size, stride),
                nn.Tanh(),
            )

    def forward(self, noise):
        '''
        Function for completing a forward pass of the generator: Given a noise tensor, 
        returns generated images.
        Parameters:
            noise: a noise tensor with dimensions (n_samples, input_dim)
        '''
        x = noise.view(len(noise), self.input_dim, 1, 1)
        return self.gen(x)

def get_noise(n_samples, input_dim, device='cpu'):
    '''
    Function for creating noise vectors: Given the dimensions (n_samples, input_dim)
    creates a tensor of that shape filled with random numbers from the normal distribution.
    Parameters:
        n_samples: the number of samples to generate, a scalar
        input_dim: the dimension of the input vector, a scalar
        device: the device type
    '''
    return torch.randn(n_samples, input_dim, device=device)
class Generator(nn.Module): ''' Generator Class Values: input_dim: the dimension of the input vector, a scalar im_chan: the number of channels in the images, fitted for the dataset used, a scalar (MNIST is black-and-white, so 1 channel is your default) hidden_dim: the inner dimension, a scalar ''' def __init__(self, input_dim=10, im_chan=1, hidden_dim=64): super(Generator, self).__init__() self.input_dim = input_dim # Build the neural network self.gen = nn.Sequential( self.make_gen_block(input_dim, hidden_dim * 4), self.make_gen_block(hidden_dim * 4, hidden_dim * 2, kernel_size=4, stride=1), self.make_gen_block(hidden_dim * 2, hidden_dim), self.make_gen_block(hidden_dim, im_chan, kernel_size=4, final_layer=True), ) def make_gen_block(self, input_channels, output_channels, kernel_size=3, stride=2, final_layer=False): ''' Function to return a sequence of operations corresponding to a generator block of DCGAN; a transposed convolution, a batchnorm (except in the final layer), and an activation. Parameters: input_channels: how many channels the input feature representation has output_channels: how many channels the output feature representation should have kernel_size: the size of each convolutional filter, equivalent to (kernel_size, kernel_size) stride: the stride of the convolution final_layer: a boolean, true if it is the final layer and false otherwise (affects activation and batchnorm) ''' if not final_layer: return nn.Sequential( nn.ConvTranspose2d(input_channels, output_channels, kernel_size, stride), nn.BatchNorm2d(output_channels), nn.ReLU(inplace=True), ) else: return nn.Sequential( nn.ConvTranspose2d(input_channels, output_channels, kernel_size, stride), nn.Tanh(), ) def forward(self, noise): ''' Function for completing a forward pass of the generator: Given a noise tensor, returns generated images. Parameters: noise: a noise tensor with dimensions (n_samples, input_dim) ''' x = noise.view(len(noise), self.input_dim, 1, 1) return self.gen(x) def get_noise(n_samples, input_dim, device='cpu'): ''' Function for creating noise vectors: Given the dimensions (n_samples, input_dim) creates a tensor of that shape filled with random numbers from the normal distribution. Parameters: n_samples: the number of samples to generate, a scalar input_dim: the dimension of the input vector, a scalar device: the device type ''' return torch.randn(n_samples, input_dim, device=device)

Discriminator¶

In [3]:
Copied!
class Discriminator(nn.Module):
    '''
    Discriminator Class
    Values:
      im_chan: the number of channels in the images, fitted for the dataset used, a scalar
            (MNIST is black-and-white, so 1 channel is your default)
      hidden_dim: the inner dimension, a scalar
    '''
    def __init__(self, im_chan=1, hidden_dim=64):
        super(Discriminator, self).__init__()
        self.disc = nn.Sequential(
            self.make_disc_block(im_chan, hidden_dim),
            self.make_disc_block(hidden_dim, hidden_dim * 2),
            self.make_disc_block(hidden_dim * 2, 1, final_layer=True),
        )

    def make_disc_block(self, input_channels, output_channels, kernel_size=4, stride=2, final_layer=False):
        '''
        Function to return a sequence of operations corresponding to a discriminator block of the DCGAN; 
        a convolution, a batchnorm (except in the final layer), and an activation (except in the final layer).
        Parameters:
            input_channels: how many channels the input feature representation has
            output_channels: how many channels the output feature representation should have
            kernel_size: the size of each convolutional filter, equivalent to (kernel_size, kernel_size)
            stride: the stride of the convolution
            final_layer: a boolean, true if it is the final layer and false otherwise 
                      (affects activation and batchnorm)
        '''
        if not final_layer:
            return nn.Sequential(
                nn.Conv2d(input_channels, output_channels, kernel_size, stride),
                nn.BatchNorm2d(output_channels),
                nn.LeakyReLU(0.2, inplace=True),
            )
        else:
            return nn.Sequential(
                nn.Conv2d(input_channels, output_channels, kernel_size, stride),
            )

    def forward(self, image):
        '''
        Function for completing a forward pass of the discriminator: Given an image tensor, 
        returns a 1-dimension tensor representing fake/real.
        Parameters:
            image: a flattened image tensor with dimension (im_chan)
        '''
        disc_pred = self.disc(image)
        return disc_pred.view(len(disc_pred), -1)
class Discriminator(nn.Module): ''' Discriminator Class Values: im_chan: the number of channels in the images, fitted for the dataset used, a scalar (MNIST is black-and-white, so 1 channel is your default) hidden_dim: the inner dimension, a scalar ''' def __init__(self, im_chan=1, hidden_dim=64): super(Discriminator, self).__init__() self.disc = nn.Sequential( self.make_disc_block(im_chan, hidden_dim), self.make_disc_block(hidden_dim, hidden_dim * 2), self.make_disc_block(hidden_dim * 2, 1, final_layer=True), ) def make_disc_block(self, input_channels, output_channels, kernel_size=4, stride=2, final_layer=False): ''' Function to return a sequence of operations corresponding to a discriminator block of the DCGAN; a convolution, a batchnorm (except in the final layer), and an activation (except in the final layer). Parameters: input_channels: how many channels the input feature representation has output_channels: how many channels the output feature representation should have kernel_size: the size of each convolutional filter, equivalent to (kernel_size, kernel_size) stride: the stride of the convolution final_layer: a boolean, true if it is the final layer and false otherwise (affects activation and batchnorm) ''' if not final_layer: return nn.Sequential( nn.Conv2d(input_channels, output_channels, kernel_size, stride), nn.BatchNorm2d(output_channels), nn.LeakyReLU(0.2, inplace=True), ) else: return nn.Sequential( nn.Conv2d(input_channels, output_channels, kernel_size, stride), ) def forward(self, image): ''' Function for completing a forward pass of the discriminator: Given an image tensor, returns a 1-dimension tensor representing fake/real. Parameters: image: a flattened image tensor with dimension (im_chan) ''' disc_pred = self.disc(image) return disc_pred.view(len(disc_pred), -1)

Class Input¶

In conditional GANs, the input vector for the generator will also need to include the class information. The class is represented using a one-hot encoded vector where its length is the number of classes and each index represents a class. The vector is all 0's and a 1 on the chosen class. Given the labels of multiple images (e.g. from a batch) and number of classes, please create one-hot vectors for each label. There is a class within the PyTorch functional library that can help you.

Optional hints for get_one_hot_labels
  1. This code can be done in one line.
  2. The documentation for F.one_hot may be helpful.
In [4]:
Copied!
# UNQ_C1 (UNIQUE CELL IDENTIFIER, DO NOT EDIT)
# GRADED FUNCTION: get_one_hot_labels

import torch.nn.functional as F
def get_one_hot_labels(labels, n_classes):
    '''
    Function for creating one-hot vectors for the labels, returns a tensor of shape (?, num_classes).
    Parameters:
        labels: tensor of labels from the dataloader, size (?)
        n_classes: the total number of classes in the dataset, an integer scalar
    '''
    #### START CODE HERE ####
    return F.one_hot(labels, n_classes)
    #### END CODE HERE ####
# UNQ_C1 (UNIQUE CELL IDENTIFIER, DO NOT EDIT) # GRADED FUNCTION: get_one_hot_labels import torch.nn.functional as F def get_one_hot_labels(labels, n_classes): ''' Function for creating one-hot vectors for the labels, returns a tensor of shape (?, num_classes). Parameters: labels: tensor of labels from the dataloader, size (?) n_classes: the total number of classes in the dataset, an integer scalar ''' #### START CODE HERE #### return F.one_hot(labels, n_classes) #### END CODE HERE ####
In [5]:
Copied!
assert (
    get_one_hot_labels(
        labels=torch.Tensor([[0, 2, 1]]).long(),
        n_classes=3
    ).tolist() == 
    [[
      [1, 0, 0], 
      [0, 0, 1], 
      [0, 1, 0]
    ]]
)
# Check that the device of get_one_hot_labels matches the input device
if torch.cuda.is_available():
    assert str(get_one_hot_labels(torch.Tensor([[0]]).long().cuda(), 1).device).startswith("cuda")
    
print("Success!")
assert ( get_one_hot_labels( labels=torch.Tensor([[0, 2, 1]]).long(), n_classes=3 ).tolist() == [[ [1, 0, 0], [0, 0, 1], [0, 1, 0] ]] ) # Check that the device of get_one_hot_labels matches the input device if torch.cuda.is_available(): assert str(get_one_hot_labels(torch.Tensor([[0]]).long().cuda(), 1).device).startswith("cuda") print("Success!")
Success!

Next, you need to be able to concatenate the one-hot class vector to the noise vector before giving it to the generator. You will also need to do this when adding the class channels to the discriminator.

To do this, you will need to write a function that combines two vectors. Remember that you need to ensure that the vectors are the same type: floats. Again, you can look to the PyTorch library for help.

Optional hints for combine_vectors
  1. This code can also be written in one line.
  2. The documentation for torch.cat may be helpful.
  3. Specifically, you might want to look at what the dim argument of torch.cat does.
In [6]:
Copied!
# UNQ_C2 (UNIQUE CELL IDENTIFIER, DO NOT EDIT)
# GRADED FUNCTION: combine_vectors
def combine_vectors(x, y):
    '''
    Function for combining two vectors with shapes (n_samples, ?) and (n_samples, ?).
    Parameters:
      x: (n_samples, ?) the first vector. 
        In this assignment, this will be the noise vector of shape (n_samples, z_dim), 
        but you shouldn't need to know the second dimension's size.
      y: (n_samples, ?) the second vector.
        Once again, in this assignment this will be the one-hot class vector 
        with the shape (n_samples, n_classes), but you shouldn't assume this in your code.
    '''
    # Note: Make sure this function outputs a float no matter what inputs it receives
    #### START CODE HERE ####
    combined = torch.cat((x.float(), y.float()), 1)
    #### END CODE HERE ####
    return combined
# UNQ_C2 (UNIQUE CELL IDENTIFIER, DO NOT EDIT) # GRADED FUNCTION: combine_vectors def combine_vectors(x, y): ''' Function for combining two vectors with shapes (n_samples, ?) and (n_samples, ?). Parameters: x: (n_samples, ?) the first vector. In this assignment, this will be the noise vector of shape (n_samples, z_dim), but you shouldn't need to know the second dimension's size. y: (n_samples, ?) the second vector. Once again, in this assignment this will be the one-hot class vector with the shape (n_samples, n_classes), but you shouldn't assume this in your code. ''' # Note: Make sure this function outputs a float no matter what inputs it receives #### START CODE HERE #### combined = torch.cat((x.float(), y.float()), 1) #### END CODE HERE #### return combined
In [7]:
Copied!
combined = combine_vectors(torch.tensor([[1, 2], [3, 4]]), torch.tensor([[5, 6], [7, 8]]))
if torch.cuda.is_available():
    # Check that it doesn't break with cuda
    cuda_check = combine_vectors(torch.tensor([[1, 2], [3, 4]]).cuda(), torch.tensor([[5, 6], [7, 8]]).cuda())
    assert str(cuda_check.device).startswith("cuda")
# Check exact order of elements
assert torch.all(combined == torch.tensor([[1, 2, 5, 6], [3, 4, 7, 8]]))
# Tests that items are of float type
assert (type(combined[0][0].item()) == float)
# Check shapes
combined = combine_vectors(torch.randn(1, 4, 5), torch.randn(1, 8, 5));
assert tuple(combined.shape) == (1, 12, 5)
assert tuple(combine_vectors(torch.randn(1, 10, 12).long(), torch.randn(1, 20, 12).long()).shape) == (1, 30, 12)
# Check that the float transformation doesn't happen after the inputs are concatenated
assert tuple(combine_vectors(torch.randn(1, 10, 12).long(), torch.randn(1, 20, 12)).shape) == (1, 30, 12)
print("Success!")
combined = combine_vectors(torch.tensor([[1, 2], [3, 4]]), torch.tensor([[5, 6], [7, 8]])) if torch.cuda.is_available(): # Check that it doesn't break with cuda cuda_check = combine_vectors(torch.tensor([[1, 2], [3, 4]]).cuda(), torch.tensor([[5, 6], [7, 8]]).cuda()) assert str(cuda_check.device).startswith("cuda") # Check exact order of elements assert torch.all(combined == torch.tensor([[1, 2, 5, 6], [3, 4, 7, 8]])) # Tests that items are of float type assert (type(combined[0][0].item()) == float) # Check shapes combined = combine_vectors(torch.randn(1, 4, 5), torch.randn(1, 8, 5)); assert tuple(combined.shape) == (1, 12, 5) assert tuple(combine_vectors(torch.randn(1, 10, 12).long(), torch.randn(1, 20, 12).long()).shape) == (1, 30, 12) # Check that the float transformation doesn't happen after the inputs are concatenated assert tuple(combine_vectors(torch.randn(1, 10, 12).long(), torch.randn(1, 20, 12)).shape) == (1, 30, 12) print("Success!")
Success!

Training¶

Now you can start to put it all together! First, you will define some new parameters:

  • mnist_shape: the number of pixels in each MNIST image, which has dimensions 28 x 28 and one channel (because it's black-and-white) so 1 x 28 x 28
  • n_classes: the number of classes in MNIST (10, since there are the digits from 0 to 9)
In [8]:
Copied!
mnist_shape = (1, 28, 28)
n_classes = 10
mnist_shape = (1, 28, 28) n_classes = 10

And you also include the same parameters from previous assignments:

  • criterion: the loss function
  • n_epochs: the number of times you iterate through the entire dataset when training
  • z_dim: the dimension of the noise vector
  • display_step: how often to display/visualize the images
  • batch_size: the number of images per forward/backward pass
  • lr: the learning rate
  • device: the device type
In [9]:
Copied!
criterion = nn.BCEWithLogitsLoss()
n_epochs = 200
z_dim = 64
display_step = 500
batch_size = 128
lr = 0.0002
device = 'cuda'

transform = transforms.Compose([
    transforms.ToTensor(),
    transforms.Normalize((0.5,), (0.5,)),
])

dataloader = DataLoader(
    MNIST('.', download=False, transform=transform),
    batch_size=batch_size,
    shuffle=True)
criterion = nn.BCEWithLogitsLoss() n_epochs = 200 z_dim = 64 display_step = 500 batch_size = 128 lr = 0.0002 device = 'cuda' transform = transforms.Compose([ transforms.ToTensor(), transforms.Normalize((0.5,), (0.5,)), ]) dataloader = DataLoader( MNIST('.', download=False, transform=transform), batch_size=batch_size, shuffle=True)

Then, you can initialize your generator, discriminator, and optimizers. To do this, you will need to update the input dimensions for both models. For the generator, you will need to calculate the size of the input vector; recall that for conditional GANs, the generator's input is the noise vector concatenated with the class vector. For the discriminator, you need to add a channel for every class.

In [10]:
Copied!
# UNQ_C3 (UNIQUE CELL IDENTIFIER, DO NOT EDIT)
# GRADED FUNCTION: get_input_dimensions
def get_input_dimensions(z_dim, mnist_shape, n_classes):
    '''
    Function for getting the size of the conditional input dimensions 
    from z_dim, the image shape, and number of classes.
    Parameters:
        z_dim: the dimension of the noise vector, a scalar
        mnist_shape: the shape of each MNIST image as (C, W, H), which is (1, 28, 28)
        n_classes: the total number of classes in the dataset, an integer scalar
                (10 for MNIST)
    Returns: 
        generator_input_dim: the input dimensionality of the conditional generator, 
                          which takes the noise and class vectors
        discriminator_im_chan: the number of input channels to the discriminator
                            (e.g. C x 28 x 28 for MNIST)
    '''
    #### START CODE HERE ####
    generator_input_dim = z_dim + n_classes
    discriminator_im_chan = mnist_shape[0] + n_classes
    #### END CODE HERE ####
    return generator_input_dim, discriminator_im_chan
# UNQ_C3 (UNIQUE CELL IDENTIFIER, DO NOT EDIT) # GRADED FUNCTION: get_input_dimensions def get_input_dimensions(z_dim, mnist_shape, n_classes): ''' Function for getting the size of the conditional input dimensions from z_dim, the image shape, and number of classes. Parameters: z_dim: the dimension of the noise vector, a scalar mnist_shape: the shape of each MNIST image as (C, W, H), which is (1, 28, 28) n_classes: the total number of classes in the dataset, an integer scalar (10 for MNIST) Returns: generator_input_dim: the input dimensionality of the conditional generator, which takes the noise and class vectors discriminator_im_chan: the number of input channels to the discriminator (e.g. C x 28 x 28 for MNIST) ''' #### START CODE HERE #### generator_input_dim = z_dim + n_classes discriminator_im_chan = mnist_shape[0] + n_classes #### END CODE HERE #### return generator_input_dim, discriminator_im_chan
In [11]:
Copied!
def test_input_dims():
    gen_dim, disc_dim = get_input_dimensions(23, (12, 23, 52), 9)
    assert gen_dim == 32
    assert disc_dim == 21
test_input_dims()
print("Success!")
def test_input_dims(): gen_dim, disc_dim = get_input_dimensions(23, (12, 23, 52), 9) assert gen_dim == 32 assert disc_dim == 21 test_input_dims() print("Success!")
Success!
In [12]:
Copied!
generator_input_dim, discriminator_im_chan = get_input_dimensions(z_dim, mnist_shape, n_classes)

gen = Generator(input_dim=generator_input_dim).to(device)
gen_opt = torch.optim.Adam(gen.parameters(), lr=lr)
disc = Discriminator(im_chan=discriminator_im_chan).to(device)
disc_opt = torch.optim.Adam(disc.parameters(), lr=lr)

def weights_init(m):
    if isinstance(m, nn.Conv2d) or isinstance(m, nn.ConvTranspose2d):
        torch.nn.init.normal_(m.weight, 0.0, 0.02)
    if isinstance(m, nn.BatchNorm2d):
        torch.nn.init.normal_(m.weight, 0.0, 0.02)
        torch.nn.init.constant_(m.bias, 0)
gen = gen.apply(weights_init)
disc = disc.apply(weights_init)
generator_input_dim, discriminator_im_chan = get_input_dimensions(z_dim, mnist_shape, n_classes) gen = Generator(input_dim=generator_input_dim).to(device) gen_opt = torch.optim.Adam(gen.parameters(), lr=lr) disc = Discriminator(im_chan=discriminator_im_chan).to(device) disc_opt = torch.optim.Adam(disc.parameters(), lr=lr) def weights_init(m): if isinstance(m, nn.Conv2d) or isinstance(m, nn.ConvTranspose2d): torch.nn.init.normal_(m.weight, 0.0, 0.02) if isinstance(m, nn.BatchNorm2d): torch.nn.init.normal_(m.weight, 0.0, 0.02) torch.nn.init.constant_(m.bias, 0) gen = gen.apply(weights_init) disc = disc.apply(weights_init)

Now to train, you would like both your generator and your discriminator to know what class of image should be generated. There are a few locations where you will need to implement code.

For example, if you're generating a picture of the number "1", you would need to:

  1. Tell that to the generator, so that it knows it should be generating a "1"
  2. Tell that to the discriminator, so that it knows it should be looking at a "1". If the discriminator is told it should be looking at a 1 but sees something that's clearly an 8, it can guess that it's probably fake

There are no explicit unit tests here -- if this block of code runs and you don't change any of the other variables, then you've done it correctly!

In [14]:
Copied!
# UNQ_C4 (UNIQUE CELL IDENTIFIER, DO NOT EDIT)
# GRADED CELL
cur_step = 0
generator_losses = []
discriminator_losses = []

#UNIT TEST NOTE: Initializations needed for grading
noise_and_labels = False
fake = False

fake_image_and_labels = False
real_image_and_labels = False
disc_fake_pred = False
disc_real_pred = False

for epoch in range(n_epochs):
    # Dataloader returns the batches and the labels
    for real, labels in tqdm(dataloader):
        cur_batch_size = len(real)
        # Flatten the batch of real images from the dataset
        real = real.to(device)

        one_hot_labels = get_one_hot_labels(labels.to(device), n_classes)
        image_one_hot_labels = one_hot_labels[:, :, None, None]
        image_one_hot_labels = image_one_hot_labels.repeat(1, 1, mnist_shape[1], mnist_shape[2])

        ### Update discriminator ###
        # Zero out the discriminator gradients
        disc_opt.zero_grad()
        # Get noise corresponding to the current batch_size 
        fake_noise = get_noise(cur_batch_size, z_dim, device=device)
        
        # Now you can get the images from the generator
        # Steps: 1) Combine the noise vectors and the one-hot labels for the generator
        #        2) Generate the conditioned fake images
       
        #### START CODE HERE ####
        noise_and_labels = combine_vectors(fake_noise, one_hot_labels)
        fake = gen(noise_and_labels)
        #### END CODE HERE ####
        
        # Make sure that enough images were generated
        assert len(fake) == len(real)
        # Check that correct tensors were combined
        assert tuple(noise_and_labels.shape) == (cur_batch_size, fake_noise.shape[1] + one_hot_labels.shape[1])
        # It comes from the correct generator
        assert tuple(fake.shape) == (len(real), 1, 28, 28)

        # Now you can get the predictions from the discriminator
        # Steps: 1) Create the input for the discriminator
        #           a) Combine the fake images with image_one_hot_labels, 
        #              remember to detach the generator (.detach()) so you do not backpropagate through it
        #           b) Combine the real images with image_one_hot_labels
        #        2) Get the discriminator's prediction on the fakes as disc_fake_pred
        #        3) Get the discriminator's prediction on the reals as disc_real_pred
        
        #### START CODE HERE ####
        fake_image_and_labels = combine_vectors(fake, image_one_hot_labels)
        real_image_and_labels = combine_vectors(real, image_one_hot_labels)
        disc_fake_pred = disc(fake_image_and_labels.detach())
        disc_real_pred = disc(real_image_and_labels)
        #### END CODE HERE ####
        
        # Make sure shapes are correct 
        assert tuple(fake_image_and_labels.shape) == (len(real), fake.detach().shape[1] + image_one_hot_labels.shape[1], 28 ,28)
        assert tuple(real_image_and_labels.shape) == (len(real), real.shape[1] + image_one_hot_labels.shape[1], 28 ,28)
        # Make sure that enough predictions were made
        assert len(disc_real_pred) == len(real)
        # Make sure that the inputs are different
        assert torch.any(fake_image_and_labels != real_image_and_labels)
        # Shapes must match
        assert tuple(fake_image_and_labels.shape) == tuple(real_image_and_labels.shape)
        assert tuple(disc_fake_pred.shape) == tuple(disc_real_pred.shape)
        
        
        disc_fake_loss = criterion(disc_fake_pred, torch.zeros_like(disc_fake_pred))
        disc_real_loss = criterion(disc_real_pred, torch.ones_like(disc_real_pred))
        disc_loss = (disc_fake_loss + disc_real_loss) / 2
        disc_loss.backward(retain_graph=True)
        disc_opt.step() 

        # Keep track of the average discriminator loss
        discriminator_losses += [disc_loss.item()]

        ### Update generator ###
        # Zero out the generator gradients
        gen_opt.zero_grad()

        fake_image_and_labels = combine_vectors(fake, image_one_hot_labels)
        # This will error if you didn't concatenate your labels to your image correctly
        disc_fake_pred = disc(fake_image_and_labels)
        gen_loss = criterion(disc_fake_pred, torch.ones_like(disc_fake_pred))
        gen_loss.backward()
        gen_opt.step()

        # Keep track of the generator losses
        generator_losses += [gen_loss.item()]
        #

        if cur_step % display_step == 0 and cur_step > 0:
            gen_mean = sum(generator_losses[-display_step:]) / display_step
            disc_mean = sum(discriminator_losses[-display_step:]) / display_step
            print(f"Epoch {epoch}, step {cur_step}: Generator loss: {gen_mean}, discriminator loss: {disc_mean}")
            show_tensor_images(fake)
            show_tensor_images(real)
            step_bins = 20
            x_axis = sorted([i * step_bins for i in range(len(generator_losses) // step_bins)] * step_bins)
            num_examples = (len(generator_losses) // step_bins) * step_bins
            plt.plot(
                range(num_examples // step_bins), 
                torch.Tensor(generator_losses[:num_examples]).view(-1, step_bins).mean(1),
                label="Generator Loss"
            )
            plt.plot(
                range(num_examples // step_bins), 
                torch.Tensor(discriminator_losses[:num_examples]).view(-1, step_bins).mean(1),
                label="Discriminator Loss"
            )
            plt.legend()
            plt.show()
        elif cur_step == 0:
            print("Congratulations! If you've gotten here, it's working. Please let this train until you're happy with how the generated numbers look, and then go on to the exploration!")
        cur_step += 1
# UNQ_C4 (UNIQUE CELL IDENTIFIER, DO NOT EDIT) # GRADED CELL cur_step = 0 generator_losses = [] discriminator_losses = [] #UNIT TEST NOTE: Initializations needed for grading noise_and_labels = False fake = False fake_image_and_labels = False real_image_and_labels = False disc_fake_pred = False disc_real_pred = False for epoch in range(n_epochs): # Dataloader returns the batches and the labels for real, labels in tqdm(dataloader): cur_batch_size = len(real) # Flatten the batch of real images from the dataset real = real.to(device) one_hot_labels = get_one_hot_labels(labels.to(device), n_classes) image_one_hot_labels = one_hot_labels[:, :, None, None] image_one_hot_labels = image_one_hot_labels.repeat(1, 1, mnist_shape[1], mnist_shape[2]) ### Update discriminator ### # Zero out the discriminator gradients disc_opt.zero_grad() # Get noise corresponding to the current batch_size fake_noise = get_noise(cur_batch_size, z_dim, device=device) # Now you can get the images from the generator # Steps: 1) Combine the noise vectors and the one-hot labels for the generator # 2) Generate the conditioned fake images #### START CODE HERE #### noise_and_labels = combine_vectors(fake_noise, one_hot_labels) fake = gen(noise_and_labels) #### END CODE HERE #### # Make sure that enough images were generated assert len(fake) == len(real) # Check that correct tensors were combined assert tuple(noise_and_labels.shape) == (cur_batch_size, fake_noise.shape[1] + one_hot_labels.shape[1]) # It comes from the correct generator assert tuple(fake.shape) == (len(real), 1, 28, 28) # Now you can get the predictions from the discriminator # Steps: 1) Create the input for the discriminator # a) Combine the fake images with image_one_hot_labels, # remember to detach the generator (.detach()) so you do not backpropagate through it # b) Combine the real images with image_one_hot_labels # 2) Get the discriminator's prediction on the fakes as disc_fake_pred # 3) Get the discriminator's prediction on the reals as disc_real_pred #### START CODE HERE #### fake_image_and_labels = combine_vectors(fake, image_one_hot_labels) real_image_and_labels = combine_vectors(real, image_one_hot_labels) disc_fake_pred = disc(fake_image_and_labels.detach()) disc_real_pred = disc(real_image_and_labels) #### END CODE HERE #### # Make sure shapes are correct assert tuple(fake_image_and_labels.shape) == (len(real), fake.detach().shape[1] + image_one_hot_labels.shape[1], 28 ,28) assert tuple(real_image_and_labels.shape) == (len(real), real.shape[1] + image_one_hot_labels.shape[1], 28 ,28) # Make sure that enough predictions were made assert len(disc_real_pred) == len(real) # Make sure that the inputs are different assert torch.any(fake_image_and_labels != real_image_and_labels) # Shapes must match assert tuple(fake_image_and_labels.shape) == tuple(real_image_and_labels.shape) assert tuple(disc_fake_pred.shape) == tuple(disc_real_pred.shape) disc_fake_loss = criterion(disc_fake_pred, torch.zeros_like(disc_fake_pred)) disc_real_loss = criterion(disc_real_pred, torch.ones_like(disc_real_pred)) disc_loss = (disc_fake_loss + disc_real_loss) / 2 disc_loss.backward(retain_graph=True) disc_opt.step() # Keep track of the average discriminator loss discriminator_losses += [disc_loss.item()] ### Update generator ### # Zero out the generator gradients gen_opt.zero_grad() fake_image_and_labels = combine_vectors(fake, image_one_hot_labels) # This will error if you didn't concatenate your labels to your image correctly disc_fake_pred = disc(fake_image_and_labels) gen_loss = criterion(disc_fake_pred, torch.ones_like(disc_fake_pred)) gen_loss.backward() gen_opt.step() # Keep track of the generator losses generator_losses += [gen_loss.item()] # if cur_step % display_step == 0 and cur_step > 0: gen_mean = sum(generator_losses[-display_step:]) / display_step disc_mean = sum(discriminator_losses[-display_step:]) / display_step print(f"Epoch {epoch}, step {cur_step}: Generator loss: {gen_mean}, discriminator loss: {disc_mean}") show_tensor_images(fake) show_tensor_images(real) step_bins = 20 x_axis = sorted([i * step_bins for i in range(len(generator_losses) // step_bins)] * step_bins) num_examples = (len(generator_losses) // step_bins) * step_bins plt.plot( range(num_examples // step_bins), torch.Tensor(generator_losses[:num_examples]).view(-1, step_bins).mean(1), label="Generator Loss" ) plt.plot( range(num_examples // step_bins), torch.Tensor(discriminator_losses[:num_examples]).view(-1, step_bins).mean(1), label="Discriminator Loss" ) plt.legend() plt.show() elif cur_step == 0: print("Congratulations! If you've gotten here, it's working. Please let this train until you're happy with how the generated numbers look, and then go on to the exploration!") cur_step += 1
  0%|          | 0/469 [00:00<?, ?it/s]
Congratulations! If you've gotten here, it's working. Please let this train until you're happy with how the generated numbers look, and then go on to the exploration!
  0%|          | 0/469 [00:00<?, ?it/s]
Epoch 1, step 500: Generator loss: 2.2115664736032485, discriminator loss: 0.2685868946425617
No description has been provided for this image
No description has been provided for this image
No description has been provided for this image
  0%|          | 0/469 [00:00<?, ?it/s]
Epoch 2, step 1000: Generator loss: 4.221269572257996, discriminator loss: 0.051587830167263746
No description has been provided for this image
No description has been provided for this image
No description has been provided for this image
  0%|          | 0/469 [00:00<?, ?it/s]
Epoch 3, step 1500: Generator loss: 4.211510757923127, discriminator loss: 0.05655083135422319
No description has been provided for this image
No description has been provided for this image
No description has been provided for this image
  0%|          | 0/469 [00:00<?, ?it/s]
Epoch 4, step 2000: Generator loss: 3.2707153000831606, discriminator loss: 0.10579101647436619
No description has been provided for this image
No description has been provided for this image
No description has been provided for this image
  0%|          | 0/469 [00:00<?, ?it/s]
Epoch 5, step 2500: Generator loss: 2.4357875924110415, discriminator loss: 0.2713673864603043
No description has been provided for this image
No description has been provided for this image
No description has been provided for this image
  0%|          | 0/469 [00:00<?, ?it/s]
Epoch 6, step 3000: Generator loss: 2.240764480113983, discriminator loss: 0.3099766071140766
No description has been provided for this image
No description has been provided for this image
No description has been provided for this image
  0%|          | 0/469 [00:00<?, ?it/s]
Epoch 7, step 3500: Generator loss: 1.9961848113536835, discriminator loss: 0.3215213434398174
No description has been provided for this image
No description has been provided for this image
No description has been provided for this image
  0%|          | 0/469 [00:00<?, ?it/s]
Epoch 8, step 4000: Generator loss: 2.110323561668396, discriminator loss: 0.3168881052732468
No description has been provided for this image
No description has been provided for this image
No description has been provided for this image
  0%|          | 0/469 [00:00<?, ?it/s]
Epoch 9, step 4500: Generator loss: 2.1868630158901214, discriminator loss: 0.31629042902588844
No description has been provided for this image
No description has been provided for this image
No description has been provided for this image
  0%|          | 0/469 [00:00<?, ?it/s]
Epoch 10, step 5000: Generator loss: 1.9912456004619599, discriminator loss: 0.3248158627450466
No description has been provided for this image
No description has been provided for this image
No description has been provided for this image
  0%|          | 0/469 [00:00<?, ?it/s]
Epoch 11, step 5500: Generator loss: 1.8978509147167206, discriminator loss: 0.37217000997066496
No description has been provided for this image
No description has been provided for this image
No description has been provided for this image
  0%|          | 0/469 [00:00<?, ?it/s]
Epoch 12, step 6000: Generator loss: 1.6967354121208191, discriminator loss: 0.3952812244296074
No description has been provided for this image
No description has been provided for this image
No description has been provided for this image
  0%|          | 0/469 [00:00<?, ?it/s]
Epoch 13, step 6500: Generator loss: 1.6692118233442306, discriminator loss: 0.42982025346159936
No description has been provided for this image
No description has been provided for this image
No description has been provided for this image
  0%|          | 0/469 [00:00<?, ?it/s]
Epoch 14, step 7000: Generator loss: 1.6109941833019257, discriminator loss: 0.4480661828517914
No description has been provided for this image
No description has been provided for this image
No description has been provided for this image
  0%|          | 0/469 [00:00<?, ?it/s]
Epoch 15, step 7500: Generator loss: 1.4511568641662598, discriminator loss: 0.4665398987531662
No description has been provided for this image
No description has been provided for this image
No description has been provided for this image
  0%|          | 0/469 [00:00<?, ?it/s]
  0%|          | 0/469 [00:00<?, ?it/s]
Epoch 17, step 8000: Generator loss: 1.463431914329529, discriminator loss: 0.48082829689979556
No description has been provided for this image
No description has been provided for this image
No description has been provided for this image
  0%|          | 0/469 [00:00<?, ?it/s]
Epoch 18, step 8500: Generator loss: 1.4653161545991897, discriminator loss: 0.4920199128985405
No description has been provided for this image
No description has been provided for this image
No description has been provided for this image
  0%|          | 0/469 [00:00<?, ?it/s]
Epoch 19, step 9000: Generator loss: 1.3783783526420594, discriminator loss: 0.4872072164714336
No description has been provided for this image
No description has been provided for this image
No description has been provided for this image
  0%|          | 0/469 [00:00<?, ?it/s]
Epoch 20, step 9500: Generator loss: 1.3555809535980226, discriminator loss: 0.508311718583107
No description has been provided for this image
No description has been provided for this image
No description has been provided for this image
  0%|          | 0/469 [00:00<?, ?it/s]
Epoch 21, step 10000: Generator loss: 1.2925225931406021, discriminator loss: 0.5252812886238098
No description has been provided for this image
No description has been provided for this image
No description has been provided for this image
  0%|          | 0/469 [00:00<?, ?it/s]
Epoch 22, step 10500: Generator loss: 1.267152936577797, discriminator loss: 0.5367066763043403
No description has been provided for this image
No description has been provided for this image
No description has been provided for this image
  0%|          | 0/469 [00:00<?, ?it/s]
Epoch 23, step 11000: Generator loss: 1.2421369094848633, discriminator loss: 0.5377380474209785
No description has been provided for this image
No description has been provided for this image
No description has been provided for this image
  0%|          | 0/469 [00:00<?, ?it/s]
Epoch 24, step 11500: Generator loss: 1.195749608397484, discriminator loss: 0.5449688808321953
No description has been provided for this image
No description has been provided for this image
No description has been provided for this image
  0%|          | 0/469 [00:00<?, ?it/s]
Epoch 25, step 12000: Generator loss: 1.2062078047990799, discriminator loss: 0.5494959956407547
No description has been provided for this image
No description has been provided for this image
No description has been provided for this image
  0%|          | 0/469 [00:00<?, ?it/s]
Epoch 26, step 12500: Generator loss: 1.1992291980981826, discriminator loss: 0.5466335816979409
No description has been provided for this image
No description has been provided for this image
No description has been provided for this image
  0%|          | 0/469 [00:00<?, ?it/s]
Epoch 27, step 13000: Generator loss: 1.1271400240659715, discriminator loss: 0.5497399532794952
No description has been provided for this image
No description has been provided for this image
No description has been provided for this image
  0%|          | 0/469 [00:00<?, ?it/s]
Epoch 28, step 13500: Generator loss: 1.1880803110599518, discriminator loss: 0.5669176105856896
No description has been provided for this image
No description has been provided for this image
No description has been provided for this image
  0%|          | 0/469 [00:00<?, ?it/s]
Epoch 29, step 14000: Generator loss: 1.1068376694917679, discriminator loss: 0.5652729490995407
No description has been provided for this image
No description has been provided for this image
No description has been provided for this image
  0%|          | 0/469 [00:00<?, ?it/s]
Epoch 30, step 14500: Generator loss: 1.1210307332277298, discriminator loss: 0.5693431765437126
No description has been provided for this image
No description has been provided for this image
No description has been provided for this image
  0%|          | 0/469 [00:00<?, ?it/s]
Epoch 31, step 15000: Generator loss: 1.1203343322277068, discriminator loss: 0.5783644264936447
No description has been provided for this image
No description has been provided for this image
No description has been provided for this image
  0%|          | 0/469 [00:00<?, ?it/s]
  0%|          | 0/469 [00:00<?, ?it/s]
Epoch 33, step 15500: Generator loss: 1.097046187400818, discriminator loss: 0.5738002940416336
No description has been provided for this image
No description has been provided for this image
No description has been provided for this image
  0%|          | 0/469 [00:00<?, ?it/s]
Epoch 34, step 16000: Generator loss: 1.0974226466417312, discriminator loss: 0.5746870115995407
No description has been provided for this image
No description has been provided for this image
No description has been provided for this image
  0%|          | 0/469 [00:00<?, ?it/s]
Epoch 35, step 16500: Generator loss: 1.053877674818039, discriminator loss: 0.5848516648411751
No description has been provided for this image
No description has been provided for this image
No description has been provided for this image
  0%|          | 0/469 [00:00<?, ?it/s]
Epoch 36, step 17000: Generator loss: 1.0862391217947007, discriminator loss: 0.5933754278421401
No description has been provided for this image
No description has been provided for this image
No description has been provided for this image
  0%|          | 0/469 [00:00<?, ?it/s]
Epoch 37, step 17500: Generator loss: 1.0735066876411439, discriminator loss: 0.5906632270216942
No description has been provided for this image
No description has been provided for this image
No description has been provided for this image
  0%|          | 0/469 [00:00<?, ?it/s]
Epoch 38, step 18000: Generator loss: 1.0594507942199707, discriminator loss: 0.5892614134550095
No description has been provided for this image
No description has been provided for this image
No description has been provided for this image
  0%|          | 0/469 [00:00<?, ?it/s]
Epoch 39, step 18500: Generator loss: 1.0485818824768067, discriminator loss: 0.5867860596776009
No description has been provided for this image
No description has been provided for this image
No description has been provided for this image
  0%|          | 0/469 [00:00<?, ?it/s]
Epoch 40, step 19000: Generator loss: 1.0400051473379135, discriminator loss: 0.5895858646631241
No description has been provided for this image
No description has been provided for this image
No description has been provided for this image
  0%|          | 0/469 [00:00<?, ?it/s]
Epoch 41, step 19500: Generator loss: 1.0303877574205398, discriminator loss: 0.5942053529024124
No description has been provided for this image
No description has been provided for this image
No description has been provided for this image
  0%|          | 0/469 [00:00<?, ?it/s]
Epoch 42, step 20000: Generator loss: 1.021188020825386, discriminator loss: 0.5943220034241676
No description has been provided for this image
No description has been provided for this image
No description has been provided for this image
  0%|          | 0/469 [00:00<?, ?it/s]
Epoch 43, step 20500: Generator loss: 1.0374075932502747, discriminator loss: 0.6046830003857613
No description has been provided for this image
No description has been provided for this image
No description has been provided for this image
  0%|          | 0/469 [00:00<?, ?it/s]
Epoch 44, step 21000: Generator loss: 1.0003213359117509, discriminator loss: 0.5927331103086472
No description has been provided for this image
No description has been provided for this image
No description has been provided for this image
  0%|          | 0/469 [00:00<?, ?it/s]
Epoch 45, step 21500: Generator loss: 1.003862419605255, discriminator loss: 0.6006475481390953
No description has been provided for this image
No description has been provided for this image
No description has been provided for this image
  0%|          | 0/469 [00:00<?, ?it/s]
Epoch 46, step 22000: Generator loss: 1.0291843024492264, discriminator loss: 0.5935961366891861
No description has been provided for this image
No description has been provided for this image
No description has been provided for this image
  0%|          | 0/469 [00:00<?, ?it/s]
Epoch 47, step 22500: Generator loss: 1.01244744181633, discriminator loss: 0.6002081248164177
No description has been provided for this image
No description has been provided for this image
No description has been provided for this image
  0%|          | 0/469 [00:00<?, ?it/s]
  0%|          | 0/469 [00:00<?, ?it/s]
Epoch 49, step 23000: Generator loss: 0.9994891800880432, discriminator loss: 0.5912844946980477
No description has been provided for this image
No description has been provided for this image
No description has been provided for this image
  0%|          | 0/469 [00:00<?, ?it/s]
Epoch 50, step 23500: Generator loss: 0.9970093793869018, discriminator loss: 0.5980668722987175
No description has been provided for this image
No description has been provided for this image
No description has been provided for this image
  0%|          | 0/469 [00:00<?, ?it/s]
Epoch 51, step 24000: Generator loss: 0.998129741191864, discriminator loss: 0.5971390585303307
No description has been provided for this image
No description has been provided for this image
No description has been provided for this image
  0%|          | 0/469 [00:00<?, ?it/s]
Epoch 52, step 24500: Generator loss: 1.0279298236370087, discriminator loss: 0.5956838793754577
No description has been provided for this image
No description has been provided for this image
No description has been provided for this image
  0%|          | 0/469 [00:00<?, ?it/s]
Epoch 53, step 25000: Generator loss: 1.009993726491928, discriminator loss: 0.5950178966522217
No description has been provided for this image
No description has been provided for this image
No description has been provided for this image
  0%|          | 0/469 [00:00<?, ?it/s]
Epoch 54, step 25500: Generator loss: 0.9973953018188476, discriminator loss: 0.5946959819793701
No description has been provided for this image
No description has been provided for this image
No description has been provided for this image
  0%|          | 0/469 [00:00<?, ?it/s]
Epoch 55, step 26000: Generator loss: 0.9892833046913146, discriminator loss: 0.5994198529124259
No description has been provided for this image
No description has been provided for this image
No description has been provided for this image
  0%|          | 0/469 [00:00<?, ?it/s]
Epoch 56, step 26500: Generator loss: 0.9789396873712539, discriminator loss: 0.5982562866806984
No description has been provided for this image
No description has been provided for this image
No description has been provided for this image
  0%|          | 0/469 [00:00<?, ?it/s]
Epoch 57, step 27000: Generator loss: 0.9849927604198456, discriminator loss: 0.6008585188388824
No description has been provided for this image
No description has been provided for this image
No description has been provided for this image
  0%|          | 0/469 [00:00<?, ?it/s]
Epoch 58, step 27500: Generator loss: 0.9754113411903381, discriminator loss: 0.6034010851383209
No description has been provided for this image
No description has been provided for this image
No description has been provided for this image
  0%|          | 0/469 [00:00<?, ?it/s]
Epoch 59, step 28000: Generator loss: 1.009461210489273, discriminator loss: 0.6033989825248718
No description has been provided for this image
No description has been provided for this image
No description has been provided for this image
  0%|          | 0/469 [00:00<?, ?it/s]
Epoch 60, step 28500: Generator loss: 0.9828067841529846, discriminator loss: 0.603311533510685
No description has been provided for this image
No description has been provided for this image
No description has been provided for this image
  0%|          | 0/469 [00:00<?, ?it/s]
Epoch 61, step 29000: Generator loss: 0.9908032495975494, discriminator loss: 0.6042174013257027
No description has been provided for this image
No description has been provided for this image
No description has been provided for this image
  0%|          | 0/469 [00:00<?, ?it/s]
Epoch 62, step 29500: Generator loss: 0.957794203042984, discriminator loss: 0.607917101919651
No description has been provided for this image
No description has been provided for this image
No description has been provided for this image
  0%|          | 0/469 [00:00<?, ?it/s]
Epoch 63, step 30000: Generator loss: 0.9627190870046616, discriminator loss: 0.601711801469326
No description has been provided for this image
No description has been provided for this image
No description has been provided for this image
  0%|          | 0/469 [00:00<?, ?it/s]
  0%|          | 0/469 [00:00<?, ?it/s]
Epoch 65, step 30500: Generator loss: 0.9748913640975952, discriminator loss: 0.5978434380292893
No description has been provided for this image
No description has been provided for this image
No description has been provided for this image
  0%|          | 0/469 [00:00<?, ?it/s]
Epoch 66, step 31000: Generator loss: 0.9770773639678955, discriminator loss: 0.6008287969827651
No description has been provided for this image
No description has been provided for this image
No description has been provided for this image
  0%|          | 0/469 [00:00<?, ?it/s]
Epoch 67, step 31500: Generator loss: 0.9694072247743607, discriminator loss: 0.6035050277709961
No description has been provided for this image
No description has been provided for this image
No description has been provided for this image
  0%|          | 0/469 [00:00<?, ?it/s]
Epoch 68, step 32000: Generator loss: 0.976947183251381, discriminator loss: 0.6025677533149719
No description has been provided for this image
No description has been provided for this image
No description has been provided for this image
  0%|          | 0/469 [00:00<?, ?it/s]
Epoch 69, step 32500: Generator loss: 0.972094788312912, discriminator loss: 0.597560405254364
No description has been provided for this image
No description has been provided for this image
No description has been provided for this image
  0%|          | 0/469 [00:00<?, ?it/s]
Epoch 70, step 33000: Generator loss: 0.9888450082540512, discriminator loss: 0.6054033529162407
No description has been provided for this image
No description has been provided for this image
No description has been provided for this image
  0%|          | 0/469 [00:00<?, ?it/s]
Epoch 71, step 33500: Generator loss: 0.970538076877594, discriminator loss: 0.5995624731183052
No description has been provided for this image
No description has been provided for this image
No description has been provided for this image
  0%|          | 0/469 [00:00<?, ?it/s]
Epoch 72, step 34000: Generator loss: 0.9666918925046921, discriminator loss: 0.6075156236886978
No description has been provided for this image
No description has been provided for this image
No description has been provided for this image
  0%|          | 0/469 [00:00<?, ?it/s]
Epoch 73, step 34500: Generator loss: 0.985197079539299, discriminator loss: 0.6011134975552559
No description has been provided for this image
No description has been provided for this image
No description has been provided for this image
  0%|          | 0/469 [00:00<?, ?it/s]
Epoch 74, step 35000: Generator loss: 0.9729308484792709, discriminator loss: 0.5966345617771148
No description has been provided for this image
No description has been provided for this image
No description has been provided for this image
  0%|          | 0/469 [00:00<?, ?it/s]
Epoch 75, step 35500: Generator loss: 0.9634453411102295, discriminator loss: 0.597517226934433
No description has been provided for this image
No description has been provided for this image
No description has been provided for this image
  0%|          | 0/469 [00:00<?, ?it/s]
Epoch 76, step 36000: Generator loss: 0.9687848848104477, discriminator loss: 0.6013473935723305
No description has been provided for this image
No description has been provided for this image
No description has been provided for this image
  0%|          | 0/469 [00:00<?, ?it/s]
Epoch 77, step 36500: Generator loss: 0.9802024928331375, discriminator loss: 0.6005387331843376
No description has been provided for this image
No description has been provided for this image
No description has been provided for this image
  0%|          | 0/469 [00:00<?, ?it/s]
Epoch 78, step 37000: Generator loss: 0.9731533393859864, discriminator loss: 0.5963126164674759
No description has been provided for this image
No description has been provided for this image
No description has been provided for this image
  0%|          | 0/469 [00:00<?, ?it/s]
Epoch 79, step 37500: Generator loss: 0.9780632754564286, discriminator loss: 0.5968187508583069
No description has been provided for this image
No description has been provided for this image
No description has been provided for this image
  0%|          | 0/469 [00:00<?, ?it/s]
  0%|          | 0/469 [00:00<?, ?it/s]
Epoch 81, step 38000: Generator loss: 0.9595166032314301, discriminator loss: 0.5972266513109207
No description has been provided for this image
No description has been provided for this image
No description has been provided for this image
  0%|          | 0/469 [00:00<?, ?it/s]
Epoch 82, step 38500: Generator loss: 0.9946556317806244, discriminator loss: 0.59203677880764
No description has been provided for this image
No description has been provided for this image
No description has been provided for this image
  0%|          | 0/469 [00:00<?, ?it/s]
Epoch 83, step 39000: Generator loss: 1.0046718139648438, discriminator loss: 0.6016295446157456
No description has been provided for this image
No description has been provided for this image
No description has been provided for this image
  0%|          | 0/469 [00:00<?, ?it/s]
Epoch 84, step 39500: Generator loss: 0.9973438510894775, discriminator loss: 0.5925647712945938
No description has been provided for this image
No description has been provided for this image
No description has been provided for this image
  0%|          | 0/469 [00:00<?, ?it/s]
Epoch 85, step 40000: Generator loss: 0.9907611086368561, discriminator loss: 0.5950615196824074
No description has been provided for this image
No description has been provided for this image
No description has been provided for this image
  0%|          | 0/469 [00:00<?, ?it/s]
Epoch 86, step 40500: Generator loss: 0.9770873655080795, discriminator loss: 0.5914944817423821
No description has been provided for this image
No description has been provided for this image
No description has been provided for this image
  0%|          | 0/469 [00:00<?, ?it/s]
Epoch 87, step 41000: Generator loss: 0.9874985775947571, discriminator loss: 0.6006929357051849
No description has been provided for this image
No description has been provided for this image
No description has been provided for this image
  0%|          | 0/469 [00:00<?, ?it/s]
Epoch 88, step 41500: Generator loss: 0.968919203877449, discriminator loss: 0.5986975821256637
No description has been provided for this image
No description has been provided for this image
No description has been provided for this image
  0%|          | 0/469 [00:00<?, ?it/s]
Epoch 89, step 42000: Generator loss: 0.9951355646848679, discriminator loss: 0.592059340596199
No description has been provided for this image
No description has been provided for this image
No description has been provided for this image
  0%|          | 0/469 [00:00<?, ?it/s]
Epoch 90, step 42500: Generator loss: 1.004955737233162, discriminator loss: 0.5939880201816559
No description has been provided for this image
No description has been provided for this image
No description has been provided for this image
  0%|          | 0/469 [00:00<?, ?it/s]
Epoch 91, step 43000: Generator loss: 0.9943067176342011, discriminator loss: 0.592178800880909
No description has been provided for this image
No description has been provided for this image
No description has been provided for this image
  0%|          | 0/469 [00:00<?, ?it/s]
Epoch 92, step 43500: Generator loss: 0.9897982699871063, discriminator loss: 0.5893359208703041
No description has been provided for this image
No description has been provided for this image
No description has been provided for this image
  0%|          | 0/469 [00:00<?, ?it/s]
Epoch 93, step 44000: Generator loss: 1.0014823336601257, discriminator loss: 0.5867925834059715
No description has been provided for this image
No description has been provided for this image
No description has been provided for this image
  0%|          | 0/469 [00:00<?, ?it/s]
Epoch 94, step 44500: Generator loss: 1.0084335910081863, discriminator loss: 0.588168249309063
No description has been provided for this image
No description has been provided for this image
No description has been provided for this image
  0%|          | 0/469 [00:00<?, ?it/s]
Epoch 95, step 45000: Generator loss: 0.9918670070171356, discriminator loss: 0.5872072502970695
No description has been provided for this image
No description has been provided for this image
No description has been provided for this image
  0%|          | 0/469 [00:00<?, ?it/s]
  0%|          | 0/469 [00:00<?, ?it/s]
Epoch 97, step 45500: Generator loss: 0.9993983345031738, discriminator loss: 0.5832995727658272
No description has been provided for this image
No description has been provided for this image
No description has been provided for this image
  0%|          | 0/469 [00:00<?, ?it/s]
Epoch 98, step 46000: Generator loss: 1.0084207981824875, discriminator loss: 0.5893421694636345
No description has been provided for this image
No description has been provided for this image
No description has been provided for this image
  0%|          | 0/469 [00:00<?, ?it/s]
Epoch 99, step 46500: Generator loss: 1.005779152035713, discriminator loss: 0.5812958228588104
No description has been provided for this image
No description has been provided for this image
No description has been provided for this image
  0%|          | 0/469 [00:00<?, ?it/s]
Epoch 100, step 47000: Generator loss: 1.0012432055473328, discriminator loss: 0.5822467103600502
No description has been provided for this image
No description has been provided for this image
No description has been provided for this image
  0%|          | 0/469 [00:00<?, ?it/s]
Epoch 101, step 47500: Generator loss: 1.0169043349027633, discriminator loss: 0.5826327429413796
No description has been provided for this image
No description has been provided for this image
No description has been provided for this image
  0%|          | 0/469 [00:00<?, ?it/s]
Epoch 102, step 48000: Generator loss: 1.0110969021320344, discriminator loss: 0.5813872421383858
No description has been provided for this image
No description has been provided for this image
No description has been provided for this image
  0%|          | 0/469 [00:00<?, ?it/s]
Epoch 103, step 48500: Generator loss: 1.023488322019577, discriminator loss: 0.5831918702125549
No description has been provided for this image
No description has been provided for this image
No description has been provided for this image
  0%|          | 0/469 [00:00<?, ?it/s]
Epoch 104, step 49000: Generator loss: 1.0335553978681564, discriminator loss: 0.5784744457006454
No description has been provided for this image
No description has been provided for this image
No description has been provided for this image
  0%|          | 0/469 [00:00<?, ?it/s]
Epoch 105, step 49500: Generator loss: 1.0189447674751282, discriminator loss: 0.5820126984715461
No description has been provided for this image
No description has been provided for this image
No description has been provided for this image
  0%|          | 0/469 [00:00<?, ?it/s]
Epoch 106, step 50000: Generator loss: 1.0221210837364196, discriminator loss: 0.5716938080191613
No description has been provided for this image
No description has been provided for this image
No description has been provided for this image
  0%|          | 0/469 [00:00<?, ?it/s]
Epoch 107, step 50500: Generator loss: 1.0251933991909028, discriminator loss: 0.5766321730017662
No description has been provided for this image
No description has been provided for this image
No description has been provided for this image
  0%|          | 0/469 [00:00<?, ?it/s]
Epoch 108, step 51000: Generator loss: 1.0197134354114532, discriminator loss: 0.5801153265833855
No description has been provided for this image
No description has been provided for this image
No description has been provided for this image
  0%|          | 0/469 [00:00<?, ?it/s]
Epoch 109, step 51500: Generator loss: 1.0264078443050384, discriminator loss: 0.573182380259037
No description has been provided for this image
No description has been provided for this image
No description has been provided for this image
  0%|          | 0/469 [00:00<?, ?it/s]
Epoch 110, step 52000: Generator loss: 1.025400733590126, discriminator loss: 0.578817637860775
No description has been provided for this image
No description has been provided for this image
No description has been provided for this image
  0%|          | 0/469 [00:00<?, ?it/s]
Epoch 111, step 52500: Generator loss: 1.0250889576673508, discriminator loss: 0.5751831395626068
No description has been provided for this image
No description has been provided for this image
No description has been provided for this image
  0%|          | 0/469 [00:00<?, ?it/s]
  0%|          | 0/469 [00:00<?, ?it/s]
Epoch 113, step 53000: Generator loss: 1.0345792025327682, discriminator loss: 0.5761105507016182
No description has been provided for this image
No description has been provided for this image
No description has been provided for this image
  0%|          | 0/469 [00:00<?, ?it/s]
Epoch 114, step 53500: Generator loss: 1.046409807920456, discriminator loss: 0.5670096014738083
No description has been provided for this image
No description has been provided for this image
No description has been provided for this image
  0%|          | 0/469 [00:00<?, ?it/s]
Epoch 115, step 54000: Generator loss: 1.043058182477951, discriminator loss: 0.5697268338799477
No description has been provided for this image
No description has been provided for this image
No description has been provided for this image
  0%|          | 0/469 [00:00<?, ?it/s]
Epoch 116, step 54500: Generator loss: 1.0440865910053254, discriminator loss: 0.5709615953564644
No description has been provided for this image
No description has been provided for this image
No description has been provided for this image
  0%|          | 0/469 [00:00<?, ?it/s]
Epoch 117, step 55000: Generator loss: 1.0426995037794113, discriminator loss: 0.5676410868763924
No description has been provided for this image
No description has been provided for this image
No description has been provided for this image
  0%|          | 0/469 [00:00<?, ?it/s]
Epoch 118, step 55500: Generator loss: 1.0447862722873689, discriminator loss: 0.570641079068184
No description has been provided for this image
No description has been provided for this image
No description has been provided for this image
  0%|          | 0/469 [00:00<?, ?it/s]
Epoch 119, step 56000: Generator loss: 1.0509468381404876, discriminator loss: 0.5667704539299011
No description has been provided for this image
No description has been provided for this image
No description has been provided for this image
  0%|          | 0/469 [00:00<?, ?it/s]
Epoch 120, step 56500: Generator loss: 1.0431218415498733, discriminator loss: 0.5697332881093026
No description has been provided for this image
No description has been provided for this image
No description has been provided for this image
  0%|          | 0/469 [00:00<?, ?it/s]
Epoch 121, step 57000: Generator loss: 1.0509914045333861, discriminator loss: 0.5675132256150246
No description has been provided for this image
No description has been provided for this image
No description has been provided for this image
  0%|          | 0/469 [00:00<?, ?it/s]
Epoch 122, step 57500: Generator loss: 1.0600460569858552, discriminator loss: 0.5695472390055657
No description has been provided for this image
No description has been provided for this image
No description has been provided for this image
  0%|          | 0/469 [00:00<?, ?it/s]
Epoch 123, step 58000: Generator loss: 1.049864450097084, discriminator loss: 0.5721188992857933
No description has been provided for this image
No description has been provided for this image
No description has been provided for this image
  0%|          | 0/469 [00:00<?, ?it/s]
Epoch 124, step 58500: Generator loss: 1.057814681649208, discriminator loss: 0.5665506597161293
No description has been provided for this image
No description has been provided for this image
No description has been provided for this image
  0%|          | 0/469 [00:00<?, ?it/s]
Epoch 125, step 59000: Generator loss: 1.0607161283493043, discriminator loss: 0.5659274329543114
No description has been provided for this image
No description has been provided for this image
No description has been provided for this image
  0%|          | 0/469 [00:00<?, ?it/s]
Epoch 126, step 59500: Generator loss: 1.0576261911392213, discriminator loss: 0.5697718257308007
No description has been provided for this image
No description has been provided for this image
No description has been provided for this image
  0%|          | 0/469 [00:00<?, ?it/s]
Epoch 127, step 60000: Generator loss: 1.0615184675455094, discriminator loss: 0.5659393563866615
No description has been provided for this image
No description has been provided for this image
No description has been provided for this image
  0%|          | 0/469 [00:00<?, ?it/s]
Epoch 128, step 60500: Generator loss: 1.0663750462532045, discriminator loss: 0.5642126491069793
No description has been provided for this image
No description has been provided for this image
No description has been provided for this image
  0%|          | 0/469 [00:00<?, ?it/s]
  0%|          | 0/469 [00:00<?, ?it/s]
Epoch 130, step 61000: Generator loss: 1.0743729020357131, discriminator loss: 0.5611261808276177
No description has been provided for this image
No description has been provided for this image
No description has been provided for this image
  0%|          | 0/469 [00:00<?, ?it/s]
Epoch 131, step 61500: Generator loss: 1.0573465493917464, discriminator loss: 0.5666580362915993
No description has been provided for this image
No description has been provided for this image
No description has been provided for this image
  0%|          | 0/469 [00:00<?, ?it/s]
Epoch 132, step 62000: Generator loss: 1.0756184371709823, discriminator loss: 0.5646456980109215
No description has been provided for this image
No description has been provided for this image
No description has been provided for this image
  0%|          | 0/469 [00:00<?, ?it/s]
Epoch 133, step 62500: Generator loss: 1.0694524844884872, discriminator loss: 0.569121537566185
No description has been provided for this image
No description has been provided for this image
No description has been provided for this image
  0%|          | 0/469 [00:00<?, ?it/s]
Epoch 134, step 63000: Generator loss: 1.0663066757917403, discriminator loss: 0.5699702188372612
No description has been provided for this image
No description has been provided for this image
No description has been provided for this image
  0%|          | 0/469 [00:00<?, ?it/s]
Epoch 135, step 63500: Generator loss: 1.0663514223098756, discriminator loss: 0.5695594551563263
No description has been provided for this image
No description has been provided for this image
No description has been provided for this image
  0%|          | 0/469 [00:00<?, ?it/s]
Epoch 136, step 64000: Generator loss: 1.0644668765068055, discriminator loss: 0.5682681980729103
No description has been provided for this image
No description has been provided for this image
No description has been provided for this image
  0%|          | 0/469 [00:00<?, ?it/s]
Epoch 137, step 64500: Generator loss: 1.0550921256542205, discriminator loss: 0.5696422832608223
No description has been provided for this image
No description has been provided for this image
No description has been provided for this image
  0%|          | 0/469 [00:00<?, ?it/s]
Epoch 138, step 65000: Generator loss: 1.055631823182106, discriminator loss: 0.5705020905137063
No description has been provided for this image
No description has been provided for this image
No description has been provided for this image
  0%|          | 0/469 [00:00<?, ?it/s]
Epoch 139, step 65500: Generator loss: 1.058024223446846, discriminator loss: 0.5688595096468926
No description has been provided for this image
No description has been provided for this image
No description has been provided for this image
  0%|          | 0/469 [00:00<?, ?it/s]
Epoch 140, step 66000: Generator loss: 1.0759759875535966, discriminator loss: 0.573324174284935
No description has been provided for this image
No description has been provided for this image
No description has been provided for this image
  0%|          | 0/469 [00:00<?, ?it/s]
Epoch 141, step 66500: Generator loss: 1.0771814155578614, discriminator loss: 0.5739586219787598
No description has been provided for this image
No description has been provided for this image
No description has been provided for this image
  0%|          | 0/469 [00:00<?, ?it/s]
Epoch 142, step 67000: Generator loss: 1.0670026228427887, discriminator loss: 0.565967336654663
No description has been provided for this image
No description has been provided for this image
No description has been provided for this image
  0%|          | 0/469 [00:00<?, ?it/s]
Epoch 143, step 67500: Generator loss: 1.0589428154230118, discriminator loss: 0.5749310872554779
No description has been provided for this image
No description has been provided for this image
No description has been provided for this image
  0%|          | 0/469 [00:00<?, ?it/s]
Epoch 144, step 68000: Generator loss: 1.0735257205963136, discriminator loss: 0.5708859901428223
No description has been provided for this image
No description has been provided for this image
No description has been provided for this image
  0%|          | 0/469 [00:00<?, ?it/s]
Epoch 146, step 68500: Generator loss: 1.085207364320755, discriminator loss: 0.5710993441343307
No description has been provided for this image
No description has been provided for this image
No description has been provided for this image
  0%|          | 0/469 [00:00<?, ?it/s]
Epoch 147, step 69000: Generator loss: 1.0593492151498796, discriminator loss: 0.5720132147073745
No description has been provided for this image
No description has been provided for this image
No description has been provided for this image
  0%|          | 0/469 [00:00<?, ?it/s]
Epoch 148, step 69500: Generator loss: 1.064256736278534, discriminator loss: 0.5665577530860901
No description has been provided for this image
No description has been provided for this image
No description has been provided for this image
  0%|          | 0/469 [00:00<?, ?it/s]
Epoch 149, step 70000: Generator loss: 1.0695160275697708, discriminator loss: 0.573642312347889
No description has been provided for this image
No description has been provided for this image
No description has been provided for this image
  0%|          | 0/469 [00:00<?, ?it/s]
Epoch 150, step 70500: Generator loss: 1.0682124434709548, discriminator loss: 0.5700670898556709
No description has been provided for this image
No description has been provided for this image
No description has been provided for this image
  0%|          | 0/469 [00:00<?, ?it/s]
Epoch 151, step 71000: Generator loss: 1.0720481954813004, discriminator loss: 0.5675706258416175
No description has been provided for this image
No description has been provided for this image
No description has been provided for this image
  0%|          | 0/469 [00:00<?, ?it/s]
Epoch 152, step 71500: Generator loss: 1.0719645861387253, discriminator loss: 0.5696461454629899
No description has been provided for this image
No description has been provided for this image
No description has been provided for this image
  0%|          | 0/469 [00:00<?, ?it/s]
Epoch 153, step 72000: Generator loss: 1.0640132036209107, discriminator loss: 0.5676938418149948
No description has been provided for this image
No description has been provided for this image
No description has been provided for this image
  0%|          | 0/469 [00:00<?, ?it/s]
Epoch 154, step 72500: Generator loss: 1.0774863104820251, discriminator loss: 0.5696572477817535
No description has been provided for this image
No description has been provided for this image
No description has been provided for this image
  0%|          | 0/469 [00:00<?, ?it/s]
Epoch 155, step 73000: Generator loss: 1.0846751042604446, discriminator loss: 0.5695129683613778
No description has been provided for this image
No description has been provided for this image
No description has been provided for this image
  0%|          | 0/469 [00:00<?, ?it/s]
Epoch 156, step 73500: Generator loss: 1.0688781418800355, discriminator loss: 0.5694116997122765
No description has been provided for this image
No description has been provided for this image
No description has been provided for this image
  0%|          | 0/469 [00:00<?, ?it/s]
Epoch 157, step 74000: Generator loss: 1.071542314171791, discriminator loss: 0.5739160211086273
No description has been provided for this image
No description has been provided for this image
No description has been provided for this image
  0%|          | 0/469 [00:00<?, ?it/s]
Epoch 158, step 74500: Generator loss: 1.0847300235033035, discriminator loss: 0.5704194900393486
No description has been provided for this image
No description has been provided for this image
No description has been provided for this image
  0%|          | 0/469 [00:00<?, ?it/s]
Epoch 159, step 75000: Generator loss: 1.0868128070831298, discriminator loss: 0.5691923908591271
No description has been provided for this image
No description has been provided for this image
No description has been provided for this image
  0%|          | 0/469 [00:00<?, ?it/s]
Epoch 160, step 75500: Generator loss: 1.055856355190277, discriminator loss: 0.5733889238834381
No description has been provided for this image
No description has been provided for this image
No description has been provided for this image
  0%|          | 0/469 [00:00<?, ?it/s]
  0%|          | 0/469 [00:00<?, ?it/s]
Epoch 162, step 76000: Generator loss: 1.0819706790447234, discriminator loss: 0.5653914992213249
No description has been provided for this image
No description has been provided for this image
No description has been provided for this image
  0%|          | 0/469 [00:00<?, ?it/s]
Epoch 163, step 76500: Generator loss: 1.0538540441989899, discriminator loss: 0.5795382104516029
No description has been provided for this image
No description has been provided for this image
No description has been provided for this image
  0%|          | 0/469 [00:00<?, ?it/s]
Epoch 164, step 77000: Generator loss: 1.0863464752435683, discriminator loss: 0.568696259200573
No description has been provided for this image
No description has been provided for this image
No description has been provided for this image
  0%|          | 0/469 [00:00<?, ?it/s]
Epoch 165, step 77500: Generator loss: 1.0780459738969803, discriminator loss: 0.5726611486077309
No description has been provided for this image
No description has been provided for this image
No description has been provided for this image
  0%|          | 0/469 [00:00<?, ?it/s]
Epoch 166, step 78000: Generator loss: 1.0684958882331848, discriminator loss: 0.5709155834913254
No description has been provided for this image
No description has been provided for this image
No description has been provided for this image
  0%|          | 0/469 [00:00<?, ?it/s]
Epoch 167, step 78500: Generator loss: 1.0799500557184218, discriminator loss: 0.5744387047886849
No description has been provided for this image
No description has been provided for this image
No description has been provided for this image
  0%|          | 0/469 [00:00<?, ?it/s]
Epoch 168, step 79000: Generator loss: 1.0891749030351638, discriminator loss: 0.5703308569192886
No description has been provided for this image
No description has been provided for this image
No description has been provided for this image
  0%|          | 0/469 [00:00<?, ?it/s]
Epoch 169, step 79500: Generator loss: 1.0801849263906478, discriminator loss: 0.5717149977684021
No description has been provided for this image
No description has been provided for this image
No description has been provided for this image
  0%|          | 0/469 [00:00<?, ?it/s]
Epoch 170, step 80000: Generator loss: 1.0773317233324051, discriminator loss: 0.572909461915493
No description has been provided for this image
No description has been provided for this image
No description has been provided for this image
  0%|          | 0/469 [00:00<?, ?it/s]
Epoch 171, step 80500: Generator loss: 1.0868586196899415, discriminator loss: 0.5702256690263748
No description has been provided for this image
No description has been provided for this image
No description has been provided for this image
  0%|          | 0/469 [00:00<?, ?it/s]
Epoch 172, step 81000: Generator loss: 1.0818107388019562, discriminator loss: 0.5666396592259407
No description has been provided for this image
No description has been provided for this image
No description has been provided for this image
  0%|          | 0/469 [00:00<?, ?it/s]
Epoch 173, step 81500: Generator loss: 1.0765926374197006, discriminator loss: 0.5795883925557137
No description has been provided for this image
No description has been provided for this image
No description has been provided for this image
  0%|          | 0/469 [00:00<?, ?it/s]
Epoch 174, step 82000: Generator loss: 1.064666698694229, discriminator loss: 0.5703501603603363
No description has been provided for this image
No description has been provided for this image
No description has been provided for this image
  0%|          | 0/469 [00:00<?, ?it/s]
Epoch 175, step 82500: Generator loss: 1.0683815361261368, discriminator loss: 0.5778474681973458
No description has been provided for this image
No description has been provided for this image
No description has been provided for this image
  0%|          | 0/469 [00:00<?, ?it/s]
Epoch 176, step 83000: Generator loss: 1.0776479239463805, discriminator loss: 0.5652679976820946
No description has been provided for this image
No description has been provided for this image
No description has been provided for this image
  0%|          | 0/469 [00:00<?, ?it/s]
  0%|          | 0/469 [00:00<?, ?it/s]
Epoch 178, step 83500: Generator loss: 1.0784572540521622, discriminator loss: 0.5711396316289902
No description has been provided for this image
No description has been provided for this image
No description has been provided for this image
  0%|          | 0/469 [00:00<?, ?it/s]
Epoch 179, step 84000: Generator loss: 1.0799720207452774, discriminator loss: 0.5715777632594109
No description has been provided for this image
No description has been provided for this image
No description has been provided for this image
  0%|          | 0/469 [00:00<?, ?it/s]
Epoch 180, step 84500: Generator loss: 1.0897232381105424, discriminator loss: 0.5722200784087181
No description has been provided for this image
No description has been provided for this image
No description has been provided for this image
  0%|          | 0/469 [00:00<?, ?it/s]
Epoch 181, step 85000: Generator loss: 1.0807708615064622, discriminator loss: 0.573267793238163
No description has been provided for this image
No description has been provided for this image
No description has been provided for this image
  0%|          | 0/469 [00:00<?, ?it/s]
Epoch 182, step 85500: Generator loss: 1.0747569193840028, discriminator loss: 0.568444437801838
No description has been provided for this image
No description has been provided for this image
No description has been provided for this image
  0%|          | 0/469 [00:00<?, ?it/s]
Epoch 183, step 86000: Generator loss: 1.0965240434408188, discriminator loss: 0.5684093906879425
No description has been provided for this image
No description has been provided for this image
No description has been provided for this image
  0%|          | 0/469 [00:00<?, ?it/s]
Epoch 184, step 86500: Generator loss: 1.0669475437402725, discriminator loss: 0.570864848613739
No description has been provided for this image
No description has been provided for this image
No description has been provided for this image
  0%|          | 0/469 [00:00<?, ?it/s]
Epoch 185, step 87000: Generator loss: 1.0866483138799667, discriminator loss: 0.5801505998969078
No description has been provided for this image
No description has been provided for this image
No description has been provided for this image
  0%|          | 0/469 [00:00<?, ?it/s]
Epoch 186, step 87500: Generator loss: 1.0898144243955612, discriminator loss: 0.577188600718975
No description has been provided for this image
No description has been provided for this image
No description has been provided for this image
  0%|          | 0/469 [00:00<?, ?it/s]
Epoch 187, step 88000: Generator loss: 1.0560118396282197, discriminator loss: 0.57802058416605
No description has been provided for this image
No description has been provided for this image
No description has been provided for this image
  0%|          | 0/469 [00:00<?, ?it/s]
Epoch 188, step 88500: Generator loss: 1.081513246178627, discriminator loss: 0.5700414397716522
No description has been provided for this image
No description has been provided for this image
No description has been provided for this image
  0%|          | 0/469 [00:00<?, ?it/s]
Epoch 189, step 89000: Generator loss: 1.08189000415802, discriminator loss: 0.5706097315549851
No description has been provided for this image
No description has been provided for this image
No description has been provided for this image
  0%|          | 0/469 [00:00<?, ?it/s]
Epoch 190, step 89500: Generator loss: 1.0741279730796813, discriminator loss: 0.5842734354138375
No description has been provided for this image
No description has been provided for this image
No description has been provided for this image
  0%|          | 0/469 [00:00<?, ?it/s]
Epoch 191, step 90000: Generator loss: 1.0650814998149871, discriminator loss: 0.5789232801198959
No description has been provided for this image
No description has been provided for this image
No description has been provided for this image
  0%|          | 0/469 [00:00<?, ?it/s]
Epoch 192, step 90500: Generator loss: 1.0703366216421126, discriminator loss: 0.5697177290916443
No description has been provided for this image
No description has been provided for this image
No description has been provided for this image
  0%|          | 0/469 [00:00<?, ?it/s]
  0%|          | 0/469 [00:00<?, ?it/s]
Epoch 194, step 91000: Generator loss: 1.0717908999919892, discriminator loss: 0.5789009360074997
No description has been provided for this image
No description has been provided for this image
No description has been provided for this image
  0%|          | 0/469 [00:00<?, ?it/s]
Epoch 195, step 91500: Generator loss: 1.0874603331089019, discriminator loss: 0.5739682900309563
No description has been provided for this image
No description has been provided for this image
No description has been provided for this image
  0%|          | 0/469 [00:00<?, ?it/s]
Epoch 196, step 92000: Generator loss: 1.069947368979454, discriminator loss: 0.5766175038814545
No description has been provided for this image
No description has been provided for this image
No description has been provided for this image
  0%|          | 0/469 [00:00<?, ?it/s]
Epoch 197, step 92500: Generator loss: 1.107958074271679, discriminator loss: 0.5807928264141082
No description has been provided for this image
No description has been provided for this image
No description has been provided for this image
  0%|          | 0/469 [00:00<?, ?it/s]
Epoch 198, step 93000: Generator loss: 1.0663117953538894, discriminator loss: 0.5773091700673103
No description has been provided for this image
No description has been provided for this image
No description has been provided for this image
  0%|          | 0/469 [00:00<?, ?it/s]
Epoch 199, step 93500: Generator loss: 1.0706544547080994, discriminator loss: 0.5798768946528434
No description has been provided for this image
No description has been provided for this image
No description has been provided for this image

Exploration¶

You can do a bit of exploration now!

In [15]:
Copied!
# Before you explore, you should put the generator
# in eval mode, both in general and so that batch norm
# doesn't cause you issues and is using its eval statistics
gen = gen.eval()
# Before you explore, you should put the generator # in eval mode, both in general and so that batch norm # doesn't cause you issues and is using its eval statistics gen = gen.eval()

Changing the Class Vector¶

You can generate some numbers with your new model! You can add interpolation as well to make it more interesting.

So starting from a image, you will produce intermediate images that look more and more like the ending image until you get to the final image. Your're basically morphing one image into another. You can choose what these two images will be using your conditional GAN.

In [19]:
Copied!
import math

### Change me! ###
n_interpolation = 9 # Choose the interpolation: how many intermediate images you want + 2 (for the start and end image)
interpolation_noise = get_noise(1, z_dim, device=device).repeat(n_interpolation, 1)

def interpolate_class(first_number, second_number):
    first_label = get_one_hot_labels(torch.Tensor([first_number]).long(), n_classes)
    second_label = get_one_hot_labels(torch.Tensor([second_number]).long(), n_classes)

    # Calculate the interpolation vector between the two labels
    percent_second_label = torch.linspace(0, 1, n_interpolation)[:, None]
    interpolation_labels = first_label * (1 - percent_second_label) + second_label * percent_second_label

    # Combine the noise and the labels
    noise_and_labels = combine_vectors(interpolation_noise, interpolation_labels.to(device))
    fake = gen(noise_and_labels)
    show_tensor_images(fake, num_images=n_interpolation, nrow=int(math.sqrt(n_interpolation)), show=False)

### Change me! ###
start_plot_number = 1 # Choose the start digit
### Change me! ###
end_plot_number = 5 # Choose the end digit

plt.figure(figsize=(8, 8))
interpolate_class(start_plot_number, end_plot_number)
_ = plt.axis('off')

### Uncomment the following lines of code if you would like to visualize a set of pairwise class 
### interpolations for a collection of different numbers, all in a single grid of interpolations.
### You'll also see another visualization like this in the next code block!
plot_numbers = [2, 3, 4, 5, 7]
n_numbers = len(plot_numbers)
plt.figure(figsize=(8, 8))
for i, first_plot_number in enumerate(plot_numbers):
     for j, second_plot_number in enumerate(plot_numbers):
         plt.subplot(n_numbers, n_numbers, i * n_numbers + j + 1)
         interpolate_class(first_plot_number, second_plot_number)
         plt.axis('off')
plt.subplots_adjust(top=1, bottom=0, left=0, right=1, hspace=0.1, wspace=0)
plt.show()
plt.close()
import math ### Change me! ### n_interpolation = 9 # Choose the interpolation: how many intermediate images you want + 2 (for the start and end image) interpolation_noise = get_noise(1, z_dim, device=device).repeat(n_interpolation, 1) def interpolate_class(first_number, second_number): first_label = get_one_hot_labels(torch.Tensor([first_number]).long(), n_classes) second_label = get_one_hot_labels(torch.Tensor([second_number]).long(), n_classes) # Calculate the interpolation vector between the two labels percent_second_label = torch.linspace(0, 1, n_interpolation)[:, None] interpolation_labels = first_label * (1 - percent_second_label) + second_label * percent_second_label # Combine the noise and the labels noise_and_labels = combine_vectors(interpolation_noise, interpolation_labels.to(device)) fake = gen(noise_and_labels) show_tensor_images(fake, num_images=n_interpolation, nrow=int(math.sqrt(n_interpolation)), show=False) ### Change me! ### start_plot_number = 1 # Choose the start digit ### Change me! ### end_plot_number = 5 # Choose the end digit plt.figure(figsize=(8, 8)) interpolate_class(start_plot_number, end_plot_number) _ = plt.axis('off') ### Uncomment the following lines of code if you would like to visualize a set of pairwise class ### interpolations for a collection of different numbers, all in a single grid of interpolations. ### You'll also see another visualization like this in the next code block! plot_numbers = [2, 3, 4, 5, 7] n_numbers = len(plot_numbers) plt.figure(figsize=(8, 8)) for i, first_plot_number in enumerate(plot_numbers): for j, second_plot_number in enumerate(plot_numbers): plt.subplot(n_numbers, n_numbers, i * n_numbers + j + 1) interpolate_class(first_plot_number, second_plot_number) plt.axis('off') plt.subplots_adjust(top=1, bottom=0, left=0, right=1, hspace=0.1, wspace=0) plt.show() plt.close()
No description has been provided for this image
No description has been provided for this image
No description has been provided for this image

Changing the Noise Vector¶

Now, what happens if you hold the class constant, but instead you change the noise vector? You can also interpolate the noise vector and generate an image at each step.

In [20]:
Copied!
n_interpolation = 9 # How many intermediate images you want + 2 (for the start and end image)

# This time you're interpolating between the noise instead of the labels
interpolation_label = get_one_hot_labels(torch.Tensor([5]).long(), n_classes).repeat(n_interpolation, 1).float()

def interpolate_noise(first_noise, second_noise):
    # This time you're interpolating between the noise instead of the labels
    percent_first_noise = torch.linspace(0, 1, n_interpolation)[:, None].to(device)
    interpolation_noise = first_noise * percent_first_noise + second_noise * (1 - percent_first_noise)

    # Combine the noise and the labels again
    noise_and_labels = combine_vectors(interpolation_noise, interpolation_label.to(device))
    fake = gen(noise_and_labels)
    show_tensor_images(fake, num_images=n_interpolation, nrow=int(math.sqrt(n_interpolation)), show=False)

# Generate noise vectors to interpolate between
### Change me! ###
n_noise = 5 # Choose the number of noise examples in the grid
plot_noises = [get_noise(1, z_dim, device=device) for i in range(n_noise)]
plt.figure(figsize=(8, 8))
for i, first_plot_noise in enumerate(plot_noises):
    for j, second_plot_noise in enumerate(plot_noises):
        plt.subplot(n_noise, n_noise, i * n_noise + j + 1)
        interpolate_noise(first_plot_noise, second_plot_noise)
        plt.axis('off')
plt.subplots_adjust(top=1, bottom=0, left=0, right=1, hspace=0.1, wspace=0)
plt.show()
plt.close()
n_interpolation = 9 # How many intermediate images you want + 2 (for the start and end image) # This time you're interpolating between the noise instead of the labels interpolation_label = get_one_hot_labels(torch.Tensor([5]).long(), n_classes).repeat(n_interpolation, 1).float() def interpolate_noise(first_noise, second_noise): # This time you're interpolating between the noise instead of the labels percent_first_noise = torch.linspace(0, 1, n_interpolation)[:, None].to(device) interpolation_noise = first_noise * percent_first_noise + second_noise * (1 - percent_first_noise) # Combine the noise and the labels again noise_and_labels = combine_vectors(interpolation_noise, interpolation_label.to(device)) fake = gen(noise_and_labels) show_tensor_images(fake, num_images=n_interpolation, nrow=int(math.sqrt(n_interpolation)), show=False) # Generate noise vectors to interpolate between ### Change me! ### n_noise = 5 # Choose the number of noise examples in the grid plot_noises = [get_noise(1, z_dim, device=device) for i in range(n_noise)] plt.figure(figsize=(8, 8)) for i, first_plot_noise in enumerate(plot_noises): for j, second_plot_noise in enumerate(plot_noises): plt.subplot(n_noise, n_noise, i * n_noise + j + 1) interpolate_noise(first_plot_noise, second_plot_noise) plt.axis('off') plt.subplots_adjust(top=1, bottom=0, left=0, right=1, hspace=0.1, wspace=0) plt.show() plt.close()
No description has been provided for this image
In [ ]:
Copied!


Documentation built with MkDocs.

Keyboard Shortcuts

Keys Action
? Open this help
n Next page
p Previous page
s Search