Skip to main content

fastumap

UMAP in pure numpy + scipy. No numba, no LLVM, nothing that compiles when you import it.

cold import added to image
import umap (umap-learn) ~21 s (laptop) · 148 s (0.5 vCPU ×4) ~172 MB
import fastumap ~12 ms 0 MB

The whole idea: the problem was never numba — it's that numba compiles at import time. numpy and scipy are just as compiled, but they ship precompiled in the wheel, so they load in milliseconds. Same math, no runtime JIT.

Why import cost matters

A small, CPU-throttled container — a fraction of a vCPU, a few workers, a health check polling from the first second:

  • import umap ≈ 4 CPU-seconds. pynndescent alone JIT-compiles 46 @njit functions.
  • Through a 0.5 vCPU, 4-worker cgroup that's ~148 s — past a ~120 s health check. The container is killed before it serves one request.
  • More cores barely help (37.8 s at 1 CPU, 16.1 s at 2) — the compile is serial.
  • Numba cache? No help (eager signatures skip it). NUMBA_DISABLE_JIT=1? ~100× slower.

fastumap imports in ~12 ms. That's the point.

Quality vs umap-learn

Within 0.01–0.02 neighbour-overlap of umap-learn, ahead on global structure, and it buries PCA and the random control. Real MNIST (784-dim, single thread, make bench):

n method wall overlap@15 ↑ global corr ↑
5000 fastumap 26 s 0.333 0.310
5000 umap-learn 73 s 0.344 0.329
10000 fastumap 72 s 0.267 0.279
10000 umap-learn 83 s 0.274 0.286
20000 fastumap 110 s 0.188 0.323
20000 umap-learn 31 s 0.205 0.316
  • Wins at 5k/10k, loses at 20k — the brute-force O(n²) kNN catches up with it (approximate kNN is roadmap #15). PCA sits at ~0.02–0.06 overlap: a linear method can't compete locally.
  • umap-learn's times here reuse the numba compile paid on the first fit; a fresh process pays ~20 s every time — the cost fastumap exists to avoid.
  • chunk_count=10 closes most of the local-overlap gap (~5× slower, still deterministic). Default 1 is the fast path.

overlap@k = share of each point's k input neighbours still neighbours after projection (read it against random). global corr = Spearman corr of all pairwise distances, before vs after.

Install

pip install fastumap        # numpy + scipy, nothing else

Use

from fastumap import umap_project, spectral_project

xy  = umap_project(x, 2)                     # (n, 2)
xyz = umap_project(x, 3)                     # (n, 3)
cos = umap_project(x, 2, metric="cosine")    # text / CLS embeddings
  • cosine for encoder embeddings — euclidean on unnormalised vectors is dominated by length, not the direction that carries meaning.
  • pca_dim=100 for wide inputs (e.g. 1024-dim): pre-reduces before the kNN, overlap holds within ~0.01, off by default.

Same input + seed → bit-identical output across processes. umap_project also takes n_neighbors, min_dist, spread, n_epochs, negative_sample_rate, random_state.

In a server

Thread-safe — fresh RNG per call, no module-level state, so await asyncio.to_thread(umap_project, x, 2) is fine.

Don't refit every request. Fit once, place new points:

model = fit(window, 2)          # cache it — UMAPModel pickles
xy    = transform(model, pts)   # per request: cheap, stable across requests
  • transform ≈ refit? Keeps ~72% of a full refit's local overlap. Good for placing in-distribution points against a fixed window; refit when the window itself shifts.
  • Gone stale? Watch new-point distance to nearest training neighbour. Drifts to 2–3× the training mean → time to refit. (A timer is a weak proxy.)
  • Memory: ~20 MB per cached 5000×1024 model (train kept as float32).
  • Rolling window ("add these, drop old ones") and sparse input: not supported — both would need a rebuild. Densify sparse first; fit/transform cover the append-only case.

Speed, honestly

At 1024-dim, n=5000, fastumap is ~2× slower per call than umap-learn (~38–53 s vs ~22 s). That's inherent — a vectorised numpy SGD can't match numba's in-place walk. Use fastumap when cold-start / import cost dominates; reach for umap-learn when per-call latency on big high-dimensional batches does.

Optional Rust accelerator (rust/) — ~1.7–1.9× faster with better overlap, one abi3 wheel for Python 3.11+. Auto-detected when installed; the base stays pure numpy+scipy and is the fallback.

Guarantees (each pinned by a test)

  • numpy + scipy only at runtime — no numba, llvmlite, sklearn, or compiled code of ours.
  • Import < 200 ms · deterministic (bit-identical) · thread-safe.
  • Memory-bounded — the n×n distance matrix is never built (blocked kNN); < 200 MB at 5000×1024.
  • 2-D and 3-D, both first-class · typed, pyright strict.

Testing

make check     # lint + typecheck + tests (mirrors CI's gate)
make tox       # across Python 3.11 / 3.12 / 3.13
make fargate   # import + fit timing under docker --cpus=0.5 --memory=2g

--cpus is a CFS quota (throttles total CPU-time like a container cgroup), so the numbers mean what they will on 0.5 vCPU.

Not affiliated with UMAP

An independent reimplementation of the UMAP algorithm (McInnes, Healy, Melville, arXiv:1802.03426) — not endorsed by the authors, and not a drop-in replacement. MIT licensed.

Download files

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

Source Distribution

fastumap-0.1.12.tar.gz (35.6 kB view details)

Uploaded Source

Built Distribution

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

fastumap-0.1.12-py3-none-any.whl (23.5 kB view details)

Uploaded Python 3

File details

Details for the file fastumap-0.1.12.tar.gz.

File metadata

  • Download URL: fastumap-0.1.12.tar.gz
  • Upload date:
  • Size: 35.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.11.19 {"installer":{"name":"uv","version":"0.11.19","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Debian GNU/Linux","version":"12","id":"bookworm","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for fastumap-0.1.12.tar.gz
Algorithm Hash digest
SHA256 11acb811526943cc48c83a56285e036020ffdab1ece44fd7b954eb6377aa2ad4
MD5 98be74aa7bf23a39a0bc1c80e80d0dcd
BLAKE2b-256 6b757cfb28cf78823678f94df8496e914348c3735437f3930c0049487f9a1688

See more details on using hashes here.

File details

Details for the file fastumap-0.1.12-py3-none-any.whl.

File metadata

  • Download URL: fastumap-0.1.12-py3-none-any.whl
  • Upload date:
  • Size: 23.5 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.11.19 {"installer":{"name":"uv","version":"0.11.19","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Debian GNU/Linux","version":"12","id":"bookworm","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for fastumap-0.1.12-py3-none-any.whl
Algorithm Hash digest
SHA256 f4e4f7dcd152c99d7084439905b3ece224f55638a14e7b419a92989d9f978fa0
MD5 03299eb2d9c4c7f2e1f0706c574718f7
BLAKE2b-256 c29ddc38d0de3911d90ab9f4a0753a0d9461a91a207e07e887cea580612f20a4

See more details on using hashes here.

Release history Release notifications | RSS feed

0.2.29

1 file

0.2.28

1 file

0.2.27

6 files

0.2.26

1 file

0.2.20

6 files

0.2.19

6 files

0.2.18

6 files

0.2.17

6 files

0.2.16

5 files

0.2.15

5 files

0.2.14

5 files

0.2.13

5 files

0.2.12

5 files

0.2.11

5 files

0.2.10

5 files

0.2.9

5 files

0.2.8

5 files

0.2.7

5 files

0.2.6

3 files

0.2.5

3 files

0.2.4

3 files

0.2.3

3 files

0.2.2

3 files

0.2.1

3 files

0.2.0

2 files

0.1.26

2 files

0.1.25

2 files

0.1.24

2 files

0.1.23

2 files

0.1.22

2 files

0.1.21

2 files

0.1.20

2 files

0.1.19

2 files

0.1.18

2 files

0.1.16

2 files

0.1.15

2 files

0.1.14

2 files

0.1.13

2 files

This release

0.1.12 This release

2 files

0.1.11

2 files

0.1.10

2 files

0.1.9

2 files

0.1.8

2 files

0.1.7

2 files

0.1.6

2 files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page