Skip to main content

A lightweight, powerful Python framework for training AI models — inspired by numpy, scikit-learn, PyTorch and TensorFlow.

Project description

EmberML

CI License Python Version

A lightweight, powerful Python framework for training AI models — built from scratch.

EmberML combines the essentials of numpy, scikit-learn, PyTorch and TensorFlow into one small, readable codebase. The core has exactly one hard dependency (numpy); everything else — GPU support, PyTorch/TensorFlow/scikit-learn/OpenCV interop — is an optional extra you opt into.

Author: Levi Enama


Honest positioning

EmberML's own autograd engine is pure numpy. It is not a replacement for PyTorch or TensorFlow on real production workloads — it doesn't have compiled CUDA kernels, doesn't do distributed multi-node training, and won't match their raw throughput on large models. What it gives you instead:

  • A training engine you can read end-to-end in an afternoon, with every op unit-tested and several (Conv2d, MaxPool2d, checkpointing) verified against numerical gradients
  • A single, consistent API across deep learning and classical ML and data loading and metrics
  • Real, working bridges to PyTorch/TensorFlow/scikit-learn/OpenCV for when you need their production-grade speed or ecosystem, without leaving EmberML's workflow

Features

Core (numpy only)

  • Full reverse-mode autograd on n-dimensional tensors
  • nn: Linear, Conv2d, MaxPool2d, Flatten, Dropout, BatchNorm1d, SimpleRNN, Sequential
  • optim: SGD, Adam, AdamW, RMSprop + lr_scheduler: StepLR, ExponentialLR, ReduceLROnPlateau
  • ml: LinearRegression, LogisticRegression, KMeans, KNNClassifier, GaussianNB, PCA, DecisionTreeClassifier, RandomForestClassifier
  • metrics: precision, recall, F1, confusion matrix, MSE, R²
  • Dataset / DataLoader (generic, works with lazy/on-disk data too) / train_test_split
  • Model persistence: .save()/.load() for networks, save_model()/load_model() for classical ML
  • EarlyStopping callback

Native acceleration (optional C++/C/Rust, auto-detected — see emberml/_native/)

  • Conv2d/MaxPool2d transparently use a compiled C++/OpenMP extension for the im2col/col2im/max-pool steps on CPU float32 tensors — the actual measured bottleneck in the pure-Python path (np.add.at-based col2im), not the matmul itself (numpy's BLAS already wins there). Falls back to the original pure-numpy code automatically on GPU tensors, other dtypes, or if no C++ compiler was available at install time — results are bit-for-bit checked equal either way (tests/test_native.py).
  • emberml.security: HMAC-SHA256 signing for saved models (save_model_secure()/load_model_secure()), backed by a small, dependency-free C implementation of SHA-256/HMAC. Addresses the fact that plain pickle.load() (what save_model()/load_model() use) runs arbitrary code from the file — verification happens before unpickling, so a wrong key or a tampered file is rejected outright.
  • emberml.safeformat: a pickle-free binary container (.emsf) for {name: numpy.ndarray} dicts — no unpickling step exists at all, so there's no code-execution surface to defend, unlike signed pickle. Implemented in Rust (PyO3) for safe parsing of untrusted files (bounds checking, no manual buffer arithmetic), with a byte-for-byte cross-compatible pure-Python fallback. security.save_tensors_secure()/ load_tensors_secure() combine it with the same HMAC signing as above — the strongest option when what you're saving is purely tensors (nn.Module weights, embeddings). Module.save(path, format="safe") uses it directly.
  • Check emberml.HAVE_NATIVE_OPS / emberml.HAVE_NATIVE_CRYPTO / emberml._native.HAVE_NATIVE_SAFEFORMAT at runtime to see which compiled extensions are active.

Scaling up (still numpy/stdlib only)

  • GPU: Tensor(..., device="cuda") / Module.to("cuda") via CuPy — a drop-in numpy-compatible GPU array library. Requires pip install emberml[gpu] and an NVIDIA GPU; raises a clear error rather than silently running on CPU if unavailable.
  • Mixed precision: emberml.amp.autocast() + GradScaler (dynamic loss scaling)
  • Gradient checkpointing: emberml.checkpoint.checkpoint(fn, *tensors) — trade compute for memory on deep networks
  • CPU data parallelism: emberml.parallel.DataParallelCPU — shard a batch across processes on one machine (not multi-GPU/multi-node)

emberml.integrations (optional bridges, not imported by default)

  • torch_bridge — hand off to real PyTorch when you need production GPU speed
  • tf_bridge — hand off to real TensorFlow
  • sklearn_bridge — use emberml.ml models inside scikit-learn Pipeline/GridSearchCV, or reach for a real scikit-learn model by name
  • cv — OpenCV-backed ImageDataset, image loading, flip/rotation augmentation

Installation

git clone https://github.com/<your-username>/emberml.git
cd emberml
pip install -e .                 # core only (numpy) — native extensions build automatically if a C/C++ compiler is present
pip install -e .[torch]          # + PyTorch bridge
pip install -e .[tf]             # + TensorFlow bridge
pip install -e .[sklearn]        # + scikit-learn bridge
pip install -e .[cv]             # + OpenCV bridge
pip install -e .[gpu]            # + CuPy (needs an NVIDIA GPU)
pip install -e .[all]            # everything

No C/C++ compiler or Rust toolchain on the machine (or a build hiccup)? Installation still succeeds — pip prints a one-line warning per missing toolchain and emberml runs on its pure-Python/numpy fallbacks. Verify what actually got built:

import emberml
print(emberml.HAVE_NATIVE_OPS, emberml.HAVE_NATIVE_CRYPTO, emberml._native.HAVE_NATIVE_SAFEFORMAT)

Signing a model checkpoint

from emberml import security

key = security.generate_key()          # keep this secret; os.urandom(32) under the hood
security.save_model_secure(model, "model.emlpkl", key)

# ... later, possibly on another machine / after downloading the file ...
model = security.load_model_secure("model.emlpkl", key)   # raises SecurityError on wrong key or tampering

Pickle-free tensor checkpoints (recommended for nn.Module weights)

# strongest option for pure-tensor checkpoints: no pickle anywhere, plus HMAC authenticity
from emberml import security

key = security.generate_key()
security.save_tensors_secure({"w1": w1, "b1": b1}, "weights.bin", key)
tensors = security.load_tensors_secure("weights.bin", key)   # SecurityError on wrong key/tampering

# or, unsigned, straight from a Module:
model.save("checkpoint", format="safe")   # writes checkpoint.emsf, no pickle involved
model.load("checkpoint", format="safe")

Quick start

Train a CNN, GPU if available

import numpy as np
from emberml import Tensor, nn, optim

device = "cuda"  # falls back to "cpu" if you don't have CuPy + a GPU
X = Tensor(np.random.randn(32, 1, 28, 28).astype(np.float32), device="cpu")
y = Tensor(np.random.randint(0, 2, (32, 1)).astype(np.float32), device="cpu")

model = nn.Sequential(
    nn.Conv2d(1, 8, kernel_size=3, padding=1), nn.ReLU(), nn.MaxPool2d(2),
    nn.Flatten(), nn.Linear(8 * 14 * 14, 32), nn.ReLU(), nn.Dropout(0.3),
    nn.Linear(32, 1), nn.Sigmoid(),
)
# model.to("cuda"); X = X.to("cuda"); y = y.to("cuda")  # uncomment on a GPU box

optimizer = optim.Adam(model.parameters(), lr=0.001)
for epoch in range(10):
    optimizer.zero_grad()
    loss = nn.bce_loss(model(X), y)
    loss.backward()
    optimizer.step()

model.save("mnist_like_model")

Mixed precision training

from emberml.amp import autocast, GradScaler

scaler = GradScaler()
with autocast():
    pred = model(X)
    loss = nn.mse_loss(pred, y)
scaler.scale(loss).backward()
scaler.step(optimizer)
scaler.update()

When you need real PyTorch speed

from emberml.integrations import torch_bridge

torch_state = torch_bridge.emberml_module_to_torch_state(model)
# now train_state in real torch.Tensors on a real GPU with real torch.optim

Classic ML inside a scikit-learn Pipeline

from emberml import ml
from emberml.integrations.sklearn_bridge import EmberMLClassifier
from sklearn.model_selection import cross_val_score

clf = EmberMLClassifier(ml.RandomForestClassifier, n_estimators=50)
scores = cross_val_score(clf, X_train, y_train, cv=5)

Real image data via OpenCV

from emberml.integrations.cv import ImageDataset
from emberml import DataLoader

ds = ImageDataset(image_paths, labels, size=(64, 64), augment=True)
loader = DataLoader(ds, batch_size=32, shuffle=True)

Command-line interface

python -m emberml info                        # library info
python -m emberml demo                        # run a live training demo
python -m emberml benchmark --iters 500        # benchmark forward+backward speed
python -m emberml --help                       # list all commands

Architecture

emberml/
├── tensor.py            # Core: Tensor + autograd, device (CPU/CUDA) + dtype aware
├── functional.py        # conv2d / max_pool2d (im2col/col2im, gradient-checked, device-aware)
├── amp.py                # autocast + GradScaler (mixed precision)
├── checkpoint.py         # gradient checkpointing
├── parallel.py            # CPU multiprocessing data parallelism
├── nn/                     # Linear, Conv2d, MaxPool2d, Flatten, Dropout,
│                            # BatchNorm1d, SimpleRNN, Sequential, losses
├── optim.py                 # SGD, Adam, AdamW, RMSprop
├── lr_scheduler.py           # StepLR, ExponentialLR, ReduceLROnPlateau
├── callbacks.py                # EarlyStopping
├── ml/                          # LinearRegression, LogisticRegression, KMeans,
│                                 # KNNClassifier, GaussianNB, PCA, DecisionTree,
│                                 # RandomForest
├── data.py                       # Dataset, DataLoader (generic), train_test_split
├── metrics.py                     # precision/recall/F1/confusion_matrix/MSE/R²
├── utils.py                        # seed, accuracy, one_hot, normalize, save/load
├── security.py                      # HMAC-SHA256 model signing (save_model_secure/load_model_secure)
├── safeformat.py                     # pickle-free tensor container dispatcher (.emsf)
├── _safeformat_py.py                  # pure-Python reference impl of the .emsf format
├── cli.py                            # info / demo / benchmark
├── _native/                            # OPTIONAL — compiled C++/C/Rust extensions, auto-detected
│   ├── ops.cpp                          # im2col/col2im/max_pool2d/activations (pybind11 + OpenMP)
│   ├── sha256.c, sha256.h, _crypto.c     # SHA-256/HMAC (plain C, no dependencies)
│   ├── rust_safeformat/                   # Cargo crate: .emsf reader/writer (PyO3, memory-safe parsing)
│   └── __init__.py                       # try/except imports; HAVE_NATIVE_OPS / _CRYPTO / _SAFEFORMAT
└── integrations/                     # OPTIONAL — never imported by default
    ├── torch_bridge.py
    ├── tf_bridge.py
    ├── sklearn_bridge.py
    └── cv.py
tests/                                 # 48 pytest tests (gradient checks, native-vs-reference checks, integration bridges)
examples/train_cnn_classifier.py        # full end-to-end training example
setup.py                                 # builds ext_modules (C/C++) + cargo build (Rust); metadata stays in pyproject.toml
.github/workflows/ci.yml                 # CI: core job (numpy only, + Rust toolchain) + integrations job (all extras)

Testing

pip install -e .[dev]
pytest tests/ -v                    # core tests, including native-extension checks (auto-skipped if not built)
pip install -e .[all,dev]
pytest tests/ -v                    # + integration bridge tests

Roadmap

  • LSTM / GRU cells
  • Real multi-GPU / multi-node distributed training (would hand off to torch.distributed rather than reinvent it)
  • ONNX-style model export

License

MIT — see LICENSE.

Author

Levi Enama

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

emberml-0.5.0.tar.gz (64.4 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

emberml-0.5.0-cp310-cp310-win_amd64.whl (58.8 kB view details)

Uploaded CPython 3.10Windows x86-64

File details

Details for the file emberml-0.5.0.tar.gz.

File metadata

  • Download URL: emberml-0.5.0.tar.gz
  • Upload date:
  • Size: 64.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.10.11

File hashes

Hashes for emberml-0.5.0.tar.gz
Algorithm Hash digest
SHA256 ef931ceac1a6b6b9eacc6d978b3508f011dcc72a0452b6bb0e22765f61508e26
MD5 d2a2428fcb2fd39d653f15ce927a41b1
BLAKE2b-256 71275879227b2f2190dcaaf21b2654acb36288884fecea83a0d5fa6013109161

See more details on using hashes here.

File details

Details for the file emberml-0.5.0-cp310-cp310-win_amd64.whl.

File metadata

  • Download URL: emberml-0.5.0-cp310-cp310-win_amd64.whl
  • Upload date:
  • Size: 58.8 kB
  • Tags: CPython 3.10, Windows x86-64
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.10.11

File hashes

Hashes for emberml-0.5.0-cp310-cp310-win_amd64.whl
Algorithm Hash digest
SHA256 924c5aae07f1861ea178a418eb4177af58b15686eecf4414ecb844fc68d862bf
MD5 53b1f8f9b74c2bd89459c7771238137e
BLAKE2b-256 f1e2a9033ab2a231622b6c76d1dc0ecc56a192468964bec381ef96223b47a96d

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page