lmcinnes / lmcinnes/umap

Incorrect structure on random points for data with small variations. Lack of shuffling?

Open
#840 3 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
Python
Stars
8.3k
Forks
871
Avg merge
1d 13h
Merged PRs (30d)
5

Description

umap.__version__ == 0.4.6

In the following example, UMAP is applied to random data with tiny variations around a fixed value. Arbitrary labels are assigned to the data in order ('a' for the first 150 samples, 'b' to the next 150, etc.).

When applying UMAP, a structure appears (points with the same label are grouped), as shown in the image below, but it should not (random data).
This issue can potentially lead to incorrect interpretations.

It could be due to a kind of greedy behavior in the construction of the neighborhood graph.
Randomly shuffling the data before construction of the neighborhood graph solves the problem, but might not be an ideal fix.

import numpy as np
from umap import UMAP
import umap.plot

n_obs = 600
n_vars = 16
np.random.seed(42)

fixed_value = np.random.random(n_vars)
X = 10 * fixed_value + 1e-9 * np.random.random((n_obs, n_vars))
labels = np.array(['a'] * (n_obs // 4)
                  + ['b'] * (n_obs // 4)
                  + ['c'] * (n_obs // 4)
                  + ['d'] * (n_obs // 4))

reducer = UMAP(
    metric="cosine",
    min_dist=0.0,
    n_neighbors=10,
    random_state=0,
)
reducer.fit(X)
p = umap.plot.points(reducer, labels=labels, theme="fire")
umap.plot.show(p)

Screenshot from 2022-03-02 15-25-55

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by running the provided Python reproduction with UMAP 0.4.6 and inspect the neighborhood graph construction reached by reducer.fit(X). Compare the result with and without shuffling the near-constant data; done means the embedding no longer reflects the input label order for random data.

Written by the indexing model from the issue text.

Assessment

Tech stack
numpy, python
Domain
machine-learning
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Needs clarification
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.