lmcinnes / lmcinnes/umap

Contents of precomputed_knn tuple

Open
#848 4 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

I'm trying to feed to UMAP nearest neighbors computed with another method than pynndescent, and so I need to put the data in the format of precomputed_knn that UMAP accept: the tuple: (knn_indices, knn_distances, NNDescentObject)
Since I had trouble making an NNDescent object without giving it data, I tried giving it a fake NNDescent object, that returns true to isinstance(knn[2], NNDescent):

```python
import pynndescent
import numpy as np
import umap
import umap.plot
from umap.umap_ import nearest_neighbors
import matplotlib.pyplot as plt

n = 200
N = 3*n
y = np.random.rand(n, 60)
X = np.concatenate((y+20, y, y-20))
synthetic_labels = np.repeat([1, 2, 3], repeats=n)

random_seed = 10

knn = nearest_neighbors(
X,
n_neighbors=30,
metric='euclidean',
metric_kwds={},
angular=False,
random_state=random_seed,
)

knn_umap = umap.UMAP(n_neighbors=30, precomputed_knn=knn, random_state=random_seed, force_approximation_algorithm=True)
knn_umap.fit(X)

class MyNNDescent(pynndescent.NNDescent):
def __init__(self):
return

knn2 = (knn[0],knn[1],MyNNDescent())
knn_umap2 = umap.UMAP(n_neighbors=30, precomputed_knn=knn2, random_state=random_seed, force_approximation_algorithm=True)
knn_umap2.fit(X)

print("\033[1m"+"Are the embeddings for knn_umap and knn_umap2 the same?\033[0m")
print((knn_umap.embedding_ == knn_umap2.embedding_).all())

fig, ax = plt.subplots(1, 2, figsize=(13,7))
umap.plot.points(knn_umap, labels=synthetic_labels, ax=ax[0], theme='green')
umap.plot.points(knn_umap2, labels=synthetic_labels, ax=ax[1], theme='green')
ax[0].set_title("Precomputed knn 1st run", size=16)
ax[1].set_title("Precomputed knn 2nd run", size=16)
plt.show()
```

The result is that the 2 embeddings are the same, so it seems that the NNDescent object is not used at all.
Is my assumption correct, or is the object used in some particular cases, which would explain why it was included in the tuple?
I tried digging into the code, but I can't find the place where this object is used...

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 tracing the UMAP.UMAP precomputed_knn path and the nearest_neighbors entry point, then inspect where the tuple's NNDescent object is accessed. Done means documenting whether that object is used and identifying the cases, if any, in which it affects processing.

Written by the indexing model from the issue text.

Assessment

Tech stack
numpy, python
Domain
api, machine-learning
Issue type
Documentation
Difficulty
3/5
Estimated time
1-2 days
Activity status
Stale
Clarity
Needs clarification
Newbie friendliness
28/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.