WalzoneInterview Prep
📞 Interviewing soon? Practice with a realistic AI mock phone interview — it calls you, then scores you. First 15 min FREE →

PyTorch · Expert · question 70 of 100

Describe the process of implementing and training generative adversarial networks (GANs) in PyTorch, including techniques for stabilizing training and measuring performance.?

📕 Buy this interview preparation book: 100 PyTorch questions & answers — PDF + EPUB for $5

Generative Adversarial Networks (GANs) have been a popular topic in the field of Deep Learning for generating synthetic data that looks like it was sampled from the training data. GANs have multiple applications such as image synthesis, data augmentation, image-to-image translation, and text generation.

In PyTorch, implementing and training GANs involves the following steps:

1. Importing necessary modules and setting up the device, such as GPU or CPU.

import torch
import torch.nn as nn
import torch.optim as optim
import torchvision
import torchvision.transforms as transforms

device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")

2. Defining the discriminator and generator networks. Discriminator network tries to classify the input data into real or fake, while the generator network tries to generate fake data to fool the discriminator.

class Discriminator(nn.Module):
    def __init__(self):
        super(Discriminator, self).__init__()
        self.conv_layer = nn.Sequential(
                nn.Conv2d(in_channels=3, out_channels=64, kernel_size=4, stride=2),
                nn.BatchNorm2d(64),
                nn.LeakyReLU(0.2),
                nn.Conv2d(in_channels=64, out_channels=128, kernel_size=4, stride=2),
                nn.BatchNorm2d(128),
                nn.LeakyReLU(0.2),
                nn.Conv2d(in_channels=128, out_channels=256, kernel_size=4, stride=2),
                nn.BatchNorm2d(256),
                nn.LeakyReLU(0.2),
                nn.Conv2d(in_channels=256, out_channels=512, kernel_size=4, stride=2),
                nn.BatchNorm2d(512),
                nn.LeakyReLU(0.2),
                nn.Conv2d(in_channels=512, out_channels=1, kernel_size=4, stride=2),
                nn.Sigmoid()) 

    def forward(self, x):
        # Forward pass
        return self.conv_layer(x).view(-1, 1)
        
        
class Generator(nn.Module):
    def __init__(self):
        super(Generator, self).__init__()
        self.deconv_layer = nn.Sequential(
            nn.ConvTranspose2d(in_channels=100, out_channels=512, kernel_size=4, stride=1),
            nn.BatchNorm2d(512),
            nn.ReLU(True),
            nn.ConvTranspose2d(in_channels=512, out_channels=256, kernel_size=4, stride=2),
            nn.BatchNorm2d(256),
            nn.ReLU(True),
            nn.ConvTranspose2d(in_channels=256, out_channels=128, kernel_size=4, stride=2),
            nn.BatchNorm2d(128),
            nn.ReLU(True),
            nn.ConvTranspose2d(in_channels=128, out_channels=64, kernel_size=4, stride=2),
            nn.BatchNorm2d(64),
            nn.ReLU(True),
            nn.ConvTranspose2d(in_channels=64, out_channels=3, kernel_size=4, stride=2),
            nn.Tanh())
        
    def forward(self, x):
        # Forward pass
        return self.deconv_layer(x)

3. Defining the loss functions and optimizers. The discriminator is trained to minimize binary cross-entropy loss, and the generator is trained to maximize the loss of the discriminator on fake images.

discriminator = Discriminator().to(device)
generator = Generator().to(device)

discriminator_criterion = nn.BCELoss()
generator_criterion = nn.BCELoss()

discriminator_optimizer = optim.Adam(discriminator.parameters(), lr=0.0002, betas=(0.5, 0.999))
generator_optimizer = optim.Adam(generator.parameters(), lr=0.0002, betas=(0.5, 0.999))

4. Training the GAN model with real and fake data. Discriminator training occurs in one batch, while the generator training occurs in another batch.

for epoch in range(num_epochs):
    for batch_idx, (real_images, _) in enumerate(trainloader):
        real_images = real_images.to(device)
        batch_size = real_images.shape[0]
        
        # Train discriminator
        discriminator.zero_grad()
        real_targets = torch.ones(batch_size, 1).to(device)
        fake_targets = torch.zeros(batch_size, 1).to(device)

        # Real images
        real_outputs = discriminator(real_images)
        discriminator_loss_real = discriminator_criterion(real_outputs, real_targets)

        # Fake images
        noise = torch.randn(batch_size, 100, 1, 1).to(device)
        fake_images = generator(noise)
        fake_outputs = discriminator(fake_images.detach())
        discriminator_loss_fake = discriminator_criterion(fake_outputs, fake_targets)

        # Total loss
        discriminator_loss = discriminator_loss_real + discriminator_loss_fake
        discriminator_loss.backward()
        discriminator_optimizer.step()

        # Train generator
        generator.zero_grad()
        fake_outputs = discriminator(fake_images)
        generator_loss = generator_criterion(fake_outputs, real_targets)
        generator_loss.backward()
        generator_optimizer.step()

5. Measuring the performance of the GAN model. GANs can be challenging to measure performance, as no fixed loss function measures the quality of the generated samples. Some popular metrics that can be used for measuring the performance of GANs include the Frechet Inception Distance (FID) and Inception Score. FID measures the quality and diversity of generated images compared to the real data, while Inception Score measures the quality and the diversity of the generated images.

# Measuring FID
import torch.nn.functional as F
from torch.nn import Parameter

def compute_mu_sigma(x, eps=1e-6):
    assert len(x.shape) == 4, "(N, C, H, W)"
    N, C = x.shape[:2]
    vals = x.view(N, C, -1)
    mean = torch.mean(vals, dim=-1, keepdim=True)
    centered = vals - mean
    cov = torch.matmul(centered, centered.transpose(1, 2)) + (eps * torch.eye(C, device=x.device))
    sigma = cov.sum(dim=-1) / (cov.shape[-1] - 1)
    return mean.squeeze(), sigma


class GetFeatures(nn.Module):
    def __init__(self):
        super().__init__()
        self.upsample = nn.Upsample(size=(299, 299), mode='bilinear', align_corners=True)
        self.inception = torchvision.models.inception_v3(pretrained=True, aux_logits=False)
        
        for param in self.inception.parameters():
            param.requires_grad_(False)
        
    def forward(self, x):
        x = self.upsample(x)
        x = self.inception(x)
        return x
    
    
# Training loop...
    
# After training...
with torch.no_grad():
    real_feature_list = []
    fake_feature_list = []
    
    get_features = GetFeatures().to(device)
    
    for batch_idx, (real_images, _) in enumerate(trainloader):
        real_images = real_images.to(device)
        fake_images = generator(torch.randn(real_images.shape[0], 100, device=device))

        # Get features for real images
        real_features = get_features(real_images)
        real_mu, real_sigma = compute_mu_sigma(real_features[:, :2048])
        real_feature_list.append((real_mu.cpu().numpy(), real_sigma.cpu().numpy()))

        # Get features for fake images
        fake_features = get_features(fake_images)
        fake_mu, fake_sigma = compute_mu_sigma(fake_features[:, :2048])
        fake_feature_list.append((fake_mu.cpu().numpy(), fake_sigma.cpu().numpy()))

    real_features = np.array(real_feature_list)
    fake_features = np.array(fake_feature_list)

    # Compute FID
    m = ((real_features.mean(0) - fake_features.mean(0)) ** 2).sum()
    s = np.linalg.norm(real_features.std(0) ** 2 + fake_features.std(0) ** 2 - 2 * (real_features.std(0) * fake_features.std(0)))**0.5
    fid = m + s

6. Techniques for stabilizing GAN training. GANs are known to suffer from training instability, including mode collapse and vanishing gradients. Some techniques that can be used to stabilize training include:

Stabilizing GANs requires continuous experimentation with different architectures, hyperparameters, and loss functions to maintain a balance between discriminator and generator training.

Reading is step one. Saying it out loud is the interview. Our AI interviewer calls your phone and runs a realistic PyTorch interview — then scores it.
📞 Practice PyTorch — free 15 min
📕 Buy this interview preparation book: 100 PyTorch questions & answers — PDF + EPUB for $5

All 100 PyTorch questions · All topics