Reciprocal Isomap
Reciprocal Isomap is a reciprocal variant of Isomap for robust non-linear dimensionality reduction in Python.
The ReciprocalIsomap
transformer was inspired by scikit-learn’s implementation of Isomap, but the reciprocal variant enforces shared connectivity in the underlying k-nearest neighbors graph (i.e., two points are only considered neighbors if each is a neighbor of the other).
Related Projects
- NeuMapper is a scalable Mapper algorithm for neuroimaging data analysis. The Matlab implementation was designed specifically for working with complex, high-dimensional neuroimaging data and produces a shape graph representation that can be annotated with meta-information and further examined using network science tools.
Setup
Dependencies
Python 3.6+
Required Python Packages
Install using pip
Assuming you have the required dependencies, you should be able to install using pip.
pip install git+https://github.com/calebgeniesse/reciprocal_isomap.git
Alternatively, you can also clone the repository and build from source.
git clone git@github.com:calebgeniesse/reciprocal_isomap.git
cd reciprocal_isomap
pip install -r requirements.txt
pip install -e .
Usage
The ReciprocalIsomap
object
Here, we will walk through a simple example using ReciprocalIsomap
.
import numpy as np
from reciprocal_isomap import ReciprocalIsomap
# generate some random data points.
X = np.random.random((100, 10))
# configure the ReciprocalIsomap object
r_isomap = ReciprocalIsomap(n_neighbors=8)
# fit and transform the data in a single step
embedding = r_isomap.fit_transform(X)
We can also fit the data, and then project points into the embedding.
# fit the data and then transform a subset of the data
embedding = r_isomap.fit(X).transform(X[1::2])
Similarly, we can project new unseen data points into the embedding.
# fit a subset of the data and then transform the other half of the data
embedding = r_isomap.fit(X[0::2]).transform(X[1::2])
Comparison with Isomap
Here, we compare embeddings created using Isomap
and ReciprocalIsomap
across several values of the n_neighbors
parameter.
First, let’s plot the embeddings from Isomap
.
from sklearn.manifold import Isomap
import matplotlib.pyplot as plt
try_n_neighbors = [3, 4, 5, 6]
fig, axes = plt.subplots(1, 4, figsize=(24, 5))
for i,n_neighbors in enumerate(try_n_neighbors):
isomap = Isomap(n_neighbors=n_neighbors)
embedding = isomap.fit_transform(X)
axes[i].scatter(embedding[:,0], embedding[:,1], c=y, cmap='Spectral_r')
axes[i].set_title(f"Isomap(n_neighbors={n_neighbors})", fontweight='bold')
Now, let’s plot the embeddings from ReciprocalIsomap
.
from reciprocal_isomap import ReciprocalIsomap
import matplotlib.pyplot as plt
try_n_neighbors = [3, 4, 5, 6]
fig, axes = plt.subplots(1, 4, figsize=(24, 5))
for i,n_neighbors in enumerate(try_n_neighbors):
r_isomap = ReciprocalIsomap(n_neighbors=n_neighbors)
embedding = r_isomap.fit_transform(X)
axes[i].scatter(embedding[:,0], embedding[:,1], c=y, cmap='Spectral_r')
axes[i].set_title(f"ReciprocalIsomap(n_neighbors={n_neighbors})", fontweight='bold')
Citation
If you find Reciprocal Isomap useful, please consider citing:
Geniesse, C., Chowdhury, S., & Saggar, M. (2022). NeuMapper: A Scalable Computational Framework for Multiscale Exploration of the Brain’s Dynamical Organization. Network Neuroscience, Advance publication. doi:10.1162/netn_a_00229