A from-scratch deep learning framework and interactive AI lab — built entirely in pure NumPy.
No PyTorch. No TensorFlow. No Keras. Every gradient is computed by a reverse-mode automatic-differentiation engine that this project implements itself, down to convolutional backprop, backpropagation-through-time, multi-head attention, and the Q-learning update. It is not a thin wrapper around someone else's tensor library — the tensor math, the optimizer states, the training loop, the reinforcement-learning agent, and even the web dashboard are all written here.
Why build it? To demonstrate that the ideas powering modern AI — autograd, convnets, transformers, and deep reinforcement learning — can be understood and reimplemented from first principles, and to have a fun, interactive way to watch them learn.
| Capability | What it is |
|---|---|
| 🧮 Autograd engine | Reverse-mode automatic differentiation over n-d tensors with broadcasting — passes finite-difference gradient checks. |
| 🕸️ Full layer zoo | Linear, Conv2d, MaxPool/AvgPool/AdaptivePool, BatchNorm, LayerNorm, Dropout, Embedding. |
| 🔁 Recurrent nets | RNN, GRU, and LSTM with backpropagation-through-time (via graph unrolling). |
| 🧠 Transformers | Multi-head attention, causal masking, pre-norm blocks, and a GPT decoder-only language model. |
| 🎛️ Optimizers | SGD (+momentum/Nesterov), RMSprop, Adam, AdamW, plus LR schedulers (Step/Exp/Cosine/OneCycle). |
| 🏗️ NeuroIR DSL | A mini-compiler that turns input 1x28x28 conv 8 3x3 pad 1 relu pool 2 … into a trainable model with shape inference + a summary table. |
| 📦 Data module | Dataset/DataLoader, transforms, a cached MNIST loader and character tokenizer (with offline fallbacks). |
| 🚂 Trainer | Metrics, callbacks, checkpointing, early stopping, live progress hooks. |
| 🎮 Reinforcement learning | DQN with Double-DQN target updates + replay buffer, a hand-written CartPole physics env, and a grid-world game. |
| 🌐 Web dashboard | Train models live, draw a digit and classify it, generate Shakespeare, watch the RL agent navigate a maze. |
Three real, trained demos ship with it:
- MNIST CNN — a LeNet-style convnet that reaches ~98–99% test accuracy.
- GPT text generator — a decoder-only transformer trained on a character corpus.
- DQN grid-world agent — learns to reach a goal while dodging traps.
The only hard dependency is NumPy (the demos additionally use Matplotlib and
Flask for the dashboard; pytest for the tests). Everything already works with a
stock Anaconda/Python 3.10+ environment:
# 0) (optional) create an environment — or just use an existing one
python -m venv .venv && source .venv/bin/activate # Windows: .venv\Scripts\activate
pip install numpy matplotlib flask pytest tqdm rich
# 1) run the test suite (66 tests, all gradient-checked)
python -m pytest
# 2) train a model
python run.py train-mnist --epochs 4
python run.py train-gpt --epochs 8
python run.py train-cartpole --episodes 300
python run.py train-gridworld --episodes 400
# 3) compile an architecture from a spec string
python run.py ir "input 1x28x28 conv 8 3x3 pad 1 relu pool 2 flatten linear 10"
# 4) launch the interactive dashboard
python run.py serve --port 5000 # then open http://127.0.0.1:5000Data (MNIST, the text corpus) and model checkpoints are cached under ./data/
and ./checkpoints/ — nothing leaves this project directory.
import numpy as np
from neuroforge import Tensor, nn, optim, data
# -- autograd, from first principles -------------------------------
a = Tensor(np.array([1.0, 2.0]), requires_grad=True)
b = Tensor(np.array([3.0, 4.0]), requires_grad=True)
c = (a * b).sum() # builds a computation graph
c.backward() # reverse-mode differentiation
print(a.grad) # -> [3. 4.]
# -- a trainable convnet -------------------------------------------
model = nn.Sequential(
nn.Conv2d(1, 8, 3, padding=1), nn.ReLU(), nn.MaxPool2d(2),
nn.Flatten(), nn.Linear(8 * 14 * 14, 10),
)
opt = optim.Adam(model.parameters(), lr=1e-3)
loss_fn = nn.CrossEntropyLoss()
x_train, y_train, x_test, y_test = data.fetch_mnist()
for xb, yb in data.DataLoader(data.TensorDataset(x_train, y_train), batch_size=64, shuffle=True):
opt.zero_grad()
loss = loss_fn(model(Tensor(xb)), yb)
loss.backward()
opt.step()See examples/ for four standalone scripts that walk through autograd, the DSL,
a full MNIST training loop, and CartPole DQN.
from neuroforge import ir
spec = ("input 1x28x28 conv 8 3x3 pad 1 relu pool 2 "
"conv 16 3x3 pad 1 relu pool 2 flatten linear 128 relu linear 10")
print(ir.format_summary(spec))
model, _ = ir.compile(spec) # a ready-to-train nn.SequentialThe compiler is a real pipeline — lexer → parser (with shape inference) →
codegen — so you never specify an input dimension twice: it infers Linear
input sizes, Conv2d channel counts, and layer output shapes from the declared
input shape.
Grammar (whitespace-separated; 3x3 and 1x28x28 are valid):
input C H W | input D
conv OUT KX [KY] [pad P] [stride S] linear OUT
pool K [stride S] | avgpool K flatten | adaptiveavgpool
relu | gelu | sigmoid | tanh | silu | leakyrelu | softmax | logsoftmax
batchnorm | layernorm | dropout P identity
neuroforge/
├── core/ Tensor + autograd engine, differentiable ops, initializers
├── nn/ Module/Parameter, layers, RNN/GRU/LSTM, transformer/GPT, losses
├── optim/ SGD/Momentum/RMSprop/Adam/AdamW + LR schedulers
├── data/ Dataset/DataLoader, transforms, MNIST + text corpora
├── train/ Trainer, metrics, callbacks, history
├── rl/ CartPole + grid-world envs, replay buffer, DQN
├── ir/ NeuroIR DSL (lexer, parser, compiler)
├── utils/ checkpoint serialization, plotting
└── recipes.py turn-key training recipes shared by CLI + dashboard
app/ Flask web dashboard (server + vanilla-JS front-end)
examples/ standalone how-to scripts
tests/ pytest suite (gradient checks, layer checks, trainer, RL, IR)
run.py unified command-line interface
The suite (66 tests) is the project's correctness backbone:
- Finite-difference gradient checks for every op — matmul (2D/3D/batched), conv2d (stride/pad), pooling, batch/layer norm, softmax/log-softmax, embedding, reductions, shape ops — and for whole layers (Linear, Conv2d, RNN/GRU/LSTM, attention, GPT).
- Optimizer convergence checks on toy problems.
- Trainer end-to-end (loss decreases, early stopping, checkpoint round-trip).
- RL environment sanity + DQN smoke test.
- NeuroIR parse/compile/summarize round-trips and error cases.
python -m pytest # -> 66 passed- Autograd stores a backward closure per op and walks the graph in reverse
topological order, so branched graphs accumulate gradients correctly.
Broadcasting is inverted with an
unbroadcastreduction. - Conv/pool use an
im2col/ window-scatter formulation — exact and backprop-correct on CPU. - RNNs are unrolled over time, so BPTT is just the ordinary reverse-mode pass over the unrolled graph (weight sharing = gradient accumulation).
- GPT uses learned positional embeddings, causal (upper-triangular) masking, pre-norm residuals, and temperature / top-k sampling for generation.
- DQN learns with a target network, a circular replay buffer, Double-DQN updates (online net selects, target net evaluates), and ε-greedy exploration over a hand-written physics/grid environment.
Everything is deterministic under a fixed seed, so runs are reproducible.
MIT — use it, learn from it, extend it.