পাঠ ৩৬ · ৪০-এর মধ্যে · মডিউল ৫

GAN — Generative Adversarial Network

GANs — adversarial generative modeling
৮ মিনিট পড়া মাঝারি · Intermediate PyTorch hands-on

এই পাঠে যা শিখবেন

  • Generator ও Discriminator-এর role ও architecture
  • Min-max objective — গাণিতিকভাবে
  • DCGAN — convolutional GAN-এর foundation
  • Mode collapse ও training instability-এর কারণ
  • WGAN, WGAN-GP, conditional GAN, StyleGAN
  • PyTorch-এ minimal MNIST GAN

১ · GAN-এর সরল ধারণা

Ian Goodfellow-এর ২০১৪-র revolutionary idea — দু'টি neural network লড়াই করুক:

  • Generator $G(z)$: random noise $z \sim \mathcal{N}(0, I)$ থেকে fake image তৈরি।
  • Discriminator $D(x)$: input image real (training data থেকে) নাকি fake (G-এর output) — binary classify।

$G$-এর লক্ষ্য — $D$-কে ধোঁকা দেওয়া। $D$-এর লক্ষ্য — কখনো ধোঁকা না খাওয়া। দু'জন একসাথে train করতে গিয়ে $G$ ক্রমশ realistic image তৈরিতে দক্ষ হয়।

ভাবুন একজন জাল-নোট নির্মাতা (G) ও একজন ব্যাংক পরীক্ষক (D)। নির্মাতা যত উন্নত নোট বানায়, পরীক্ষক তত শাণিত হন। উভয়েই উন্নত হয়ে যান — একপর্যায়ে নির্মাতার নোট আসল-প্রায়। GAN ঠিক এভাবেই কাজ করে — adversarial pressure দু'পক্ষকেই strong করে।

২ · Min-max objective

Goodfellow original loss:

$$\min_G \max_D \; \mathbb{E}_{x \sim p_{\text{data}}}[\log D(x)] + \mathbb{E}_{z \sim p(z)}[\log(1 - D(G(z)))]$$

Discriminator side: real-এ $D(x) \to 1$, fake-এ $D(G(z)) \to 0$ — দু'টোতেই objective বাড়ে।
Generator side: $D(G(z)) \to 1$ — অর্থাৎ fake-কে real ভাবাতে চায়।

Theorem: optimal $D$-এ generator-এর objective JS-divergence minimize — $p_G \to p_{\text{data}}$।

Non-saturating loss

Practice-এ original $\log(1 - D(G(z)))$ early training-এ gradient vanish — $D$ সহজে fake reject করে। তাই $G$ maximize $\log D(G(z))$ — gradient ভালো। PyTorch implementation-এ এটাই default।

৩ · DCGAN — convolutional GAN

Radford et al. (২০১৫)-এর Deep Convolutional GAN — image-এর জন্য first stable architecture। Key tricks:

  • Pooling এর বদলে strided convolution (D), transposed conv (G)।
  • Generator-এ BatchNorm — output layer ছাড়া।
  • Generator-এ ReLU, output Tanh।
  • Discriminator-এ LeakyReLU।
  • Adam optimizer, learning rate ০.০০০২, $\beta_1 = 0.5$।

DCGAN ৬৪×৬৪ image-এ stable train — face, bedroom, anime — সব generate। GAN era-র শুরু।

৪ · Mode collapse — GAN-এর সবচেয়ে কুখ্যাত সমস্যা

Generator হঠাৎ একটি বা কয়েকটি image-এর কাছাকাছি সব output produce করে — diversity হারায়। কারণ:

  • $G$ একটি "safe" mode খুঁজে পায় — যা $D$-কে easily fool।
  • Loss-এ explicit diversity penalty নেই।
  • $D$-এর local optima-এ stuck।

সমাধান: minibatch discrimination, unrolled GAN, WGAN, spectral normalization, feature matching loss।

৫ · Wasserstein GAN — better loss

Arjovsky et al. (২০১৭) — JS-divergence-এর বদলে Wasserstein distance। Critic (D-এর alternative) score output, sigmoid নয়।

$$L_{\text{WGAN}} = \mathbb{E}_{x \sim p_{\text{data}}}[D(x)] - \mathbb{E}_{z}[D(G(z))]$$

  • Lipschitz constraint: $D$-এর gradient norm ≤ ১। Original — weight clipping।
  • WGAN-GP (২০১৭): gradient penalty — interpolated point-এ $\|\nabla D\| \to 1$।
  • Result: training stable, mode collapse rare, loss meaningful (correlate with image quality)।
GAN — adversarial training Generator vs Discriminator z ~ N(0,I) Generator G noise → fake image fake x̃ G(z) real x data Discriminator D real or fake? D(·) ∈ [0, 1] G loss: maximize log D(G(z)) D loss: maximize log D(x) + log(1−D(G(z))) Nash equilibrium → p_G = p_data
GAN — Generator noise থেকে fake তৈরি, Discriminator real-fake বাছে। দু'জনের loss পরস্পরবিরোধী — equilibrium-এ G real distribution match।

৬ · PyTorch — minimal MNIST GAN

Python · GAN training step
import torch
import torch.nn as nn
import torch.optim as optim

class Generator(nn.Module):
    def __init__(self, z_dim=100, img_dim=784):
        super().__init__()
        self.net = nn.Sequential(
            nn.Linear(z_dim, 256), nn.LeakyReLU(0.2),
            nn.Linear(256, 512),  nn.LeakyReLU(0.2),
            nn.Linear(512, img_dim), nn.Tanh(),
        )
    def forward(self, z): return self.net(z)

class Discriminator(nn.Module):
    def __init__(self, img_dim=784):
        super().__init__()
        self.net = nn.Sequential(
            nn.Linear(img_dim, 512), nn.LeakyReLU(0.2),
            nn.Linear(512, 256),     nn.LeakyReLU(0.2),
            nn.Linear(256, 1),       nn.Sigmoid(),
        )
    def forward(self, x): return self.net(x)

G, D = Generator(), Discriminator()
opt_G = optim.Adam(G.parameters(), lr=2e-4, betas=(0.5, 0.999))
opt_D = optim.Adam(D.parameters(), lr=2e-4, betas=(0.5, 0.999))
bce = nn.BCELoss()

# One training step
real = torch.rand(64, 784) * 2 - 1   # MNIST flattened, in [-1, 1]
B = real.size(0)
z = torch.randn(B, 100)
fake = G(z)

# D step
opt_D.zero_grad()
d_real = D(real)
d_fake = D(fake.detach())
loss_D = bce(d_real, torch.ones_like(d_real)) + \
         bce(d_fake, torch.zeros_like(d_fake))
loss_D.backward()
opt_D.step()

# G step
opt_G.zero_grad()
d_fake = D(fake)
loss_G = bce(d_fake, torch.ones_like(d_fake))   # non-saturating
loss_G.backward()
opt_G.step()
print(f"loss_D={loss_D.item():.3f}  loss_G={loss_G.item():.3f}")

    

৭ · Conditional GAN (cGAN)

Mirza-Osindero (২০১৪) — GAN-কে condition-aware করো। Class label $y$ both $G$ ও $D$-তে input। তখন target class-এ specific image generate সম্ভব ("৭ লেখো")।

Pix2Pix, CycleGAN — image-to-image translation। Edge-to-photo, day-to-night, horse-to-zebra।

৮ · StyleGAN — photorealistic faces

Karras et al. (NVIDIA, ২০১৮-২০২০) — photorealistic face generation-এর golden standard। Innovations:

  • Mapping network: $z$-কে intermediate $w$ space-এ project — disentangle।
  • AdaIN (Adaptive Instance Norm): per-layer style injection।
  • Progressive growing (StyleGAN1) → modulated conv (StyleGAN2)।
  • Style mixing: different layer-এ different latent — coarse vs fine attribute control।

thispersondoesnotexist.com — StyleGAN2-এর demo। ২০১৯-এ AI-generated face বনাম real-এ মানুষ পার্থক্য করতে পারত না।

৯ · GAN বনাম VAE বনাম Diffusion

  • VAE: stable training, smooth latent, blurry image।
  • GAN: sharp image, hard to train, no likelihood, mode collapse risk।
  • Diffusion: stable, high quality, slow inference, currently dominant।

২০২২-এ Stable Diffusion আসার পর GAN-এর momentum কমেছে — কিন্তু StyleGAN-style face generation, GAN inversion (image edit), super-resolution (ESRGAN) এ এখনো relevant।

GAN training art — অনেক practitioner হাল ছাড়ে instability-তে। ২০১৭ পরবর্তী tricks (Spectral norm, R1 penalty, EMA) ছাড়া modern result অসম্ভব। L37-এ Diffusion দেখব — যা GAN-কে ছাপিয়ে গেছে।

ভাবনার প্রশ্ন

প্রতিটি প্রশ্ন নিজে কিছুক্ষণ ভাবুন — তারপর "→ উত্তর" চাপুন।

প্র ০১ Mode collapse — GAN-এর নাটকীয় failure mode। গাণিতিকভাবে কেন ঘটে? Fix-এর মূল idea কী?

Mode collapse — GAN research-এর central pain point। Causes multifaceted।

Mathematical perspective:

  • $G$ optimal — point distribution-এ collapse চাইতে পারে।
  • $D$ fixed হলে $G$ argmax $\log D(G(z))$ — এক mode যথেষ্ট।
  • Diversity-এর কোনো explicit incentive নেই objective-এ।

Game dynamics:

  • $G$ একটি mode পায় যা D fool করে।
  • D সেই mode reject শিখে।
  • $G$ আরেকটি mode-এ jump।
  • Cyclical — never coverage।

Loss landscape:

  • JS-divergence — disjoint distribution-এ saturate।
  • Gradient signal poor।
  • $G$ gradient escape difficult।

Fixes — by category:

(১) Loss redesign:

  • WGAN — Wasserstein metric, smooth gradient সর্বত্র।
  • Hinge loss — robust।
  • Least squares GAN।

(২) Architecture:

  • Spectral normalization — Lipschitz $D$।
  • Self-attention — global pattern।
  • Progressive growing।

(৩) Training tricks:

  • Minibatch discrimination — D batch-এ diversity check।
  • Feature matching — generated features match real distribution।
  • Unrolled GAN — D-এর future steps predict।
  • Two time-scale update rule (TTUR)।

(৪) Optimization:

  • EMA — running average of G weights।
  • R1, R2 regularization।
  • Lower learning rate।

Empirical observation:

  • StyleGAN2 + mode-coverage techniques — significant improvement।
  • Diversity metric (LPIPS) তবু fragile।
  • Class-conditional GAN — partial fix।

Current standing:

  • Diffusion — mode coverage natural।
  • GAN-এ ongoing technique stack।
  • StyleGAN3 — texture-stable, mode-stable।
  • Diffusion taking over generation।

মূল উপলব্ধি: Mode collapse — GAN objective-এ implicit। Diversity না engineered, automatic নয়। Wasserstein + tricks-এর stack lessen। Diffusion fundamentally different — mode coverage natural। GAN art + science — production-এ caution।

প্র ০২ WGAN-এর Lipschitz constraint কী, কেন গুরুত্বপূর্ণ? Weight clipping vs gradient penalty — কোনটা ভালো এবং কেন?

WGAN — GAN history-এর landmark। Mathematical foundation শক্ত।

Why Lipschitz:

  • Wasserstein distance dual form — $\sup_{f \in \text{Lip-1}} \mathbb{E}[f(x)] - \mathbb{E}[f(y)]$।
  • $D$ ($f$) — Lipschitz-1 constraint।
  • Gradient bounded by ১ everywhere।
  • Smooth loss landscape।

Original WGAN — weight clipping:

  • $D$-এর প্রতিটি weight $[-c, c]$-এ clip।
  • Crude approximation Lipschitz-এর।
  • $c = 0.01$ typical।

Problems:

  • Weight distribution bimodal — most at $\pm c$।
  • Capacity loss — D underutilized।
  • Gradient explode/vanish — depending $c$।
  • Hyperparameter sensitive।

WGAN-GP — gradient penalty (২০১৭):

  • Real-fake interpolated point $\hat{x}$।
  • $D$-এর gradient $\hat{x}$-এ — penalty $(\|\nabla\| - 1)^2$।
  • Lipschitz-1 push exactly।

Implementation:

def gradient_penalty(D, real, fake):
    eps = torch.rand(real.size(0), 1, 1, 1)
    interp = eps * real + (1-eps) * fake
    interp.requires_grad_(True)
    d_interp = D(interp)
    grad = torch.autograd.grad(
        d_interp.sum(), interp, create_graph=True)[0]
    grad = grad.view(grad.size(0), -1)
    return ((grad.norm(2, dim=1) - 1) ** 2).mean()

Comparison:

Weight clipping:

  • Simple, fast।
  • Capacity loss।
  • Hyperparameter brittle।

Gradient penalty:

  • More principled।
  • Computationally costly (extra grad)।
  • BatchNorm-এর সাথে interaction issue (use LayerNorm/InstanceNorm in D)।

Spectral normalization (২০১৮):

  • Each layer-এর spectral norm clip।
  • Lipschitz layer-wise।
  • Computationally efficient।
  • SAGAN, BigGAN-এ ব্যবহৃত।

Practical recommendation:

  • SN-GAN — modern default।
  • WGAN-GP — research standard।
  • Original WGAN — historical।

Production:

  • StyleGAN — R1 penalty (gradient on real only)।
  • Lower compute, similar effect।
  • Spectral norm + R1 — strong combination।

মূল উপলব্ধি: Lipschitz constraint Wasserstein-এর mathematical requirement। Weight clipping ad-hoc, gradient penalty principled, spectral norm efficient। R1 modern production। GAN training Lipschitz enforcement — central engineering challenge।

প্র ০৩ StyleGAN-এর "style mixing" — coarse-medium-fine layer-এ different latent। কেন এই disentanglement কাজ করে?

StyleGAN-এর architecture insight — image generation-এর landmark contribution।

Resolution hierarchy:

  • Coarse layers (4×4 → 8×8) — pose, face shape, hair style।
  • Middle layers (16×16 → 32×32) — facial features, eyes, nose।
  • Fine layers (64×64+) — color, texture, lighting।
  • Spatial scale → semantic scale natural correspondence।

Mapping network:

  • $z \to w$ — 8-layer MLP।
  • $z$ Gaussian, $w$ disentangled।
  • $\mathcal{W}$-space "linear separable"।

AdaIN injection:

  • $w$ — affine projection per layer।
  • Layer activation normalize, scale-shift।
  • Per-layer style control।

Style mixing trick:

  • Two latent $w_1, w_2$।
  • Layer 1-3 use $w_1$, layer 4-end use $w_2$।
  • $w_1$ identity, $w_2$ texture — mixed image।

Why it works:

  • Mapping network — disentanglement encourage।
  • Style mixing regularization — independent layer।
  • Mixing during training — robustness।
  • $w$-space-এ semantic direction discoverable।

Disentanglement test:

  • "Smile" direction — $w$-এ identify।
  • Add direction → smile add।
  • Other attribute unchanged।
  • Linear interpretability।

Editing application:

  • GAN inversion — image → $w$।
  • $w$-এ edit।
  • Decode → edited image।
  • FaceShop, deepfake editing।

StyleGAN2 improvements:

  • Modulated conv — AdaIN replacement।
  • Path length regularization।
  • Lazy regularization।
  • Photorealistic ১০২৪×১০২৪।

StyleGAN3:

  • Texture sticking fix।
  • Equivariance to translation/rotation।
  • Smooth interpolation।

Compared to alternatives:

  • VAE — less disentangled।
  • BigGAN — class-conditioned, less interpretable।
  • Diffusion — different mechanism, prompt-based control।

Bangla face editing:

  • StyleGAN fine-tune — Bangla face dataset।
  • Cultural attribute (age, attire) editing।
  • Limited dataset — challenge।
  • Transfer learning critical।

মূল উপলব্ধি: StyleGAN — architectural innovation enable disentanglement। Spatial-semantic correspondence emergent। $w$-space linear control। Modern face generation gold standard। Editing applications powerful।

প্র ০৪ Bangladesh-এ একটি startup synthetic Bangla handwriting generate করতে চাচ্ছে — train data augmentation-এর জন্য। GAN, VAE, Diffusion — কোনটি বাছবেন? Trade-offs।

Practical Bangladesh use case — handwritten Bangla character generation। Data augmentation-এর crucial application।

Use case:

  • OCR system trained on synthetic + real।
  • Bangla handwritten data scarce।
  • Style variation needed।
  • Production inference fast।

Option 1 — VAE:

Pros:

  • Stable training।
  • Latent interpolation smooth।
  • Probabilistic foundation।

Cons:

  • Blurry — handwriting sharpness lost।
  • OCR training-এ poor signal।
  • Unsuitable।

Option 2 — GAN (DCGAN/StyleGAN):

Pros:

  • Sharp output — handwriting essential।
  • Style mixing — diverse strokes।
  • Fast inference।
  • Established for character generation (HWGAN)।

Cons:

  • Training instability।
  • Mode collapse — character variety risk।
  • Hyperparameter tuning art।

Option 3 — Diffusion:

Pros:

  • Best quality।
  • Mode coverage natural।
  • Prompt-based control (class-conditional)।

Cons:

  • Slow inference (diffusion step)।
  • Heavier compute training।
  • Recent — fewer Bangla-specific resource।

Recommendation — phased approach:

Phase 1 — Conditional GAN:

  • Class label condition — 'ক', 'খ', etc।
  • BanglaLekha-Isolated dataset (Hossain et al.)।
  • ~৮০ class, ~১৫০K image।
  • DCGAN baseline।

Phase 2 — StyleGAN-style:

  • Style mixing — different writer style।
  • Coarse style → letter shape, fine → stroke।
  • Diverse handwriting।

Phase 3 — Diffusion (if budget allows):

  • Best quality production।
  • Latent diffusion in compressed space।
  • OCR training boost।

Implementation:

# Conditional DCGAN for Bangla characters
class CondGenerator(nn.Module):
    def __init__(self, z_dim=100, n_class=80, img_dim=784):
        super().__init__()
        self.label_emb = nn.Embedding(n_class, n_class)
        self.net = nn.Sequential(
            nn.Linear(z_dim + n_class, 256),
            nn.LeakyReLU(0.2),
            nn.Linear(256, 512), nn.LeakyReLU(0.2),
            nn.Linear(512, img_dim), nn.Tanh())
    def forward(self, z, y):
        c = self.label_emb(y)
        return self.net(torch.cat([z, c], dim=1))

Evaluation:

  • FID score (vs real handwriting)।
  • OCR accuracy boost — primary metric।
  • Human evaluation — readability।
  • Diversity metric — style variation।

Production deployment:

  • One-time bulk generation।
  • Variation per session।
  • Cloud GPU — minimal cost।
  • Augmentation pipeline integration।

Bangla handwriting challenges:

  • Conjunct character ("যুক্তাক্ষর") complexity।
  • Vowel mark positioning ("কার")।
  • Cursive variation।
  • Modifier consistency।

Hybrid approach:

  • Real data + synthetic 50-50 mix।
  • OCR train на combined।
  • Test on real held-out।
  • Improvement validate।

Bangladesh practical:

  • OCR critical — government, banking, education।
  • Bangla data scarcity bottleneck।
  • Synthetic augmentation high value।
  • GAN-based feasible practical solution।

মূল উপলব্ধি: Synthetic Bangla handwriting — GAN best practical। StyleGAN style variation। Diffusion quality but expensive। Phased approach: GAN → StyleGAN → Diffusion। OCR augmentation impact significant। Bangladesh data-scarcity solution generation-based।

অনুশীলন

  1. Loss compute: $D(x) = 0.9$ (real) ও $D(G(z)) = 0.3$ (fake) — D-এর BCE loss?
    • $-\log(0.9) \approx 0.105$ (real-এর contribution)।
    • $-\log(1 - 0.3) = -\log(0.7) \approx 0.357$ (fake-এর)।
    • Total $\approx 0.462$।
    • $D$-এর target — কম, $G$-এর target — বেশি।
  2. Code: ১০ epoch-এর জন্য full training loop লিখুন (optimizer step, sample save)।
    for epoch in range(10):
        for real, _ in loader:
            real = real.view(real.size(0), -1)
            B = real.size(0)
            z = torch.randn(B, 100)
            fake = G(z)
            # D step
            opt_D.zero_grad()
            loss_D = bce(D(real), torch.ones(B,1)) + \
                     bce(D(fake.detach()), torch.zeros(B,1))
            loss_D.backward(); opt_D.step()
            # G step
            opt_G.zero_grad()
            loss_G = bce(D(fake), torch.ones(B,1))
            loss_G.backward(); opt_G.step()
        # save samples
        torchvision.utils.save_image(
            G(torch.randn(16,100)).view(-1,1,28,28),
            f'epoch_{epoch}.png', normalize=True)
  3. চিন্তা: GAN-এ "balance" কেন critical — D যদি পুরোপুরি জিতে যায় বা পুরোপুরি হেরে যায়, কী হবে?

    D জিতে গেলে: $D(G(z)) \approx 0$ — log gradient $\to 0$ — G-এর update signal vanish। G stuck।

    D হেরে গেলে: $D(x) \approx D(G(z)) \approx 0.5$ — D random — G-কে কোন direction-এ improve guide-ই দিতে পারে না।

    সমাধান: learning rate balance, multiple D step per G step (WGAN-এ ৫:১), spectral norm — D-এর capacity limit।

আরও পড়ুন · ABCL TECH-এ আপনার পরবর্তী পদক্ষেপ

কোড রানার কাজ না করলে? ব্রাউজারে কাজ না করলে Google Colab ব্যবহার করুন — Google-এর ফ্রি অনলাইন Python পরিবেশ, শুধু Gmail অ্যাকাউন্ট লাগে।
পূর্ববর্তী পাঠ
পাঠ ৩৫ · Autoencoder ও VAE