🔮 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.
Metadata
Release files for nanoforecast 0.2.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| nanoforecast-0.2.0.tar.gz | 40.8 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| nanoforecast-0.2.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 80.6 kB
Release files / nanoforecast-0.2.0.tar.gz
| Download URL | nanoforecast-0.2.0.tar.gz |
|---|---|
| Size | 40.8 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
7285e603b94e0274af41cb922dc0b3fce774141477164db2ae2c3ae9ca54c0af
|
|
BLAKE2b-256 checksum How to use checksums |
24594337e0928a68cca338c81ad30a3193e44dce59dc9453517ce13e2f1c9225
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.14.0
|
Release files / nanoforecast-0.2.0-py3-none-any.whl
| Download URL | nanoforecast-0.2.0-py3-none-any.whl |
|---|---|
| Size | 39.8 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
6cf08f7f69dfb17c5bc7e3e2cf738745d63f75e6c56913608d09030b08db31d0
|
|
BLAKE2b-256 checksum How to use checksums |
5e96802df7877ba0b8a95e8405af4984578845ffdbe41e1859f7e6433769d06a
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.14.0
|