Skip to content

Latest commit

ย 

History

17 Commits

Folders and files

NameName
Last commit message
Last commit date
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 

Repository files navigation

๐ŸŽฒ This Number Does Not Exist

CI License: MIT Python 3.8+ scikit-learn Live Demo

Generate realistic handwritten digits using classical : Kernel Density Estimation + PCA + Rejection Sampling. A lightweight alternative to GANs that's 40ร— faster to train and 10ร— smaller.

๐ŸŽฎ Live Demo | ๐Ÿ“– Documentation | ๐Ÿค Contributing


โœจ Features

Core Capabilities

  • ๐ŸŽฏ Conditional Generation: Choose exactly which digit to generate (0-9).
  • ๐ŸŽจ High Quality: Rejection sampling + image cleaning for artifact-free results.
  • ๐Ÿ’พ Lightweight: Models are 5-15 MB (10-100ร— smaller than GANs).
  • ๐Ÿ”ฌ Classical ML: Uses PCA + KDE instead of neural networks.
  • โš™๏ธ Auto-Tuned: Bandwidth optimization via cross-validation.
  • ๐ŸŒ Web Interface: Real-time generation in your browser.

Technical Highlights

  • PCA: Dimensionality reduction (784D โ†’ 50D) retaining ~82% variance.
  • KDE: Kernel Density Estimation with Gaussian kernel.
  • Rejection Sampling: Three quality levels (Light/Medium/Strict).
  • Image Cleaning: Bilateral denoising + morphological operations.
  • Two Architectures: Global (single model) vs Conditional (one per digit).

๐ŸŽฌ Demo

Interactive Generation

Samples Mosaic 100 unique digits generated with our conditional model

Quality Improvement

Comparison Before and after: image cleaning


๐Ÿš€ Quick Start

Prerequisites

  • Python 3.8+
  • pip
  • 2GB RAM minimum

Installation

# Clone the repository
git clone https://github.com/sofianebeloucif/ThisNumberDoesNotExist.git
cd ThisNumberDoesNotExist

# Create virtual environment (recommended)
python -m venv venv
source venv/bin/activate  # Linux/Mac
# or
venv\Scripts\activate     # Windows

# Install dependencies
pip install -r requirements.txt

Training Models

# Launch Jupyter
jupyter notebook notebooks/train_and_compare.ipynb

The notebook will:

  1. โœ… Auto-optimize bandwidth via 5-fold cross-validation
  2. โœ… Train both Global and Conditional generators
  3. โœ… Compare performance (speed, size, quality)
  4. โœ… Generate visualizations
  5. โœ… Save models to models/

โฑ๏ธ Training time: ~3-5 minutes on CPU

Running Web App (Local)

cd app
python app.py

Open: http://localhost:5000


๐ŸŽฎ Usage

Basic Controls

  • Mode Selection: Global (random) or Conditional (choose digit)
  • Digit Picker: Select 0-9 (conditional mode only)
  • Rejection Sampling: Toggle quality filtering
  • Image Cleaning: Remove artifacts (light/medium/aggressive)

Python API

from src.generator import GlobalGenerator, ConditionalGenerator

# --- Global Generator ---
global_gen = GlobalGenerator.load('models/global_generator.pkl')

# Generate 10 random digits
images = global_gen.generate(
    n_samples=10,
    use_rejection=True,
    percentile=25,
    clean_images=True,
    cleaning_method='medium'
)

# --- Conditional Generator ---
cond_gen = ConditionalGenerator.load('models/conditional_generator.pkl')

# Generate 10 sevens
sevens = cond_gen.generate(
    digit=7,
    n_samples=10,
    use_rejection=True,
    percentile=25,
    clean_images=True,
    cleaning_method='medium'
)

# Generate all digits (10 of each)
all_digits = cond_gen.generate_all(n_samples_per_digit=10)

๐Ÿ› ๏ธ Architecture

Pipeline Overview

MNIST (60k images, 28ร—28)
    โ†“
[ PCA: 784D โ†’ 50D ]  (~82% variance retained)
    โ†“
[ KDE: Density Estimation ]  (Gaussian kernel, optimized bandwidth)
    โ†“
[ Sampling + Rejection ]  (Filter by log-likelihood)
    โ†“
[ PCA Inverse: 50D โ†’ 784D ]
    โ†“
[ Image Cleaning ]  (Denoise + threshold + morphology)
    โ†“
Generated Image (28ร—28)

Two Architectures

Architecture Description Model Size Training Time Use Case
๐ŸŒ Global Single KDE for all digits ~5 MB ~3s Random generation
๐ŸŽฏ Conditional 10 KDE (one per digit) ~15 MB ~10s Targeted generation


๐ŸŽฏ Rejection Sampling

Improve generation quality by filtering samples based on log-likelihood.

Level Percentile Acceptance Rate Speed
๐ŸŸข Light 10% ~85% Fast โšก
๐ŸŸก Medium 25% ~65% Normal
๐Ÿ”ด Strict 50% ~45% Slower

Formula: $$ \text{Accept if: } \log p(x) \geq \text{threshold}_{\text{percentile}} $$

Where $p(x)$ is the KDE-estimated probability density.


๐Ÿงน Image Cleaning

Post-process generated images to eliminate artifacts.

Cleaning Methods

Method Pipeline Effect Speed
๐ŸŸข Light Threshold (0.2) Minimal cleanup Fast
๐ŸŸก Medium Threshold (0.25) + Small components removal Balanced Normal
๐Ÿ”ด Aggressive Bilateral denoise + Threshold (0.3) + Morphology Maximum quality but risk of degradation Slower

Recommended: Medium for general use, Aggressive if many artifacts persist.


๐Ÿ“š Documentation

Algorithm Details

Kernel Density Estimation (KDE) $$ \hat{f}(x) = \frac{1}{nh} \sum_{i=1}^{n} K\left(\frac{x - x_i}{h}\right) $$

Where:

  • $K$ is the Gaussian kernel
  • $h$ is the bandwidth (auto-optimized via grid search)
  • $n$ is the number of training samples

Cross-Validation for Bandwidth

bandwidths = np.linspace(0.5, 2.5, 10)
grid = GridSearchCV(KernelDensity(), {'bandwidth': bandwidths}, cv=5)
grid.fit(data)
optimal_bandwidth = grid.best_params_['bandwidth']

Biome Mapping Analogy

Similar to terrain generation, our model maps the latent space into "digit biomes":

if log_density < threshold_10% โ†’ Reject
elif log_density < threshold_25% โ†’ Accept (Light)
elif log_density < threshold_50% โ†’ Accept (Medium)
else โ†’ Accept (Strict)

See Technical Documentation for deep dive.


๐Ÿค Contributing

Contributions welcome! See CONTRIBUTING.md.

Ideas for Enhancement

  • Fashion-MNIST support
  • CIFAR-10 (color images)
  • FID/IS metrics
  • Docker container
  • Latent space interpolation
  • Style transfer
  • Multi-modal generation (digits + letters)
  • Mobile app (iOS/Android)

๐Ÿ“ License

This project is licensed under the MIT License - see LICENSE for details.


๐Ÿ‘ค Author

Sofiane Beloucif


๐Ÿ™ Acknowledgments


๐Ÿ“– Citation

If you use this project in your research, please cite:

@misc{thisnumberdoesnotexist2024,
  author = {Beloucif, Sofiane},
  title = {This Number Does Not Exist: MNIST Generation with PCA + KDE},
  year = {2024},
  publisher = {GitHub},
  url = {https://github.com/sofianebeloucif/ThisNumberDoesNotExist}
}

โญ Star this repo if you find it useful!

GitHub stars

Made with โค๏ธ and lots of โ˜•

๐ŸŽฎ Try the Demo โ€ข ๐Ÿ“– Read the Docs โ€ข ๐Ÿ› Report Bug

About

Handwritten digit generation with classical ML (PCA, KDE, rejection sampling). A lightweight, interpretable alternative to GANs that runs in the browser.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages