Skip to content

Projection

umap_project reduces (n, d) to any output dimension: 2-D and 3-D for visualisation, around 10-D as a preprocessing step before clustering.

from fastumap import umap_project, spectral_project

xy  = umap_project(x, 2)                     # (n, 2)
xyz = umap_project(x, 3)                     # (n, 3)
red = umap_project(x, 10)                    # ~10-D for clustering (not just 2/3)
cos = umap_project(x, 2, metric="cosine")    # text / CLS embeddings
dm  = umap_project(x, 2, densmap=True)       # densMAP: keep dense/sparse regions distinct
  • metric="cosine" is recommended for encoder embeddings. Euclidean distance on unnormalised vectors is dominated by magnitude rather than by the direction that carries meaning.
  • pca_dim=100 pre-reduces very wide inputs (for example 1024-dimensional embeddings) before the nearest-neighbour search. Neighbour overlap is preserved to within about 0.01. Off by default.

umap_project also accepts n_neighbors, min_dist, spread, n_epochs, negative_sample_rate, random_state, and chunk_count.

Supervised projection

Categorical labels passed as y inform the layout: same-label points attract, so structure that is separable in the input space stays separable in 2-D instead of interleaving.

xy = umap_project(x, 2, y=labels)                     # labels: one int per point, -1 = unlabelled
xy = umap_project(x, 2, y=labels, target_weight=0.9)  # lean harder on the labels

target_weight is in [0, 1] and defaults to 0.5. It trades geometry against labels: 0.0 barely weakens inter-class edges, 1.0 cuts them entirely. Labels of -1 count as unlabelled (semi-supervised). The default y=None is ordinary unsupervised UMAP, unchanged.

This ports umap-learn's categorical intersection. The UMAP paper only sketches the idea (arXiv:1802.03426, §7 Future Work), so umap-learn is the reference; see its supervised docs.

Next

  • Placing new points into an existing layout without refitting is In a server.
  • Above ~20k points the neighbour search dominates — see Large inputs.
  • Full signatures are in the API reference.