Department of Information Technology
Natural Language Processing Lab
Semester B.E. Semester VII – INFT
Subject Deep Learning Lab
Laboratory Prof. Rasika Ransing
Teacher:
Laboratory L07
Student Name Roshan Vilas Khatal
Roll Number 22101A0040
Grade and
Subject Teacher’s
Signature
Experiment 09
Number
Experiment Train a DCGAN to generate synthetic images and evaluate output quality
Title
Resources / Hardware: Desktop/Laptop Software: Google Colab
Apparatus
Required
Code: import os
import torch
import torch.nn as nn
import torch.optim as optim
from torch.utils.data import DataLoader, Dataset, Subset
from torchvision import transforms, utils
from PIL import Image
import kagglehub
from glob import glob
# -----------------------------
# Download CelebA via kagglehub
# -----------------------------
path = kagglehub.dataset_download("jessicali9530/celeba-
dataset")
print("Path to dataset files:", path)
# CelebA images folder
data_path = os.path.join(path, "img_align_celeba")
print("Checking images folder exists:",
os.path.exists(data_path))
# -----------------------------
# Hyperparameters
# -----------------------------
device = torch.device("cuda" if torch.cuda.is_available() else
"cpu")
print("Using device:", device)
latent_dim = 100
batch_size = 128
epochs = 20 # increase later
image_size = 128
sample_dir = "samples"
os.makedirs(sample_dir, exist_ok=True)
# -----------------------------
# Transform
# -----------------------------
transform = transforms.Compose([
transforms.Resize(image_size),
transforms.CenterCrop(image_size),
transforms.ToTensor(),
transforms.Normalize([0.5]*3, [0.5]*3) # [-1,1]
])
# -----------------------------
# Custom Dataset for flat images
# -----------------------------
class CelebADataset(Dataset):
def __init__(self, root, transform=None):
# Include both .jpg and .JPG, search recursively
self.files = glob(os.path.join(root, "**", "*.jpg"),
recursive=True) + glob(os.path.join(root, "**", "*.JPG"),
recursive=True)
self.transform = transform
if len(self.files) == 0:
raise ValueError(f"No images found in {root} or
its subdirectories with .jpg or .JPG extensions. Check the
folder and extensions!")
def __len__(self):
return len(self.files)
def __getitem__(self, idx):
img = Image.open(self.files[idx]).convert("RGB")
if self.transform:
img = self.transform(img)
return img, 0 # dummy label
dataset = CelebADataset(root=data_path, transform=transform)
# Optional subset for fast debugging
subset = Subset(dataset, range(min(10000, len(dataset))))
dataloader = DataLoader(subset, batch_size=batch_size,
shuffle=True, num_workers=2)
print("Total images used:", len(subset))
# -----------------------------
# DCGAN Generator
# -----------------------------
class Generator(nn.Module):
def __init__(self, latent_dim):
super().__init__()
self.net = nn.Sequential(
nn.ConvTranspose2d(latent_dim, 512, 4, 1, 0,
bias=False),
nn.BatchNorm2d(512), nn.ReLU(True),
nn.ConvTranspose2d(512, 256, 4, 2, 1, bias=False),
nn.BatchNorm2d(256), nn.ReLU(True),
nn.ConvTranspose2d(256, 128, 4, 2, 1, bias=False),
nn.BatchNorm2d(128), nn.ReLU(True),
nn.ConvTranspose2d(128, 64, 4, 2, 1, bias=False),
nn.BatchNorm2d(64), nn.ReLU(True),
nn.ConvTranspose2d(64, 3, 4, 2, 1, bias=False),
nn.Tanh()
)
def forward(self, z):
return self.net(z)
# -----------------------------
# DCGAN Discriminator
# -----------------------------
class Discriminator(nn.Module):
def __init__(self):
super().__init__()
self.net = nn.Sequential(
nn.Conv2d(3, 64, 4, 2, 1, bias=False),
nn.LeakyReLU(0.2, inplace=True),
nn.Conv2d(64, 128, 4, 2, 1, bias=False),
nn.BatchNorm2d(128), nn.LeakyReLU(0.2,
inplace=True),
nn.Conv2d(128, 256, 4, 2, 1, bias=False),
nn.BatchNorm2d(256), nn.LeakyReLU(0.2,
inplace=True),
nn.Conv2d(256, 512, 4, 2, 1, bias=False),
nn.BatchNorm2d(512), nn.LeakyReLU(0.2,
inplace=True),
nn.Conv2d(512, 1, 4, 1, 0, bias=False),
nn.Sigmoid()
)
def forward(self, img):
# Flatten the output to a 1D tensor
return self.net(img).view(-1, 1).squeeze(1)
# -----------------------------
# Initialize models & optimizers
# -----------------------------
G = Generator(latent_dim).to(device)
D = Discriminator().to(device)
criterion = nn.BCELoss()
optimizerD = optim.Adam(D.parameters(), lr=0.0002, betas=(0.5,
0.999))
optimizerG = optim.Adam(G.parameters(), lr=0.0002, betas=(0.5,
0.999))
fixed_noise = torch.randn(64, latent_dim, 1, 1, device=device)
# -----------------------------
# Training Loop
# -----------------------------
for epoch in range(epochs):
for i, (imgs, _) in enumerate(dataloader):
real_imgs = imgs.to(device)
b_size = real_imgs.size(0)
real_labels = torch.ones(b_size, device=device)
fake_labels = torch.zeros(b_size, device=device)
# Train Discriminator
optimizerD.zero_grad()
output_real = D(real_imgs)
lossD_real = criterion(output_real, real_labels)
noise = torch.randn(b_size, latent_dim, 1, 1,
device=device)
fake_imgs = G(noise)
output_fake = D(fake_imgs.detach())
lossD_fake = criterion(output_fake, fake_labels)
lossD = lossD_real + lossD_fake
lossD.backward()
optimizerD.step()
# Train Generator
optimizerG.zero_grad()
output_fake = D(fake_imgs)
lossG = criterion(output_fake, real_labels)
lossG.backward()
optimizerG.step()
if i % 200 == 0:
print(f"Epoch [{epoch+1}/{epochs}] Step
[{i}/{len(dataloader)}] "
f"LossD: {lossD.item():.4f} LossG:
{lossG.item():.4f}")
# Save generated images
with torch.no_grad():
fake = G(fixed_noise).detach().cpu()
utils.save_image(fake,
f"{sample_dir}/epoch_{epoch+1}.png", normalize=True, nrow=8)
print(f" Saved sample images at
{sample_dir}/epoch_{epoch+1}.png")
Output: Epoch 1
Epoch 5
Epoch 10
Epoch 15
Epoch 20
Conclusion :
This experiment successfully implemented and trained a Deep
Convolutional GAN (DCGAN) on the CelebA dataset to generate human face
images from random noise. The generator and discriminator models were
trained adversarially, where the generator improved in producing realistic
samples while the discriminator learned to distinguish real from fake.
Although early outputs were blurry, progressive training gradually
improved the quality and structure of generated faces. The experiment
demonstrates the effectiveness of GANs in learning complex data
distributions, while also highlighting limitations such as potential mode
collapse and limited detail at higher resolutions. With longer training, use of
the full dataset, and advanced GAN variants, the quality and diversity of
generated images can be further enhanced.