Skill Tracer
Skills › Scientific Agent Skills › umap-learn

umap-learn

skill · 493 lines · BSD-3-Clause license · skills/umap-learn/SKILL.md

The facts

Its description

Applies UMAP-learn to nonlinear dimensionality reduction, 2D/3D embeddings, clustering preprocessing, supervised or semi-supervised UMAP, DensMAP, AlignedUMAP, and Parametric UMAP workflows.

The description the agent reads to decide when to use it.

From its settingsline 3

Files it mentions

references/api_reference.md

Files the text names, such as ones to read or write. Found by matching words, so treat them as pointers.

Found by matching wordsline 421 line 474

Licence

BSD-3-Clause license, from the skill file

The terms its author shares it under, which let it be shown here.

From its settingsline 4 licence text

Other settings

compatibility: Requires Python 3.9+ and umap-learn; optional HDBSCAN, Matplotlib, and TensorFlow with Keras 3. Network access is needed for installation, not local fitting. metadata: version: "1.5" last-reviewed: "2026-10-01" upstream-version: "0.5.12" skill-author: K-Dense Inc.

More settings at the top of the file, shown as written.

From its settingsline 5 line 6
Other files in this skill (1) Close

The text

Open on GitHub

Most marks come from matching words in the file, so treat them as pointers.

1---
2name: umap-learn
3description: Applies UMAP-learn to nonlinear dimensionality reduction, 2D/3D embeddings, clustering preprocessing, supervised or semi-supervised UMAP, DensMAP, AlignedUMAP, and Parametric UMAP workflows.
4license: BSD-3-Clause license
5compatibility: Requires Python 3.9+ and umap-learn; optional HDBSCAN, Matplotlib, and TensorFlow with Keras 3. Network access is needed for installation, not local fitting.
6metadata:
7 version: "1.5"
8 last-reviewed: "2026-10-01"
9 upstream-version: "0.5.12"
10 skill-author: K-Dense Inc.
11---
13# UMAP-Learn
15## Overview
17UMAP (Uniform Manifold Approximation and Projection) is a dimensionality reduction technique for visualization and general non-linear dimensionality reduction. Apply this skill for fast, scalable embeddings that approximate neighborhood structure, supervised learning, and clustering preprocessing.
19Before interpreting an embedding, check finite coordinates, neighborhood retention, sensitivity to seeds/parameters, and domain evidence in the original space. UMAP axes, island areas, and gaps between clusters have no calibrated physical or probabilistic meaning. Keep predictive test data outside preprocessing and embedding fits.

Overview

UMAP (Uniform Manifold Approximation and Projection) is a dimensionality reduction technique for visualization and general non-linear dimensionality reduction. Apply this skill for fast, scalable embeddings that approximate neighborhood structure, supervised learning, and clustering preprocessing.

Before interpreting an embedding, check finite coordinates, neighborhood retention, sensitivity to seeds/parameters, and domain evidence in the original space. UMAP axes, island areas, and gaps between clusters have no calibrated physical or probabilistic meaning. Keep predictive test data outside preprocessing and embedding fits.

Raw lines 15 to 20
21## Quick Start
23### Installation
25Verified on 2026-10-01: **umap-learn 0.5.12** is the current stable release (April 2026). Requires Python 3.9+ and depends on `scikit-learn>=1.6`, `numba`, `pynndescent`, `numpy`, and `scipy`. Pin to a verified release:
27```bash
28uv pip install umap-learn==0.5.12
29```

Installation

Verified on 2026-10-01: umap-learn 0.5.12 is the current stable release (April 2026). Requires Python 3.9+ and depends on scikit-learn>=1.6, numba, pynndescent, numpy, and scipy. Pin to a verified release:

uv pip install umap-learn==0.5.12
Raw lines 23 to 30
31### Basic Usage
33UMAP uses the scikit-learn estimator interface, but its geometry and supervised behavior differ from PCA and t-SNE. Core examples were exercised on small synthetic data with Python 3.13, scikit-learn 1.9.1, NumPy 2.5.3, and Numba 0.68.0. Parametric examples are source-checked illustrations, not executed TensorFlow tests. In snippets below, `data` is a finite samples-by-features array and labels must follow the same row order.
35```python
36import umap
37from sklearn.preprocessing import StandardScaler
39# Scale continuous features when their units should carry equal weight
40scaled_data = StandardScaler().fit_transform(data)
42# Method 1: Single step (fit and transform)
43embedding = umap.UMAP(random_state=42, n_jobs=1).fit_transform(scaled_data)
45# Method 2: Separate steps (for reusing trained model)
46reducer = umap.UMAP(random_state=42)
47reducer.fit(scaled_data)
48embedding = reducer.embedding_ # Access the trained embedding
49```
51**Preprocessing requirement:** Match preprocessing to the metric. For numeric Euclidean-style metrics, decide whether scaling is scientifically appropriate; it changes the feature weighting. Fit preprocessing on training data only for predictive work. Use `StandardScaler(with_mean=False)` for sparse matrices to avoid densifying them. For cosine, binary, precomputed-distance, or mixed-feature workflows, choose preprocessing that matches the metric instead of blindly standardizing every column.

Basic Usage

UMAP uses the scikit-learn estimator interface, but its geometry and supervised behavior differ from PCA and t-SNE. Core examples were exercised on small synthetic data with Python 3.13, scikit-learn 1.9.1, NumPy 2.5.3, and Numba 0.68.0. Parametric examples are source-checked illustrations, not executed TensorFlow tests. In snippets below, data is a finite samples-by-features array and labels must follow the same row order.

import umap
from sklearn.preprocessing import StandardScaler

# Scale continuous features when their units should carry equal weight
scaled_data = StandardScaler().fit_transform(data)

# Method 1: Single step (fit and transform)
embedding = umap.UMAP(random_state=42, n_jobs=1).fit_transform(scaled_data)

# Method 2: Separate steps (for reusing trained model)
reducer = umap.UMAP(random_state=42)
reducer.fit(scaled_data)
embedding = reducer.embedding_  # Access the trained embedding

Preprocessing requirement: Match preprocessing to the metric. For numeric Euclidean-style metrics, decide whether scaling is scientifically appropriate; it changes the feature weighting. Fit preprocessing on training data only for predictive work. Use StandardScaler(with_mean=False) for sparse matrices to avoid densifying them. For cosine, binary, precomputed-distance, or mixed-feature workflows, choose preprocessing that matches the metric instead of blindly standardizing every column.

Raw lines 31 to 52
53### Typical Workflow
55```python
56import umap
57import matplotlib.pyplot as plt
58from sklearn.preprocessing import StandardScaler
60# 1. Preprocess data
61scaler = StandardScaler()
62scaled_data = scaler.fit_transform(raw_data)
64# 2. Create and fit UMAP
65reducer = umap.UMAP(
66 n_neighbors=15,
67 min_dist=0.1,
68 n_components=2,
69 metric='euclidean',
70 random_state=42
72embedding = reducer.fit_transform(scaled_data)
74# 3. Visualize
75plt.scatter(embedding[:, 0], embedding[:, 1], c=labels, cmap='Spectral', s=5)
76plt.colorbar()
77plt.title('UMAP Embedding')
78plt.show()
79```

Typical Workflow

import umap
import matplotlib.pyplot as plt
from sklearn.preprocessing import StandardScaler

# 1. Preprocess data
scaler = StandardScaler()
scaled_data = scaler.fit_transform(raw_data)

# 2. Create and fit UMAP
reducer = umap.UMAP(
    n_neighbors=15,
    min_dist=0.1,
    n_components=2,
    metric='euclidean',
    random_state=42
)
embedding = reducer.fit_transform(scaled_data)

# 3. Visualize
plt.scatter(embedding[:, 0], embedding[:, 1], c=labels, cmap='Spectral', s=5)
plt.colorbar()
plt.title('UMAP Embedding')
plt.show()
Raw lines 53 to 80
81## Parameter Tuning Guide
83UMAP has four primary parameters that control the embedding behavior. Understanding these is crucial for effective usage.

Parameter Tuning Guide

UMAP has four primary parameters that control the embedding behavior. Understanding these is crucial for effective usage.

Raw lines 81 to 84
85### n_neighbors (default: 15)
87**Purpose:** Balances local versus global structure in the embedding.
89**How it works:** Controls the size of the local neighborhood UMAP examines when learning manifold structure.
91**Effects by value:**
92- **Low values (2-5):** Emphasizes fine local detail but may fragment data into disconnected components
93- **Medium values (15-20):** Balanced view of both local structure and global relationships (recommended starting point)
94- **High values (50-200):** Prioritizes broad topological structure at the expense of fine-grained details
96**Recommendation:** Start with 15, keep it below the number of fitted samples, and compare several values. Larger neighborhoods do not make inter-cluster distances quantitatively reliable.

n_neighbors (default: 15)

Purpose: Balances local versus global structure in the embedding.

How it works: Controls the size of the local neighborhood UMAP examines when learning manifold structure.

Effects by value:

  • Low values (2-5): Emphasizes fine local detail but may fragment data into disconnected components
  • Medium values (15-20): Balanced view of both local structure and global relationships (recommended starting point)
  • High values (50-200): Prioritizes broad topological structure at the expense of fine-grained details

Recommendation: Start with 15, keep it below the number of fitted samples, and compare several values. Larger neighborhoods do not make inter-cluster distances quantitatively reliable.

Raw lines 85 to 97
98### min_dist (default: 0.1)
100**Purpose:** Controls how tightly points cluster in the low-dimensional space.
102**How it works:** Adjusts the attraction curve and typical packing in the embedding; it is not a hard lower bound on pairwise distances. Require `0 <= min_dist <= spread`.
104**Effects by value:**
105- **Low values (0.0-0.1):** Creates clumped embeddings useful for clustering; reveals fine topological details
106- **High values (0.5-0.99):** Encourages looser packing; does not certify preservation of global distances
108**Recommendation:** Use 0.0 for clustering applications, 0.1-0.3 for visualization, 0.5+ for loose structure.

min_dist (default: 0.1)

Purpose: Controls how tightly points cluster in the low-dimensional space.

How it works: Adjusts the attraction curve and typical packing in the embedding; it is not a hard lower bound on pairwise distances. Require 0 <= min_dist <= spread.

Effects by value:

  • Low values (0.0-0.1): Creates clumped embeddings useful for clustering; reveals fine topological details
  • High values (0.5-0.99): Encourages looser packing; does not certify preservation of global distances

Recommendation: Use 0.0 for clustering applications, 0.1-0.3 for visualization, 0.5+ for loose structure.

Raw lines 98 to 109
110### n_components (default: 2)
112**Purpose:** Determines the dimensionality of the embedded output space.
114**Key feature:** Unlike t-SNE, UMAP scales well in the embedding dimension, enabling use beyond visualization.
116**Common uses:**
117- **2-3 dimensions:** Visualization
118- **5-10 dimensions:** Clustering preprocessing (may retain more useful structure than 2D; does not guarantee density preservation)
119- **10-50 dimensions:** Feature engineering for downstream ML models
121**Recommendation:** Use 2 for visualization, 5-10 for clustering, higher for ML pipelines.

n_components (default: 2)

Purpose: Determines the dimensionality of the embedded output space.

Key feature: Unlike t-SNE, UMAP scales well in the embedding dimension, enabling use beyond visualization.

Common uses:

  • 2-3 dimensions: Visualization
  • 5-10 dimensions: Clustering preprocessing (may retain more useful structure than 2D; does not guarantee density preservation)
  • 10-50 dimensions: Feature engineering for downstream ML models

Recommendation: Use 2 for visualization, 5-10 for clustering, higher for ML pipelines.

Raw lines 110 to 122
123### metric (default: 'euclidean')
125**Purpose:** Specifies how distance is calculated between input data points.
127**Supported metrics:**
128- **Minkowski variants:** euclidean, manhattan, chebyshev
129- **Spatial metrics:** canberra, braycurtis, haversine
130- **Correlation metrics:** cosine, correlation (good for text/document embeddings)
131- **Binary data metrics:** hamming, jaccard, dice, russellrao, kulsinski, rogerstanimoto, sokalmichener, sokalsneath, yule
132- **Custom metrics:** User-defined distance functions via Numba
134**Recommendation:** Use euclidean for numeric data, cosine for text/document vectors, hamming for binary data.

metric (default: 'euclidean')

Purpose: Specifies how distance is calculated between input data points.

Supported metrics:

  • Minkowski variants: euclidean, manhattan, chebyshev
  • Spatial metrics: canberra, braycurtis, haversine
  • Correlation metrics: cosine, correlation (good for text/document embeddings)
  • Binary data metrics: hamming, jaccard, dice, russellrao, kulsinski, rogerstanimoto, sokalmichener, sokalsneath, yule
  • Custom metrics: User-defined distance functions via Numba

Recommendation: Use euclidean for numeric data, cosine for text/document vectors, hamming for binary data.

Raw lines 123 to 135
136### Parameter Tuning Example
138```python
139# For visualization with emphasis on local structure
140umap.UMAP(n_neighbors=15, min_dist=0.1, n_components=2, metric='euclidean')
142# For clustering preprocessing
143umap.UMAP(n_neighbors=30, min_dist=0.0, n_components=10, metric='euclidean')
145# For document embeddings
146umap.UMAP(n_neighbors=15, min_dist=0.1, n_components=2, metric='cosine')
148# For emphasizing broader neighborhoods
149umap.UMAP(n_neighbors=100, min_dist=0.5, n_components=2, metric='euclidean')
150```

Parameter Tuning Example

# For visualization with emphasis on local structure
umap.UMAP(n_neighbors=15, min_dist=0.1, n_components=2, metric='euclidean')

# For clustering preprocessing
umap.UMAP(n_neighbors=30, min_dist=0.0, n_components=10, metric='euclidean')

# For document embeddings
umap.UMAP(n_neighbors=15, min_dist=0.1, n_components=2, metric='cosine')

# For emphasizing broader neighborhoods
umap.UMAP(n_neighbors=100, min_dist=0.5, n_components=2, metric='euclidean')
Raw lines 136 to 151
152## Supervised and Semi-Supervised Dimension Reduction
154UMAP supports incorporating label information to guide the embedding process, encouraging class separation while retaining parts of the feature-neighborhood graph.

Supervised and Semi-Supervised Dimension Reduction

UMAP supports incorporating label information to guide the embedding process, encouraging class separation while retaining parts of the feature-neighborhood graph.

Raw lines 152 to 155
156### Supervised UMAP
158Pass target labels via the `y` parameter when fitting:
160```python
161# Supervised dimension reduction
162embedding = umap.UMAP().fit_transform(data, y=labels)
163```
165**Interpretation:** Label-guided separation is part of the objective, not independent evidence of discovered classes. Tune using training folds and evaluate on held-out samples. To obtain an unsupervised fit, omit `y`; `target_weight=0` with categorical labels still modifies graph edges in 0.5.12.

Supervised UMAP

Pass target labels via the y parameter when fitting:

# Supervised dimension reduction
embedding = umap.UMAP().fit_transform(data, y=labels)

Interpretation: Label-guided separation is part of the objective, not independent evidence of discovered classes. Tune using training folds and evaluate on held-out samples. To obtain an unsupervised fit, omit y; target_weight=0 with categorical labels still modifies graph edges in 0.5.12.

Raw lines 156 to 166
167### Semi-Supervised UMAP
169For `target_metric="categorical"`, encode known classes as nonnegative integers and unlabeled points as `-1`. This sentinel does not extend to arbitrary regression targets:
171```python
172# Create semi-supervised labels
173semi_labels = labels.copy()
174semi_labels[unlabeled_indices] = -1
176# Fit with partial labels
177embedding = umap.UMAP().fit_transform(data, y=semi_labels)
178```
180**When to use:** When labeling is expensive or you have more data than labels available.

Semi-Supervised UMAP

For target_metric="categorical", encode known classes as nonnegative integers and unlabeled points as -1. This sentinel does not extend to arbitrary regression targets:

# Create semi-supervised labels
semi_labels = labels.copy()
semi_labels[unlabeled_indices] = -1

# Fit with partial labels
embedding = umap.UMAP().fit_transform(data, y=semi_labels)

When to use: When labeling is expensive or you have more data than labels available.

Raw lines 167 to 181
182## UMAP for Clustering
184UMAP can help HDBSCAN on high-dimensional data, but reduction can create or erase clusters. Compare against clustering in the original or PCA space.

UMAP for Clustering

UMAP can help HDBSCAN on high-dimensional data, but reduction can create or erase clusters. Compare against clustering in the original or PCA space.

Raw lines 182 to 185
186### Best Practices for Clustering
188**Key principle:** Configure UMAP differently for clustering than for visualization.
190**Starting candidates, to validate on the actual data:**
191- **n_neighbors:** Compare 15, 30, and larger valid values; there is no universally correct neighborhood size
192- **min_dist:** Set to 0.0 (pack points densely within clusters for clearer boundaries)
193- **n_components:** Try 5-10 dimensions and compare cluster stability; standard UMAP does not preserve density

Best Practices for Clustering

Key principle: Configure UMAP differently for clustering than for visualization.

Starting candidates, to validate on the actual data:

  • n_neighbors: Compare 15, 30, and larger valid values; there is no universally correct neighborhood size
  • min_dist: Set to 0.0 (pack points densely within clusters for clearer boundaries)
  • n_components: Try 5-10 dimensions and compare cluster stability; standard UMAP does not preserve density
Raw lines 186 to 194
195### Clustering Workflow
197Install HDBSCAN separately for density-based clustering:
199```bash
200uv pip install hdbscan==0.8.44
201```
203```python
204import umap
205import hdbscan
206from sklearn.preprocessing import StandardScaler
208# 1. Preprocess data
209scaled_data = StandardScaler().fit_transform(data)
211# 2. Candidate UMAP settings for clustering
212reducer = umap.UMAP(
213 n_neighbors=30,
214 min_dist=0.0,
215 n_components=10, # Evaluate stability against other dimensions
216 metric='euclidean',
217 random_state=42
219embedding = reducer.fit_transform(scaled_data)
221# 3. Apply HDBSCAN clustering
222clusterer = hdbscan.HDBSCAN(
223 min_cluster_size=15,
224 min_samples=5,
225 metric='euclidean'
227labels = clusterer.fit_predict(embedding)
229# 4. Evaluate
230from sklearn.metrics import adjusted_rand_score
231# Only when independently known labels are available; ARI here includes noise as -1.
232score = adjusted_rand_score(true_labels, labels)
233print(f"Adjusted Rand Score: {score:.3f}")
234print(f"Number of clusters: {len(set(labels)) - (1 if -1 in labels else 0)}")
235print(f"Noise points: {sum(labels == -1)}")
236```

Clustering Workflow

Install HDBSCAN separately for density-based clustering:

uv pip install hdbscan==0.8.44
import umap
import hdbscan
from sklearn.preprocessing import StandardScaler

# 1. Preprocess data
scaled_data = StandardScaler().fit_transform(data)

# 2. Candidate UMAP settings for clustering
reducer = umap.UMAP(
    n_neighbors=30,
    min_dist=0.0,
    n_components=10,  # Evaluate stability against other dimensions
    metric='euclidean',
    random_state=42
)
embedding = reducer.fit_transform(scaled_data)

# 3. Apply HDBSCAN clustering
clusterer = hdbscan.HDBSCAN(
    min_cluster_size=15,
    min_samples=5,
    metric='euclidean'
)
labels = clusterer.fit_predict(embedding)

# 4. Evaluate
from sklearn.metrics import adjusted_rand_score
# Only when independently known labels are available; ARI here includes noise as -1.
score = adjusted_rand_score(true_labels, labels)
print(f"Adjusted Rand Score: {score:.3f}")
print(f"Number of clusters: {len(set(labels)) - (1 if -1 in labels else 0)}")
print(f"Noise points: {sum(labels == -1)}")
Raw lines 195 to 237
238### Visualization After Clustering
240```python
241# Create 2D embedding for visualization (separate from clustering)
242vis_reducer = umap.UMAP(n_neighbors=15, min_dist=0.1, n_components=2, random_state=42)
243vis_embedding = vis_reducer.fit_transform(scaled_data)
245# Plot with cluster labels
246import matplotlib.pyplot as plt
247plt.scatter(vis_embedding[:, 0], vis_embedding[:, 1], c=labels, cmap='Spectral', s=5)
248plt.colorbar()
249plt.title('UMAP Visualization with HDBSCAN Clusters')
250plt.show()
251```
253**Validation:** Report noise fraction and clusters found across seeds and parameter choices. Check cluster membership and domain evidence in the original feature space. A silhouette score computed only in the optimized embedding can be misleading. No cluster or all-noise output is a possible result, not a reason to tune until attractive islands appear.

Visualization After Clustering

# Create 2D embedding for visualization (separate from clustering)
vis_reducer = umap.UMAP(n_neighbors=15, min_dist=0.1, n_components=2, random_state=42)
vis_embedding = vis_reducer.fit_transform(scaled_data)

# Plot with cluster labels
import matplotlib.pyplot as plt
plt.scatter(vis_embedding[:, 0], vis_embedding[:, 1], c=labels, cmap='Spectral', s=5)
plt.colorbar()
plt.title('UMAP Visualization with HDBSCAN Clusters')
plt.show()

Validation: Report noise fraction and clusters found across seeds and parameter choices. Check cluster membership and domain evidence in the original feature space. A silhouette score computed only in the optimized embedding can be misleading. No cluster or all-noise output is a possible result, not a reason to tune until attractive islands appear.

Raw lines 238 to 254
255## Transforming New Data
257UMAP enables preprocessing of new data through its `transform()` method, allowing trained models to project unseen data into the learned embedding space.

Transforming New Data

UMAP enables preprocessing of new data through its transform() method, allowing trained models to project unseen data into the learned embedding space.

Raw lines 255 to 258
259### Basic Transform Usage
261```python
262# Train on training data
263trans = umap.UMAP(n_neighbors=15, random_state=42).fit(X_train)
265# Transform test data
266test_embedding = trans.transform(X_test)
267```

Basic Transform Usage

# Train on training data
trans = umap.UMAP(n_neighbors=15, random_state=42).fit(X_train)

# Transform test data
test_embedding = trans.transform(X_test)
Raw lines 259 to 268
269### Integration with Machine Learning Pipelines
271```python
272from sklearn.svm import SVC
273from sklearn.model_selection import train_test_split
274from sklearn.preprocessing import StandardScaler
275import umap
277# Split data
278X_train, X_test, y_train, y_test = train_test_split(
279 data, labels, test_size=0.2, random_state=42, stratify=labels
282# Preprocess
283scaler = StandardScaler()
284X_train_scaled = scaler.fit_transform(X_train)
285X_test_scaled = scaler.transform(X_test)
287# Train UMAP
288reducer = umap.UMAP(n_components=10, random_state=42)
289X_train_embedded = reducer.fit_transform(X_train_scaled)
290X_test_embedded = reducer.transform(X_test_scaled)
292# Train classifier on embeddings
293clf = SVC()
294clf.fit(X_train_embedded, y_train)
295accuracy = clf.score(X_test_embedded, y_test)
296print(f"Test accuracy: {accuracy:.3f}")
297```

Integration with Machine Learning Pipelines

from sklearn.svm import SVC
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
import umap

# Split data
X_train, X_test, y_train, y_test = train_test_split(
    data, labels, test_size=0.2, random_state=42, stratify=labels
)

# Preprocess
scaler = StandardScaler()
X_train_scaled = scaler.fit_transform(X_train)
X_test_scaled = scaler.transform(X_test)

# Train UMAP
reducer = umap.UMAP(n_components=10, random_state=42)
X_train_embedded = reducer.fit_transform(X_train_scaled)
X_test_embedded = reducer.transform(X_test_scaled)

# Train classifier on embeddings
clf = SVC()
clf.fit(X_train_embedded, y_train)
accuracy = clf.score(X_test_embedded, y_test)
print(f"Test accuracy: {accuracy:.3f}")
Raw lines 269 to 298
299### Important Considerations
301**Data consistency:** Validate transforms on held-out data representative of deployment. Inspect out-of-distribution inputs and neighborhood support before interpreting their locations; neither standard nor Parametric UMAP guarantees meaningful extrapolation under distribution shift. Retraining on representative data requires a new downstream validation.
303**Performance:** Measure fit and transform with your sample size and metric; first calls include Numba compilation. There is no fixed latency guarantee. Standard `transform` preserves the trained coordinate system; `update` refits with added samples and can move existing points.
305**Scikit-learn compatibility:** `Pipeline.fit(X, y)` forwards `y` to UMAP, so the following is a **supervised** UMAP pipeline. Keep the whole pipeline inside cross-validation; fitting the embedding once before cross-validation leaks information. The manual example above deliberately fits UMAP without labels:
307```python
308from sklearn.pipeline import Pipeline
310pipeline = Pipeline([
311 ('scaler', StandardScaler()),
312 ('umap', umap.UMAP(n_components=10, random_state=42, n_jobs=1)),
313 ('classifier', SVC())
314])
316pipeline.fit(X_train, y_train)
317predictions = pipeline.predict(X_test)
318feature_names = pipeline.named_steps['umap'].get_feature_names_out()
319```

Important Considerations

Data consistency: Validate transforms on held-out data representative of deployment. Inspect out-of-distribution inputs and neighborhood support before interpreting their locations; neither standard nor Parametric UMAP guarantees meaningful extrapolation under distribution shift. Retraining on representative data requires a new downstream validation.

Performance: Measure fit and transform with your sample size and metric; first calls include Numba compilation. There is no fixed latency guarantee. Standard transform preserves the trained coordinate system; update refits with added samples and can move existing points.

Scikit-learn compatibility: Pipeline.fit(X, y) forwards y to UMAP, so the following is a supervised UMAP pipeline. Keep the whole pipeline inside cross-validation; fitting the embedding once before cross-validation leaks information. The manual example above deliberately fits UMAP without labels:

from sklearn.pipeline import Pipeline

pipeline = Pipeline([
    ('scaler', StandardScaler()),
    ('umap', umap.UMAP(n_components=10, random_state=42, n_jobs=1)),
    ('classifier', SVC())
])

pipeline.fit(X_train, y_train)
predictions = pipeline.predict(X_test)
feature_names = pipeline.named_steps['umap'].get_feature_names_out()
Raw lines 299 to 320
321## Advanced Features

Advanced Features

Raw lines 321 to 322
323### densMAP
325Use `UMAP(densmap=True, output_dens=True)` when local density is part of the question.
326`fit_transform` then returns `(embedding, rad_orig, rad_emb)`: the radii are
327log-transformed local-radius estimates, not probabilities or raw density values.
328`dens_frac=0.3` applies the density objective during the final 30% of optimization
329epochs, not to 30% of samples. densMAP supports Euclidean output and cannot transform
330unseen data or use `inverse_transform` in 0.5.12. See the reference for a runnable recipe.

densMAP

Use UMAP(densmap=True, output_dens=True) when local density is part of the question. fit_transform then returns (embedding, rad_orig, rad_emb): the radii are log-transformed local-radius estimates, not probabilities or raw density values. dens_frac=0.3 applies the density objective during the final 30% of optimization epochs, not to 30% of samples. densMAP supports Euclidean output and cannot transform unseen data or use inverse_transform in 0.5.12. See the reference for a runnable recipe.

Raw lines 323 to 331
332### Parametric UMAP
334Parametric UMAP replaces direct embedding optimization with a learned neural network mapping function.
336**Key differences from standard UMAP:**
337- Uses TensorFlow/Keras to train encoder networks
338- Enables efficient transformation of new data
339- Supports reconstruction via decoder networks (inverse transform)
340- Allows custom architectures (CNNs for images, RNNs for sequences)
342**Installation:**
343```bash
344uv pip install "umap-learn[parametric-umap]==0.5.12"
345# The released source also requires Keras >=3; verify the resolved TensorFlow/Keras pair.
346```
348**Illustrative basic usage (TensorFlow runtime not exercised):**
349```python
350from umap.parametric_umap import ParametricUMAP
352# Default architecture (3-layer 100-neuron fully-connected network)
353embedder = ParametricUMAP()
354embedding = embedder.fit_transform(data)
356# Transform new data efficiently
357new_embedding = embedder.transform(new_data)
358```
360**Custom architecture:**
361```python
362import tensorflow as tf
364# Define custom encoder
365encoder = tf.keras.Sequential([
366 tf.keras.layers.InputLayer(shape=(input_dim,)),
367 tf.keras.layers.Dense(128, activation='relu'),
368 tf.keras.layers.Dense(64, activation='relu'),
369 tf.keras.layers.Dense(2) # Output dimension
370])
372embedder = ParametricUMAP(encoder=encoder, dims=(input_dim,))
373embedding = embedder.fit_transform(data)
374```
376**Persistence:** Save Parametric UMAP with its built-in Keras-aware methods rather than plain pickle:
378```python
379from pathlib import Path
380Path("parametric_umap_model").mkdir(exist_ok=True)
381embedder.save("parametric_umap_model", exclude_raw_data=True)
383from umap.parametric_umap import load_ParametricUMAP
384loaded = load_ParametricUMAP("parametric_umap_model")
385new_embedding = loaded.transform(new_data)
386```
388Only load trusted model directories: loading reads a pickle. Verify transformed outputs after saving/loading. In 0.5.12, `save` writes `parametric_model.keras` while the loader checks `parametric_model`; do not assume full training-state restoration. `exclude_raw_data=True` is not a privacy/anonymization guarantee. The [released source](https://github.com/lmcinnes/umap/blob/release-0.5.12/umap/parametric_umap.py) is authoritative where hosted examples differ.
390**When to use Parametric UMAP:**
391- Need efficient transformation of new data after training
392- Require reconstruction capabilities (inverse transforms)
393- Want to combine UMAP with autoencoders
394- Working with complex data types (images, sequences) benefiting from specialized architectures

Parametric UMAP

Parametric UMAP replaces direct embedding optimization with a learned neural network mapping function.

Key differences from standard UMAP:

  • Uses TensorFlow/Keras to train encoder networks
  • Enables efficient transformation of new data
  • Supports reconstruction via decoder networks (inverse transform)
  • Allows custom architectures (CNNs for images, RNNs for sequences)

Installation:

uv pip install "umap-learn[parametric-umap]==0.5.12"
# The released source also requires Keras >=3; verify the resolved TensorFlow/Keras pair.

Illustrative basic usage (TensorFlow runtime not exercised):

from umap.parametric_umap import ParametricUMAP

# Default architecture (3-layer 100-neuron fully-connected network)
embedder = ParametricUMAP()
embedding = embedder.fit_transform(data)

# Transform new data efficiently
new_embedding = embedder.transform(new_data)

Custom architecture:

import tensorflow as tf

# Define custom encoder
encoder = tf.keras.Sequential([
    tf.keras.layers.InputLayer(shape=(input_dim,)),
    tf.keras.layers.Dense(128, activation='relu'),
    tf.keras.layers.Dense(64, activation='relu'),
    tf.keras.layers.Dense(2)  # Output dimension
])

embedder = ParametricUMAP(encoder=encoder, dims=(input_dim,))
embedding = embedder.fit_transform(data)

Persistence: Save Parametric UMAP with its built-in Keras-aware methods rather than plain pickle:

from pathlib import Path
Path("parametric_umap_model").mkdir(exist_ok=True)
embedder.save("parametric_umap_model", exclude_raw_data=True)

from umap.parametric_umap import load_ParametricUMAP
loaded = load_ParametricUMAP("parametric_umap_model")
new_embedding = loaded.transform(new_data)

Only load trusted model directories: loading reads a pickle. Verify transformed outputs after saving/loading. In 0.5.12, save writes parametric_model.keras while the loader checks parametric_model; do not assume full training-state restoration. exclude_raw_data=True is not a privacy/anonymization guarantee. The released source is authoritative where hosted examples differ.

When to use Parametric UMAP:

  • Need efficient transformation of new data after training
  • Require reconstruction capabilities (inverse transforms)
  • Want to combine UMAP with autoencoders
  • Working with complex data types (images, sequences) benefiting from specialized architectures
Raw lines 332 to 395
396### Inverse Transforms
398Inverse transforms enable reconstruction of high-dimensional data from low-dimensional embeddings.
400**Basic usage:**
401```python
402reducer = umap.UMAP()
403embedding = reducer.fit_transform(data)
405# Reconstruct high-dimensional data from embedding coordinates
406reconstructed = reducer.inverse_transform(embedding)
407```
409**Important limitations:**
410- Approximate reconstruction, not a bijective inverse or evidence that a generated sample is plausible
411- Unsupported for sparse training data, precomputed or gradient-free metrics, densMAP, and graph mode
412- Computationally expensive; poor support outside the training embedding or between disconnected clusters
414Explore inverse coordinates only where the training embedding supports them; rectangular grids often cross unsupported gaps. Check domain constraints on every generated reconstruction.

Inverse Transforms

Inverse transforms enable reconstruction of high-dimensional data from low-dimensional embeddings.

Basic usage:

reducer = umap.UMAP()
embedding = reducer.fit_transform(data)

# Reconstruct high-dimensional data from embedding coordinates
reconstructed = reducer.inverse_transform(embedding)

Important limitations:

  • Approximate reconstruction, not a bijective inverse or evidence that a generated sample is plausible
  • Unsupported for sparse training data, precomputed or gradient-free metrics, densMAP, and graph mode
  • Computationally expensive; poor support outside the training embedding or between disconnected clusters

Explore inverse coordinates only where the training embedding supports them; rectangular grids often cross unsupported gaps. Check domain constraints on every generated reconstruction.

Raw lines 396 to 415
416### AlignedUMAP
418For temporal or related datasets that need a shared coordinate system (time-series
419experiments, batches), use `umap.AlignedUMAP().fit(datasets, relations=relations)`, where
420`relations` maps sample indices between consecutive datasets and is required for meaningful
421alignment. Parameters, methods, and a worked example are in `references/api_reference.md`
422under "AlignedUMAP Class" and "Usage Examples".

AlignedUMAP

For temporal or related datasets that need a shared coordinate system (time-series experiments, batches), use umap.AlignedUMAP().fit(datasets, relations=relations), where relations maps sample indices between consecutive datasets and is required for meaningful alignment. Parameters, methods, and a worked example are in references/api_reference.md under "AlignedUMAP Class" and "Usage Examples".

Raw lines 416 to 423
Reads a file references/api_reference.md :421
424## Reproducibility
426For reproducibility in the same software/hardware environment, set `random_state` and retain the data order, preprocessing, package versions, and parameters:
428```python
429reducer = umap.UMAP(random_state=42)
430```
432UMAP is stochastic; unseeded runs can differ substantially. Compare neighborhood or cluster stability rather than unaligned coordinates, which can rotate or reflect.
434In standard UMAP, setting `random_state` forces `n_jobs=1`. `transform_seed` separately controls transform randomness. Exact cross-version or GPU/CPU equivalence is not promised. Leave it unset when throughput matters more than exact repeatability, because UMAP can use more parallelism without a fixed seed.

Reproducibility

For reproducibility in the same software/hardware environment, set random_state and retain the data order, preprocessing, package versions, and parameters:

reducer = umap.UMAP(random_state=42)

UMAP is stochastic; unseeded runs can differ substantially. Compare neighborhood or cluster stability rather than unaligned coordinates, which can rotate or reflect.

In standard UMAP, setting random_state forces n_jobs=1. transform_seed separately controls transform randomness. Exact cross-version or GPU/CPU equivalence is not promised. Leave it unset when throughput matters more than exact repeatability, because UMAP can use more parallelism without a fixed seed.

Raw lines 424 to 435
436## Common Issues and Solutions
438**Issue:** Disconnected components or fragmented clusters
439- **Solution:** Inspect graph connected components, duplicates, metric support and outliers before increasing `n_neighbors`. Fully disconnected vertices can receive NaN coordinates; do not silently drop them from the analysis.
441**Issue:** Clusters too spread out or not well separated
442- **Solution:** Compare several `min_dist` values; visual separation is not a scientific validation criterion
444**Issue:** Poor clustering results
445- **Solution:** Compare neighborhood sizes/dimensions, noise fractions, multiple seeds, and a baseline without UMAP
447**Issue:** Transform results differ significantly from training
448- **Solution:** Check preprocessing and distribution shift; validate neighborhood support and downstream performance before reusing either UMAP variant.
450**Issue:** Slow performance on large datasets
451- **Solution:** Profile neighbor search versus optimization. `low_memory=True` reduces memory use, not necessarily runtime; consider PCA or sparse TruncatedSVD only when their information loss is acceptable
453**Issue:** NaN or inf values in input data
454- **Solution:** Impute or drop invalid rows before fitting. Current UMAP uses scikit-learn-style finite-value checks (`ensure_all_finite`) in `fit()` and `update()`, so clean numeric input is the safest default
456**Issue:** All points collapsed to single cluster
457- **Solution:** Check constant/duplicate features, the distance metric and preprocessing; compare multiple settings without assuming multiple true clusters exist
459**Issue:** Imports resolve to a local file instead of the real package
460- **Solution:** Do not keep project files named `umap.py`, `sklearn.py`, `hdbscan.py`, or `tensorflow.py` beside notebooks or scripts. Those names can shadow installed packages and break or poison examples.

Common Issues and Solutions

Issue: Disconnected components or fragmented clusters

  • Solution: Inspect graph connected components, duplicates, metric support and outliers before increasing n_neighbors. Fully disconnected vertices can receive NaN coordinates; do not silently drop them from the analysis.

Issue: Clusters too spread out or not well separated

  • Solution: Compare several min_dist values; visual separation is not a scientific validation criterion

Issue: Poor clustering results

  • Solution: Compare neighborhood sizes/dimensions, noise fractions, multiple seeds, and a baseline without UMAP

Issue: Transform results differ significantly from training

  • Solution: Check preprocessing and distribution shift; validate neighborhood support and downstream performance before reusing either UMAP variant.

Issue: Slow performance on large datasets

  • Solution: Profile neighbor search versus optimization. low_memory=True reduces memory use, not necessarily runtime; consider PCA or sparse TruncatedSVD only when their information loss is acceptable

Issue: NaN or inf values in input data

  • Solution: Impute or drop invalid rows before fitting. Current UMAP uses scikit-learn-style finite-value checks (ensure_all_finite) in fit() and update(), so clean numeric input is the safest default

Issue: All points collapsed to single cluster

  • Solution: Check constant/duplicate features, the distance metric and preprocessing; compare multiple settings without assuming multiple true clusters exist

Issue: Imports resolve to a local file instead of the real package

  • Solution: Do not keep project files named umap.py, sklearn.py, hdbscan.py, or tensorflow.py beside notebooks or scripts. Those names can shadow installed packages and break or poison examples.
Raw lines 436 to 461
462## Resources
464### Official documentation
466- [UMAP user guide](https://umap-learn.readthedocs.io/en/latest/)
467- [0.5.12 release notes](https://github.com/lmcinnes/umap/releases/tag/release-0.5.12)
468- [PyPI package](https://pypi.org/project/umap-learn/) (current stable: 0.5.12)
469- [GitHub repository](https://github.com/lmcinnes/umap)
471### references/
473Contains detailed API documentation:
474- [api_reference.md](references/api_reference.md): Release-checked parameter contracts, return values, restrictions, and advanced recipes
476Load these references when detailed parameter information or advanced method usage is needed.

references/

Contains detailed API documentation:

  • api_reference.md: Release-checked parameter contracts, return values, restrictions, and advanced recipes

Load these references when detailed parameter information or advanced method usage is needed.

Raw lines 471 to 477
Reads a file references/api_reference.md :474
Boilerplate, lines 478 to 493. The same text appears in 125 other files here. Close
478## Citing Scientific Agent Skills
480This skill is part of Scientific Agent Skills by K-Dense. If it materially contributed to a
481manuscript, report, presentation, or code release, add the paper to the references or
482software section and tell the user you did so:
484> Kassis, T., Agarwal, V., He, Y., Patel, D., & Brueckner, A. M. (2026). Scientific Agent
485> Skills: A Library of Procedural Knowledge for Research Agents. arXiv:2609.00065.
486> https://doi.org/10.48550/arXiv.2609.00065
488Always cite the current version. The DOI and https://arxiv.org/abs/2609.00065 resolve to the
489latest arXiv version, so never append a version suffix such as `v1`. When network access is
490available, fetch https://arxiv.org/abs/2609.00065 (or
491http://export.arxiv.org/api/query?id_list=2609.00065) before writing the reference and take
492the author list, year, and version from that record. If the record lists a journal reference
493or publisher DOI, cite the published version instead.

From K-Dense-AI/scientific-agent-skills at 5f2bc03, 2026-10-26. Not read by a model yet. Summary and techniques by Claude Opus 5.5 on 2026-11-06.