This project implements a realistic one-week PyTorch pipeline for 64x64 image generation:
- DCGAN as the main GAN model.
- Improved residual convolutional VAE as a baseline.
- Optional compact DDPM as a compute-heavier diffusion experiment.
- FID, sample grids, diversity checks, and latent interpolation artifacts for the report.
The default settings target a consumer GPU and prioritize finishing a complete, reproducible experiment. DDPM support is included as an optional extension, but it is much slower to train and sample than the GAN/VAE models.
Use Python 3.11+.
cd generative-models
python -m venv .venv
source .venv/bin/activate
pip install -r requirements.txtThe configs in configs/ already point to the datasets present in this workspace:
data/raw/cats
data/raw/catdog
If you move the datasets, update dataset_root in the YAML files. The loader recursively finds .jpg, .jpeg, .png, and .webp images, converts them to RGB, center-crops to a square, resizes to 64x64, optionally flips during training, and normalizes tensors to [-1, 1].
Train the cat DCGAN:
python -m src.train_dcgan --config configs/dcgan_cat64_baseline.yamlThis configuration uses a DCGAN generator/discriminator trained with LSGAN loss, conservative discriminator learning rate, gradient clipping, and finite-loss guards. It saves under outputs/checkpoints/dcgan_cat64_baseline/.
Run the DCGAN hyperparameter sweep:
PYTHON_BIN=./venv/bin/python bash scripts/run_dcgan_experiments.sh --device cudaFor a quick comparison run, override epochs:
PYTHON_BIN=./venv/bin/python bash scripts/run_dcgan_experiments.sh --epochs 30 --device cudaTrain the improved residual VAE baseline:
python -m src.train_vae --config configs/vae_cat64_baseline.yamlThis VAE is not compatible with older VAE checkpoints. Start it from scratch; it saves under outputs/checkpoints/vae_cat64_baseline/.
Run the VAE hyperparameter sweep:
PYTHON_BIN=./venv/bin/python bash scripts/run_vae_experiments.sh --device cudaFor a quick comparison run, override epochs:
PYTHON_BIN=./venv/bin/python bash scripts/run_vae_experiments.sh --epochs 30 --device cudaTrain the optional compact DDPM:
python -m src.train_ddpm --config configs/ddpm_cat64_baseline.yamlCheckpoints are saved under outputs/checkpoints/<run_name>/, and sample grids under outputs/samples/<run_name>/.
Resume DCGAN training from a training checkpoint:
python -m src.train_dcgan --config configs/dcgan_cat64_baseline.yaml --resume outputs/checkpoints/dcgan_cat64_baseline/training_latest.ptResume VAE training:
python -m src.train_vae --config configs/vae_cat64_baseline.yaml --resume outputs/checkpoints/vae_cat64_baseline/training_latest.ptDCGAN:
python -m src.generate \
--model dcgan \
--checkpoint outputs/checkpoints/dcgan_cat64_baseline/generator_latest.pt \
--config configs/dcgan_cat64_baseline.yaml \
--num-images 100 \
--out-dir outputs/generated/dcgan_cat64_baselineVAE:
python -m src.generate \
--model vae \
--checkpoint outputs/checkpoints/vae_cat64_baseline/model_latest.pt \
--config configs/vae_cat64_baseline.yaml \
--num-images 100 \
--out-dir outputs/generated/vae_cat64_baselineDDPM:
python -m src.generate \
--model ddpm \
--checkpoint outputs/checkpoints/ddpm_cat64_baseline/model_latest.pt \
--config configs/ddpm_cat64_baseline.yaml \
--num-images 16 \
--batch-size 8 \
--out-dir outputs/generated/ddpm_cat64_baselineEach command saves individual PNG files and a grid image.
For DCGAN latent-noise interpolation:
python -m src.interpolate \
--model dcgan \
--checkpoint outputs/checkpoints/dcgan_cat64_baseline/generator_latest.pt \
--config configs/dcgan_cat64_baseline.yamlFor VAE latent interpolation:
python -m src.interpolate \
--model vae \
--checkpoint outputs/checkpoints/vae_cat64_baseline/model_latest.pt \
--config configs/vae_cat64_baseline.yamlFor DDPM initial-noise interpolation:
python -m src.interpolate \
--model ddpm \
--checkpoint outputs/checkpoints/ddpm_cat64_baseline/model_latest.pt \
--config configs/ddpm_cat64_baseline.yamlThis samples two latent noise tensors, linearly interpolates between them with 10 evenly spaced points, and saves:
outputs/interpolations/<run_name>/interpolation_grid.png
outputs/interpolations/<run_name>/latent_vectors.npz
The .npz file contains z_a, z_b, all 10 interpolated latent/noise matrices, and interpolation coefficients. For DDPM, the interpolated matrices are image-shaped initial noise tensors and sampling uses a deterministic DDIM-style reverse process. In the report, smooth transitions suggest the model learned a meaningful generation space; abrupt jumps or near-identical images can indicate poor coverage or mode collapse.
Compute FID for DCGAN:
python -m src.evaluate_fid \
--model dcgan \
--checkpoint outputs/checkpoints/dcgan_cat64_baseline/generator_latest.pt \
--config configs/dcgan_cat64_baseline.yaml \
--num-images 5000Compute FID for VAE:
python -m src.evaluate_fid \
--model vae \
--checkpoint outputs/checkpoints/vae_cat64_baseline/model_latest.pt \
--config configs/vae_cat64_baseline.yaml \
--num-images 5000Compute FID for DDPM. This is slow, so start with a small number:
python -m src.evaluate_fid \
--model ddpm \
--checkpoint outputs/checkpoints/ddpm_cat64_baseline/model_latest.pt \
--config configs/ddpm_cat64_baseline.yaml \
--num-images 500 \
--batch-size 8For quick smoke tests, use --num-images 1000 or smaller. Results are written to outputs/fid/<run_name>_fid.json. The script uses clean-fid first and falls back to pytorch-fid if needed.
Run a practical diversity check:
python -m src.diversity \
--model dcgan \
--checkpoint outputs/checkpoints/dcgan_cat64_baseline/generator_latest.pt \
--config configs/dcgan_cat64_baseline.yaml \
--num-images 256For VAE:
python -m src.diversity \
--model vae \
--checkpoint outputs/checkpoints/vae_cat64_baseline/model_latest.pt \
--config configs/vae_cat64_baseline.yaml \
--num-images 256For DDPM:
python -m src.diversity \
--model ddpm \
--checkpoint outputs/checkpoints/ddpm_cat64_baseline/model_latest.pt \
--config configs/ddpm_cat64_baseline.yaml \
--num-images 64 \
--batch-size 8This saves a generated sample grid and JSON metrics such as average pairwise pixel distance. These numbers are not a replacement for visual inspection or FID, but they are useful for discussing mode collapse.
If many samples look identical:
- Lower the discriminator learning rate or train it less aggressively.
- Use real-label smoothing, e.g.
real_label_smoothing: 0.9. - Add small instance noise, e.g.
instance_noise_std: 0.05. - Try
spectral_norm: true. - Reduce the learning rate from
0.0002to0.0001. - Inspect whether the dataset preprocessing is too narrow or too repetitive.
- Train
dcgan_cat64_baselinewithconfigs/dcgan_cat64_baseline.yaml. - Save qualitative grids every 5 epochs and identify the best-looking checkpoint.
- Train
vae_cat64_baselineas the improved residual VAE baseline. - Optionally train DDPM variants. DDPM is slower because each generated sample requires hundreds of denoising steps.
- Compute FID for DCGAN, VAE, and DDPM using the same number of generated images when runtime allows.
- Run
src.interpolatefor DCGAN, VAE, and DDPM. - Run diversity checks for DCGAN, VAE, and DDPM.
Use both quantitative and qualitative evidence. FID compares generated and real-image feature distributions; lower is usually better, but it can disagree with human judgment. VAE samples often have smoother, blurrier textures because the reconstruction objective averages plausible outputs. DCGAN samples may be sharper but can suffer from training instability or mode collapse.
For mixed cats+dogs training, an unconditional GAN has no label signal. If you run that extension, copy the DCGAN config and change only run_name and dataset_root. Class-distinct generation usually requires conditioning, labels, or a stronger model, so treat this part as exploratory rather than the central result.