A Deep Convolutional Generative Adversarial Network (DCGAN) built with PyTorch that generates realistic human faces after training on the CelebA dataset. The generator learns to transform 100-dimensional random noise vectors into 32×32 RGB face images, while the discriminator learns to distinguish real faces from generated ones. Trained for 25 epochs with label smoothing and Adam optimizer.
Training Data (CelebA):
Generated Faces:
- DCGAN Architecture — Discriminator uses strided convolutions (no pooling), generator uses transposed convolutions for upsampling, following the DCGAN paper guidelines
- Batch Normalization — Applied to all layers except discriminator's first conv and generator's last deconv, stabilizing training
- Label Smoothing — Real labels set to 0.9 instead of 1.0 to prevent the discriminator from becoming overconfident
- Custom Weight Initialization — Convolutional and linear layers initialized from normal distribution (mean=0, std=0.02) per DCGAN paper recommendations
- Helper Functions — Reusable
conv()anddeconv()builder functions that encapsulate Conv2d/ConvTranspose2d + BatchNorm + activation into clean blocks
Discriminator (32×32×3 → real/fake):
Input (3, 32, 32)
→ Conv2d(3→32, 4×4, stride=2) → LeakyReLU # No BatchNorm
→ Conv2d(32→64, 4×4, stride=2) → BatchNorm → LeakyReLU
→ Conv2d(64→128, 4×4, stride=2) → BatchNorm → LeakyReLU
→ Flatten → Linear(128*4*4 → 1)
Generator (z=100 → 32×32×3):
Input z (100,)
→ Linear(100 → 128*4*4) → Reshape to (128, 4, 4)
→ ConvTranspose2d(128→64, 4×4, stride=2) → BatchNorm → ReLU
→ ConvTranspose2d(64→32, 4×4, stride=2) → BatchNorm → ReLU
→ ConvTranspose2d(32→3, 4×4, stride=2) → Tanh # Output [-1, 1]
- Loss Function —
BCEWithLogitsLoss(binary cross-entropy with built-in sigmoid) for both discriminator and generator losses - Training Dynamics — Discriminator loss ≈ 1.1, generator loss ≈ 1.0–1.4 across epochs, indicating balanced adversarial training (neither network dominates)
| Parameter | Value |
|---|---|
| Image Size | 32×32×3 |
| Batch Size | 128 |
| Latent Vector (z_size) | 100 |
| Conv Depth (d & g) | 32 |
| Learning Rate | 0.0002 |
| Adam β₁ | 0.5 |
| Adam β₂ | 0.999 |
| Epochs | 25 |
| Label Smoothing | 0.9 (real labels) |
| Component | Technology |
|---|---|
| Framework | PyTorch |
| Dataset | CelebA (cropped + resized to 32×32) |
| Architecture | DCGAN |
| Optimizer | Adam (separate for D and G) |
| Loss | BCEWithLogitsLoss |
| GPU | CUDA (recommended) |
| Environment | Jupyter Notebook |
git clone https://github.com/jashjain21/Face-Generation.git
cd Face-Generation
pip install torch torchvision matplotlib numpy
jupyter notebook dlnd_face_generation.ipynbNote: The CelebA dataset needs to be downloaded separately and placed in processed_celeba_small/. Training is recommended on GPU.
- Generative Adversarial Networks — Implementing the full GAN training loop: train discriminator on real + fake, train generator to fool discriminator, alternating each batch
- DCGAN Best Practices — Strided convolutions instead of pooling, batch normalization, LeakyReLU in discriminator, ReLU in generator, Tanh output activation — all per the original paper
- Training Stability Techniques — Label smoothing, separate Adam optimizers with β₁=0.5, and proper weight initialization to prevent mode collapse
- PyTorch Proficiency — Custom
nn.Moduleclasses,DataLoaderwith transforms, GPU training, and loss visualization
- 32×32 Resolution — Generated faces are low resolution; scaling to 128×128 or 256×256 would require a deeper network (more conv layers) and significantly more training time
- No Progressive Growing — Implementing Progressive GAN (starting at 4×4 and growing to higher resolutions) would produce sharper results
- No FID/IS Metrics — Quality is evaluated visually; adding Fréchet Inception Distance or Inception Score would provide quantitative evaluation
- Mode Collapse Risk — No explicit mechanism to prevent mode collapse beyond label smoothing; techniques like minibatch discrimination or spectral normalization could help
- No Conditional Generation — The GAN generates random faces; adding class conditioning (e.g., on attributes like gender, hair color) would enable controlled generation

