shibatch's picture
Upload folder using huggingface_hub
7cdce5b verified
|
Raw
History Blame Contribute Delete
8.15 kB
---
library_name: pytorch
pipeline_tag: text-to-image
license: mit
datasets:
- ylecun/mnist
tags:
- diffusion
- ddim
- mnist
- handwritten-digits
- tiny-model
---
# Tiny Digit Diffusion 3M
Tiny Digit Diffusion 3M is a **2,767,529-parameter** conditional diffusion
model that renders a prompt containing one to eight ASCII digits as a
handwritten grayscale image. It was trained from scratch on dynamically
composed MNIST digit strings and contains no weights from another generative
model.
This is a deliberately narrow tiny-model experiment, not a general-purpose
text-to-image model. Its complete prompt language is a numeric string such as
`7`, `2026`, or `31415926`.
![Generated samples](sample_grid.png)
## Repository contents
- `model/model.safetensors`: FP32 EMA inference weights
- `model/config.json`: architecture and diffusion configuration
- `tiny_digit_diffusion.py`: model, schedule, DDIM sampler, and weight loader
- `generate_tiny_digits.py`: command-line generation example
- `train_tiny_digit_diffusion.py`: training script
- `artifact_metadata.json`: training settings and evaluation summary
- `sample_grid.png`: generations from the final checkpoint
Optimizer checkpoints, MNIST files, per-epoch samples, and the training log are
not included in the distribution package.
## Quick start
Create an environment and install the inference dependencies:
```bash
python -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt
```
Generate an eight-digit image:
```bash
python generate_tiny_digits.py 31415926 --output 31415926.png
```
On the first run, the script downloads `model/config.json` and
`model/model.safetensors` from `shibatch/tinydigitdiffusion3m` on Hugging
Face. Later runs reuse the local Hugging Face cache.
The script accepts the following useful options:
```bash
python generate_tiny_digits.py 2026 \
--steps 50 \
--guidance-scale 1.0 \
--seed 0 \
--device auto \
--output 2026.png
```
Use a different Hub revision with `--revision`, or override the repository
with `--repo-id`. To use model files already stored locally (including the
`model/` directory included in this distribution package), pass
`--model-dir`:
```bash
python generate_tiny_digits.py 2026 --model-dir ./model --output 2026.png
```
The output is a fixed `32 x 256` grayscale PNG. Short prompts are centered on
the eight available 32-pixel slots.
## Python example
```python
import sys
from pathlib import Path
import torch
from huggingface_hub import snapshot_download
from PIL import Image
repo_dir = Path(snapshot_download(
repo_id="shibatch/tinydigitdiffusion3m",
allow_patterns=[
"model/config.json",
"model/model.safetensors",
"tiny_digit_diffusion.py",
],
))
sys.path.insert(0, str(repo_dir))
from tiny_digit_diffusion import ddim_sample, load_model
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
model = load_model(repo_dir / "model", device)
image = ddim_sample(
model,
prompts=["31415926"],
device=device,
sampling_steps=50,
guidance_scale=1.0,
seed=0,
)[0, 0]
pixels = ((image.cpu() + 1) * 127.5).round().clamp(0, 255).byte().numpy()
Image.fromarray(pixels, mode="L").save("31415926.png")
```
Prompts must contain only one to eight ASCII digits. Spaces, signs, decimal
points, letters, and strings longer than eight digits are rejected.
## Recommended inference settings
```yaml
sampling_method: deterministic DDIM
sampling_steps: 50
guidance_scale: 1.0
output_size: 32 x 256
```
Use `guidance_scale=1.0`. Larger classifier-free-guidance values are not
helpful for this checkpoint. In particular, the original diagnostic setting
of `3.0` over-amplifies the conditioning difference and creates digit-like
artifacts in padding slots. At `1.0`, the sampler uses the conditional model
directly and skips the unnecessary unconditional pass.
## Architecture
```yaml
model: custom conditional diffusion U-Net
parameter_count: 2,767,529
weight_dtype: float32
weight_file_size: approximately 11 MB
image_channels: 1
image_height: 32
image_width: 256
maximum_digits: 8
slot_width: 32
base_channels: 48
channel_multipliers: [1, 1.5, 2, 2.6667]
embedding_dim: 192
token_embedding_dim: 32
spatial_condition_channels: 8
attention_heads: 4
diffusion_steps: 400
```
The denoiser has four resolution levels with residual blocks, skip
connections, a bottleneck self-attention layer, sinusoidal timestep
conditioning, global prompt conditioning, and slot-aligned spatial digit
conditioning. Prompt tokens consist of digits `0` through `9`, a padding token,
and a classifier-free null token.
## Training
Each training example was assembled dynamically from MNIST:
1. Sample a prompt length uniformly from one to eight digits.
2. Sample an MNIST image independently for every digit.
3. Center the string on a `32 x 256` canvas.
4. Apply small horizontal and vertical offsets and an intensity variation.
5. Train the model to predict noise at a random cosine-schedule timestep.
Training configuration:
```yaml
dtype: float32
epochs: 30
steps: 28,110
batch_size: 64
samples_processed: 1,799,040
optimizer: AdamW
learning_rate: 2.0e-4
warmup_steps: 500
minimum_learning_rate: 2.0e-5
weight_decay: 0.0
gradient_clip: 1.0
condition_dropout: 0.1
ema_decay: 0.999
final_recent_noise_mse: 0.015345
training_time: approximately 70 minutes
```
The distributed checkpoint is the EMA model, not the raw final optimizer
weights.
To train from scratch, install the additional dependencies and choose an output
directory:
```bash
pip install -r requirements-train.txt
python train_tiny_digit_diffusion.py \
--output-dir runs/tiny_digit_diffusion_3m \
--data-dir data/mnist \
--epochs 30 \
--batch-size 64 \
--device cuda
```
## Evaluation
A separate small MNIST classifier was trained only for automated readability
measurement. It reached 98.68% accuracy on the MNIST test split. The final
generator was then evaluated on 240 random prompts: 30 prompts for every length
from one through eight digits, using 50 DDIM steps and guidance 1.0.
| Prompt length | Exact string | Per-digit accuracy |
|---:|---:|---:|
| 1 | 29/30 (96.7%) | 96.7% |
| 2 | 26/30 (86.7%) | 91.7% |
| 3 | 26/30 (86.7%) | 95.6% |
| 4 | 22/30 (73.3%) | 93.3% |
| 5 | 22/30 (73.3%) | 93.3% |
| 6 | 14/30 (46.7%) | 88.9% |
| 7 | 22/30 (73.3%) | 95.7% |
| 8 | 13/30 (43.3%) | 90.4% |
| **Overall** | **174/240 (72.5%)** | **92.6%** |
These are OCR-proxy measurements, not human ratings. A generated digit can be
legible to a person while being classified differently, and the classifier can
also be confidently wrong. The samples should therefore be considered
alongside the numeric results.
## Limitations
- Longer strings compound individual digit errors; eight-digit exact match is
substantially lower than single-digit accuracy.
- Some handwritten `3`, `5`, `7`, `8`, and `9` shapes can be ambiguous.
- The output canvas and maximum string length are fixed by the architecture.
- The model supports only ASCII digits and does not render signs, punctuation,
decimal values, mathematical expressions, or arbitrary text.
- This checkpoint reproduces MNIST-like handwriting only. It is not suitable
for OCR security testing, document generation, or realistic typography.
- Results vary with the random seed even though each DDIM trajectory is
deterministic for a fixed seed.
## Scope
This checkpoint is intended for education, architecture experiments, tests,
and demonstrations of a complete conditional image generator at a very small
parameter count. It should not be interpreted as an official MNIST model or as
an image-generation counterpart of any production diffusion system.
## License
The source code and model checkpoint in this package are released under the
MIT License. See `LICENSE` for the complete terms.
The MNIST images are not redistributed in this package. Training used MNIST
through `torchvision`; the [MNIST dataset card](https://huggingface.co/datasets/ylecun/mnist)
identifies its license as MIT and credits Yann LeCun, Corinna Cortes, and
Christopher J. C. Burges as the dataset curators.