Ultra-lightweight time series foundation model architecture (200K-1.6M params) with streaming inference and Hugging Face Hub integration.
Project description
🔮 NanoForecast
World's most deployable time series transformer
NanoForecast is a tiny, fast, deployable time series forecasting model. Unlike foundation models that require GPUs and terabytes of data, NanoForecast:
- Trains on your data in 2 minutes —
python3 train_from_csv.py --csv sales.csv --target revenue - Streams forecasts online — the only TS model where you can feed one value at a time
- Runs on a Raspberry Pi (<50ms inference on ARM)
- Exports to 1.4 MB ONNX (Edge/IoT/browser ready)
- Fully Apache 2.0 — no strings attached
It's not a foundation model. It's not going to beat TimesFM on benchmarks. What it does is actually ship to production.
Quick Start
Train on your own data (primary path)
python3 train_from_csv.py --csv my_data.csv --target sales --horizon 48
That's it. You get a saved model checkpoint + forecast CSV. No GPU, no cloud.
Built by Eulogik — deployable AI for the real world.
Or use the pretrained model
pip install nanoforecast
import numpy as np
from nanoforecast import NanoForecast
model = NanoForecast.from_pretrained("eulogik/nanoforecast-500k")
context = np.sin(np.linspace(0, 8*np.pi, 256)) + 0.1 * np.random.randn(256)
result = model.predict(context, horizon=48, freq=1)
forecast = result["forecast"][0] # shape (48,)
Streaming / Online Inference (unique to NanoForecast)
NanoForecast's DeltaNet RNN architecture maintains a recurrent state across calls — no other TS model does this.
# Initial forecast + state
result = model.predict(context, horizon=48, return_state=True)
state = result.pop("state")
# Stream new observations one at a time
for new_val in incoming_data_stream:
result = model.predict_step(new_val, state, horizon=48)
print(result["forecast"][0, :5]) # updated forecast instantly
Each call preserves the DeltaNet's memory of all past data. Use it for:
- Real-time IoT sensor monitoring
- Live financial tick data
- Interactive dashboards
Try It Now
Upload a CSV, set your horizon, get a forecast + prediction intervals + decomposition plot. No code required.
Features
| Feature | Details |
|---|---|---|
| Architecture | LongConv + DeltaNet RNN + gated router + MLP blocks |
| Parameters | ~200K–700K (tiny) |
| Outputs | Point forecast + 5 quantiles (p10/p25/p50/p75/p90) + trend/seasonal/residual decomposition |
| Context | 256 timesteps |
| Horizon | Any length (trained on 48) |
| Frequency | Hourly / Daily / Weekly / Monthly |
| Deploy targets | CPU, ARM, Raspberry Pi, Lambda, iOS, browser (via ONNX.js) |
| Streaming inference | Stateful RNN — feed one value at a time, no re-processing |
| Train on your data | train_from_csv.py — 2 min on a laptop, no GPU |
Deploy
FastAPI Server
pip install nanoforecast fastapi uvicorn python-multipart
python3 deploy/fastapi_server.py
# → http://localhost:8000/docs
curl -X POST http://localhost:8000/predict \
-d "context=[1.0,2.0,3.0,...]" \
-d "horizon=48" \
-d "freq=1"
Docker
docker build -t nanoforecast -f deploy/Dockerfile .
docker run -p 8000:8000 nanoforecast
ONNX (Edge / IoT)
pip install "nanoforecast[onnx]"
python3 -m nanoforecast.export.onnx_export \
--checkpoint <checkpoint-dir> \
--output nanoforecast.onnx
Then load with onnxruntime on any platform:
import onnxruntime as ort
session = ort.InferenceSession("nanoforecast.onnx")
forecast = session.run(None, {"input": context_numpy})
Repository layout
nanoforecast/
config.py # NanoForecastConfig dataclass
model/ # core architecture
blocks.py # LongConv, DeltaNet, GatedMLP, GatedRouter
heads.py # point, quantile (monotonic), anomaly, decomposition
core.py # NanoForecast nn.Module
utils.py # scaler, patching, freq prefix, positional encoding
train/
loss.py # multi-task loss (point + quantile + anomaly + smooth)
trainer.py # OneCycleLR trainer with MPS / CUDA / CPU support
data/
generator.py # synthetic time series generator
pipeline.py # dataset + resolution-aware batch sampler
real_datasets.py # ETTh1/2, ETTm1, exchange_rate, electricity, traffic loaders
evaluation/
benchmark.py # MASE, sMAPE, MSE, MAE, CRPS, coverage
export/
onnx_export.py # FP32 + dynamic INT8 ONNX export
hub.py # save_pretrained / from_pretrained / predict mixin
gradio_app.py # Hugging Face Space (upload CSV → forecast plot)
demo.py # one-liner demo: python3 demo.py
deploy/ # FastAPI server + Docker
fastapi_server.py
Dockerfile
requirements.txt
pretrain.py # real + synthetic pretraining CLI
benchmark.py # multi-dataset benchmark CLI
push_to_hub.py # publish a checkpoint to the HF Hub
run_pipeline.py # synthetic-only smoke pipeline (legacy)
train_from_csv.py # train on your own CSV (primary user path)
tests/ # unit + smoke tests
Architecture
Raw Context -> Robust Scaling & Patching -> Resolution Prefix Token
|
v
Sequence Mixing Blocks (x N)
- LongConv (global periodicity)
- DeltaNet RNN (local dependencies)
- Gated Router & MLP (dynamic blend)
|
v
Multi-Task Heads (single forward pass)
- Point forecast
- Monotonic quantiles (p10..p90)
- Context reconstruction (anomaly)
- Trend / Seasonality decomposition
| Preset | d_model | Layers | Patch | Parameters | FP32 size |
|---|---|---|---|---|---|
nano-200k |
32 | 4 | 8 | ~676K | ~2.7 MB |
nano-500k |
64 | 8 | 8 | ~1.6M | ~6.4 MB |
nano-1m (v0.3) |
96 | 8 | 8 | ~3.6M | ~14 MB |
Design notes
- Instance Robust Scaler (median / IQR) makes the model robust to outliers.
- Monotonic quantile head guarantees p10 ≤ p25 ≤ p50 ≤ p75 ≤ p90.
- Conservation identity: trend + seasonal + residual ≡ point forecast.
- ONNX exportable with a drop-in RMSNorm replacement.
Train Your Own
python3 pretrain.py \
--datasets ETTh1,ETTh2,exchange_rate,electricity \
--epochs 50 \
--batch-size 64 \
--device cpu \
--output checkpoints/nanoforecast-my-data
Benchmarking
python3 benchmark.py \
--checkpoint <checkpoint-dir> \
--datasets ETTh1,ETTh2,ETTm1,exchange_rate \
--max-windows 64 \
--output results/benchmark.json
Publishing to HF Hub
huggingface-cli login
python3 push_to_hub.py \
--checkpoint <checkpoint-dir> \
--repo-id your-username/nanoforecast-500k \
--benchmark-json results/benchmark.json
Benchmarks
v0.3 (d_model=96, 6.5M params, context=512, 200 epochs, Colab T4)
| Dataset | MASE | sMAPE (%) | MAE | CRPS |
|---|---|---|---|---|
| ETTh1 | 1.95 | 12.06 | 1.30 | 1.05 |
| ETTh2 | 2.74 | 10.47 | 2.46 | 1.99 |
| ETTm1 | 2.17 | 10.70 | 0.72 | 0.65 |
| exchange_rate | 7.44 | 1.72 | 0.011 | 0.014 |
| electricity | 1.29 | 4.76 | 158.30 | 175.24 |
| traffic | 0.81 | 24.00 | 0.004 | 0.003 |
| Overall | 2.73 | 10.62 | 27.13 | 29.83 |
v0.2 (d_model=64, 1.6M params, context=256, 100 epochs, Mac Mini M4)
| Dataset | MASE | sMAPE (%) | MAE | CRPS |
|---|---|---|---|---|
| ETTh1 | 3.34 | 25.13 | 2.40 | 1.80 |
| ETTh2 | 3.71 | 17.65 | 3.21 | 2.52 |
| ETTm1 | 3.58 | 17.22 | 1.17 | 1.00 |
| exchange_rate | 7.31 | 1.63 | 0.010 | 0.009 |
| electricity | 1.54 | 5.65 | 189.75 | 187.26 |
| traffic | 1.25 | 44.80 | 0.006 | 0.006 |
| Overall | 3.45 | 18.68 | 32.76 | 32.10 |
v0.3 vs v0.2 comparison
| Dataset | v0.2 | v0.3 | Improvement |
|---|---|---|---|
| ETTh1 | 3.34 | 1.95 | ↓ 42% |
| ETTh2 | 3.71 | 2.74 | ↓ 26% |
| ETTm1 | 3.58 | 2.17 | ↓ 39% |
| exchange_rate | 7.31 | 7.44 | ↑ 2% |
| electricity | 1.54 | 1.29 | ↓ 16% |
| traffic | 1.25 | 0.81 | ↓ 35% |
| Overall | 3.45 | 2.73 | ↓ 21% |
v0.3 beats v0.2 on 5 of 6 datasets. Larger model (6.5M vs 1.6M) and longer context (512 vs 256) provide significant accuracy gains on ETTh1/ETTh2/ETTm1. Exchange rate (volatile FX) slightly regresses.
Known limitations
| Issue | Status |
|---|---|
| Accuracy | Modest vs SOTA (MASE ~2.73 overall for v0.3). Good enough for prototypes, not production forecasting at scale. |
| Training | Multi-dataset mixing (v0.3: 6 real + 10K synthetic, 200 epochs). |
| Context | Fixed 256 — longer history is truncated. |
| Channels | Univariate by default; multivariate support is per-dimension independent. |
| Edge cases | NaN values, missing timestamps, irregularly-sampled data not handled automatically. |
This is a developer tool, not a research paper. It prioritizes deployability over accuracy.
Roadmap
| Version | Focus | Timeline |
|---|---|---|
| v0.1 | Deployable MVP — train, predict, export, deploy | ✅ Done |
| v0.2 | Streaming inference + train-from-CSV CLI + multi-dataset training (Mac Mini) | ✅ Done |
| v0.3 | Colab T4 training (larger model, more data) + ONNX.js browser demo | TBD |
| v0.4 | OpenRouter API — $0.001/forecast | TBD |
Why "NanoForecast"?
Because forecasting models shouldn't require:
- A $30K GPU
- 100 GB of training data
- 12 dependencies that break every release
- A team of PhDs to deploy
You should be able to train a forecasting model on your laptop, deploy it to a Raspberry Pi, and have it running in production before lunch.
License
Apache 2.0. See LICENSE.
Built by Eulogik — deployable AI for the real world.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file nanoforecast-0.2.0.tar.gz.
File metadata
- Download URL: nanoforecast-0.2.0.tar.gz
- Upload date:
- Size: 40.8 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.0
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
7285e603b94e0274af41cb922dc0b3fce774141477164db2ae2c3ae9ca54c0af
|
|
| MD5 |
62a34ff6553ddbc9c4a95e6183ffb86d
|
|
| BLAKE2b-256 |
24594337e0928a68cca338c81ad30a3193e44dce59dc9453517ce13e2f1c9225
|
File details
Details for the file nanoforecast-0.2.0-py3-none-any.whl.
File metadata
- Download URL: nanoforecast-0.2.0-py3-none-any.whl
- Upload date:
- Size: 39.8 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.0
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
6cf08f7f69dfb17c5bc7e3e2cf738745d63f75e6c56913608d09030b08db31d0
|
|
| MD5 |
07ee9a41c7fd11aa925388a2310917c7
|
|
| BLAKE2b-256 |
5e96802df7877ba0b8a95e8405af4984578845ffdbe41e1859f7e6433769d06a
|