A research-grade, from-scratch implementation of a fully-connected Variational AutoEncoder (VAE) trained on the MNIST dataset, including a custom LinearLayer, μ/logσ² heads, reparameterization trick, IDX dataloader, training pipeline, sampling module, and reconstruction visualization.
As with the AutoEncoder project:
No torchvision, no shortcuts every part is implemented manually for full mathematical transparency.
This project contains a full Variational AutoEncoder pipeline implemented entirely from scratch, covering:
-
Custom
LinearLayerwith Xavier initialization -
Encoder producing (μ, logσ²)
-
Reparameterization Trick:
z = μ + σ ⊙ εwhereε ∼ N(0, I) -
Two-layer decoder, generating reconstructed images
-
Raw MNIST IDX parsing (no torchvision)
-
Full ELBO loss implementation:
- Negative log-likelihood (reconstruction)
- KL-divergence term
-
Latent space sampling & visualization
scratch-variational-autoencoder/
├── LICENSE
├── README.md
├── vae_weights.pth
├── data/
├── docs/
│ ├── reconstructions.png
│ └── samples.png
├── notebooks/
│ ├── vae.ipynb
├── requirements.txt
└── src/
├── __init__.py
├── config.py
├── data_loader.py
├── layers.py
├── model.py
├── klloss.py
├── train.py
├── reconstruct_images.py
├── generate_new_image.py.py
Fully manual weight–bias module with Xavier uniform initialization.
LinearLayer(in_features → out_features)Outputs two heads:
784 → 256 → 8 → (μ, logσ²)
Both activations: Sigmoid (except heads which are linear).
z = μ + exp(0.5 * logσ²) * ε where ε ~ N(0, I)
Ensures gradients flow through random sampling.
8 → 256 → 784
Sigmoid activation for final output.
graph LR
A[Input 784-dim] --> B[Encoder]
B --> C[μ, logσ²]
C --> D[Reparameterization Trick]
D --> E[Decoder]
E --> F[Reconstructed Output]
git clone https://github.com/Himanshu7921/scratch-variational-autoencoder
cd scratch-variational-autoencoder
pip install -r requirements.txtPlace MNIST IDX files inside:
./data/
All commands assume:
scratch-variational-autoencoder/
python -m src.trainThis will:
- Load MNIST IDX files
- Apply normalization + flattening
- Train the VAE for 200 epochs
- Save model weights:
vae_weights.pth
python -m src.reconstruct_imagesOutputs a grid showing:
- MNIST original images
- Reconstructed images
Saved as:
./docs/regenerated_images.png
python -m src.generate_new_imageThis draws random z ∼ N(0, I) and generates new MNIST-like digits:
./docs/sample.jpeg
Epoch 1, Recon Loss: xx, KL: xx, Total: xx
Epoch 5, Recon Loss: xx, KL: xx, Total: xx
...
Epoch 200, Recon Loss: xx, KL: xx, Total: xx
All hyperparameters live in:
src/config.py
| Parameter | Value |
|---|---|
input_dim |
28*28 |
hidden_dim |
256 |
latent_dim |
8 |
batch_size |
128 |
lr |
0.001 |
epochs |
300 |
beta |
1.0 (KL weight) |
input_path |
./data |
- Kingma, D.P., Welling, M. Auto-Encoding Variational Bayes. ICLR 2014.
- Rezende, D.J., Stochastic Backpropagation and Approximate Inference. ICML 2014.
- “An Introduction to Variational Autoencoders”
- “Auto-Encoding Variational Bayes”
- Doersch, C. Tutorial on VAEs. arXiv:1606.05908
- Townsend, J. From Scratch VAE Derivations
- Cremer, C. Inference Suboptimality in VAEs. ICML 2018
If this implementation is used in academic or research work:
@software{Singh_VAE_2026,
author = {Himanshu Singh},
title = {Fully-Connected Variational AutoEncoder for MNIST: A Research Implementation},
year = {2026},
url = {https://github.com/Himanshu7921/scratch-variational-autoencoder}
}This project is licensed under the MIT License. You are free to use, modify, and distribute this code with attribution.


