Isomap construit une représentation de faible dimension en s’appuyant sur les chemins dans un graphe de voisinage. L’objectif est de mieux respecter certaines structures courbes qu’une projection linéaire. La qualité du résultat dépend toutefois du graphe : un voisinage mal choisi peut déconnecter les données ou créer des raccourcis.
Ce guide propose un exemple Python complet sur un Swiss roll synthétique, compare Isomap à PCA et vérifie les distances utilisées pour cette comparaison. Le dessin sert à explorer une structure ; il ne prouve pas l’existence de catégories métier.
Exécuté le 18 septembre 2026 avec Python 3.12.14, scikit-learn 1.9.1, SciPy 1.18.1 et NumPy 2.5.3.
Pourquoi une feuille enroulée est un bon exemple
Deux points situés sur des tours différents d’une feuille enroulée peuvent être proches dans l’espace, mais éloignés lorsqu’on suit sa surface. PCA cherche des directions linéaires ; elle n’a pas pour objectif de dérouler la feuille. Isomap tente d’estimer des distances le long de la structure à partir de voisinages locaux.
Cette intuition suppose que les points échantillonnent suffisamment bien une structure où les voisinages ont un sens. Sur un nuage très bruité, des régions peu échantillonnées ou plusieurs composantes séparées, cette hypothèse peut être mauvaise. Isomap ne découvre pas automatiquement la « vraie dimension » de n’importe quel tableau.
Les trois étapes de la méthode
- Construire un graphe : relier chaque point à ses voisins selon une métrique.
- Calculer des plus courts chemins : additionner les longueurs des liaisons pour approcher des distances le long de la structure.
- Construire la projection : rechercher des coordonnées de faible dimension représentant ces distances.
Le guide officiel sur les variétés décrit cette logique. La distance de graphe n’est qu’une approximation de la distance géométrique recherchée. Une liaison qui traverse deux tours du Swiss roll peut créer un raccourci et modifier beaucoup de distances à la fois.
Vérifier la connexité avant la projection
Nous construisons le même type de graphe de voisins que celui utilisé par Isomap, puis le symétrisons. Si le graphe a plusieurs composantes, certaines paires n’ont pas de chemin entre elles. Le script interrompt alors la projection, au lieu de laisser une réparation automatique passer inaperçue.
Augmenter le nombre de voisins peut reconnecter le graphe, mais ne garantit pas une meilleure géométrie. Il faut aussi vérifier les données, les régions isolées et le sens de la distance choisie. Dans certains problèmes, traiter les composantes séparément est plus cohérent que de les relier artificiellement.
Exemple Python : Swiss roll, Isomap et PCA
python -m pip install numpy==2.5.3 scipy==1.18.1 scikit-learn==1.9.1
Enregistrez le script dans exemple_isomap.py, puis lancez python exemple_isomap.py. Le jeu est créé localement ; les coordonnées sont conservées dans leur échelle commune.
"""Isomap : vérifier le graphe, projeter et comparer les mêmes paires."""
import numpy as np
from scipy.sparse.csgraph import connected_components
from scipy.spatial.distance import pdist
from scipy.stats import spearmanr
from sklearn.datasets import make_swiss_roll
from sklearn.decomposition import PCA
from sklearn.manifold import Isomap, trustworthiness
from sklearn.neighbors import kneighbors_graph
X, couleur = make_swiss_roll(n_samples=650, noise=0.05, random_state=42)
k = 10
graphe = kneighbors_graph(X, n_neighbors=k, mode="distance", include_self=False)
graphe = graphe.maximum(graphe.T)
composantes = connected_components(graphe, directed=False, return_labels=False)
if composantes != 1:
raise ValueError("Graphe déconnecté : revoir le voisinage avant Isomap.")
model = Isomap(n_neighbors=k, n_components=2, eigen_solver="arpack", n_jobs=1)
projection = model.fit_transform(X)
pca = PCA(n_components=2).fit_transform(X)
# pdist et triu_indices(k=1) décrivent les mêmes paires i < j, dans le même ordre.
paires = np.triu_indices(len(X), k=1)
distances_graphe = model.dist_matrix_[paires]
print("Composantes du graphe :", composantes)
print("Forme de la projection :", projection.shape)
for nom, resultat in [("PCA", pca), ("Isomap", projection)]:
rho = spearmanr(distances_graphe, pdist(resultat)).statistic
confiance = trustworthiness(X, resultat, n_neighbors=10)
print(f"{nom} : corrélation au graphe={rho:.3f} ; voisinages locaux={confiance:.3f}")
print("Connexité selon le nombre de voisins :")
for voisins in [2, 5, 10, 35]:
g = kneighbors_graph(X, n_neighbors=voisins, mode="distance", include_self=False)
nombre = connected_components(g.maximum(g.T), directed=False, return_labels=False)
print(f"k={voisins} : {nombre} composante(s)")
Sortie observée, arrondie à trois décimales :
Composantes du graphe : 1 Forme de la projection : (650, 2) PCA : corrélation au graphe=0.367 ; voisinages locaux=0.963 Isomap : corrélation au graphe=0.999 ; voisinages locaux=0.999 Connexité selon le nombre de voisins : k=2 : 34 composante(s) k=5 : 1 composante(s) k=10 : 1 composante(s) k=35 : 1 composante(s)

Comparer les mêmes paires de points
model.dist_matrix_ est une matrice carrée de distances de graphe. pdist renvoie seulement les distances des paires distinctes, une seule fois par paire. Comparer la matrice aplatie à ce vecteur serait incorrect : leurs tailles et leurs éléments ne correspondent pas.
Le code sélectionne le triangle supérieur strict de la matrice. Les paires i < j sont alors dans le même ordre que celles de pdist. La corrélation de Spearman compare leurs rangs, pas une égalité exacte de toutes les distances.
Sur ce jeu, la corrélation au graphe vaut environ 0,999 pour Isomap et 0,367 pour PCA. Cette comparaison favorise naturellement l’objectif d’Isomap puisque le graphe fournit les distances qu’il cherche à représenter. Elle ne suffit pas à désigner la meilleure projection pour tous les usages.
Le second indicateur, trustworthiness, examine les voisinages locaux. Les deux indicateurs répondent à des questions différentes et dépendent du voisinage choisi. Ni l’un ni l’autre ne mesure directement la réussite d’une tâche métier.
Que change le nombre de voisins ?
Sur cet échantillon, deux voisins donnent 34 composantes ; cinq, dix et 35 voisins donnent un graphe connexe. Ce contrôle ne dit pas que ces trois dernières projections seraient équivalentes. Un graphe connexe peut encore contenir des raccourcis indésirables.
| Choix | Point à surveiller |
|---|---|
| Peu de voisins | Fragmentation et sensibilité aux points isolés. |
| Beaucoup de voisins | Liaisons entre régions qui devraient rester éloignées sur la surface. |
| Plus de composantes de sortie | Représentation moins comprimée, au prix d’une visualisation moins simple. |
| Changement de métrique ou d’échelle | Changement des voisinages et donc de l’ensemble du raisonnement géométrique. |
L’API Isomap expose aussi le solveur spectral et la méthode de plus court chemin. Nous fixons ici eigen_solver="arpack" et un petit jeu pour obtenir un exemple lisible. Les matrices de distances peuvent occuper une mémoire importante : une matrice dense de n × n valeurs double précision nécessite environ 8 × n² octets, avant les autres allocations.
Projeter de nouveaux points et éviter les fuites
La classe propose transform après l’apprentissage. Si la projection sert ensuite à entraîner un prédicteur, ajustez Isomap uniquement sur les données autorisées pour l’apprentissage, puis transformez la validation et le test. Ajuster la projection sur tout le jeu avant la séparation fait déjà intervenir les données réservées dans la représentation.
Une projection ajustée ailleurs peut avoir une orientation différente. Ne comparez pas directement ses premières coordonnées à celles d’une ancienne projection comme s’il s’agissait d’unités physiques stables.
Deux exercices pour vérifier votre compréhension
- Remplacez
k = 10park = 2et expliquez pourquoi le script s’arrête avant la projection. - Essayez plusieurs voisinages connexes et comparez visuellement les projections ainsi que leurs indicateurs. Gardez ces essais comme une exploration ; réservez un protocole distinct pour évaluer un futur modèle prédictif.
Continuer avec des données tabulaires
Pour travailler d’abord la lecture, les identifiants et les contrôles d’un fichier, le projet CSV Python fournit des données et un programme complet. Les ressources Python gratuites et livres par niveau permettent de reprendre les prérequis.
Parcours de lecture : 4 — Passer de l’exploration à une cible numérique
Si votre objectif est de prévoir une durée connue dans l’historique, consultez le guide XGBoost régression. Il repart de variables explicatives et d’une cible avec des lots séparés. Ce parcours compare les rôles des méthodes ; il ne recommande pas d’enchaîner automatiquement Isomap et XGBoost.

