UMAP projette des données de nombreuses colonnes sur une carte en 2D en gardant les voisinages, comme t-SNE, mais plus vite et en respectant en général mieux la structure d'ensemble. Surtout, la carte apprise accueille de nouvelles lignes sans être recalculée, ce qui en fait aussi une étape de préparation avant un clustering.
Un plan de métro : les stations voisines sont proches et les lignes gardent leur ordre, mais les distances sur le plan ne sont pas celles du terrain.
Chaque client est relié à ses plus proches voisins dans l'espace d'origine (n_neighbors), avec un poids qui décroît avec la distance.
On part d'une carte initiale, en général issue d'une décomposition spectrale du graphe, puis on rapproche les points reliés et on écarte les autres.
Le modèle appris sait placer un nouveau client sur la carte existante à partir de ses voisins, sans tout recalculer.
Une ligne par client, une colonne par produit (120), les notes centrées sur la moyenne du client et les produits non notés à 0. Le jeu contient 4 groupes de goûts cachés, que la carte doit faire apparaître.
La carte est construite sur 500 clients. Les clients proches ont des goûts proches ; on y repère des groupes, que l'on nomme à partir de leurs produits préférés. Les 100 clients suivants sont placés sur la carte existante, comme le seraient les nouveaux inscrits du mois.
La carte n'a pas de vérité à laquelle se comparer. On vérifie que les groupes vus sur la carte ont des produits préférés distincts, qu'ils restent en changeant la graine ou n_neighbors, et que les nouveaux clients tombent dans des zones cohérentes avec leurs achats.
Noms identiques en R (uwot) et Python (umap-learn).
Taille du voisinage, 15 par défaut. Petite, la carte détaille les micro-groupes ; grande, elle privilégie la structure d'ensemble. On teste de 5 à 50.
Écart minimal entre points sur la carte. Proche de 0, les groupes sont compacts, utile avant un clustering ; vers 0,5, la carte est plus aérée. La valeur par défaut est 0,1 dans umap-learn et 0,01 dans uwot : mieux vaut la fixer.
La distance d'origine. Euclidienne par défaut ; cosinus pour des profils où compte la direction plutôt que l'intensité, comme des notes centrées ou des embeddings de texte.
# Carte des goûts clients : UMAP en R
library(uwot)
notes <- read.csv("notes_produits.csv")
# Une ligne par client, une colonne par produit, notes centrées sur la moyenne du client
produits <- sort(unique(notes$id_produit))
M <- matrix(NA, nrow = max(notes$id_client), ncol = length(produits))
M[cbind(notes$id_client, match(notes$id_produit, produits))] <- notes$note
X <- M - rowMeans(M, na.rm = TRUE)
X[is.na(X)] <- 0
set.seed(42)
# Les 500 premiers clients servent à construire la carte
modele <- umap(X[1:500, ], n_neighbors = 15, min_dist = 0.1, metric = "cosine", ret_model = TRUE)
carte <- modele$embedding
# Les 100 derniers sont placés sur la carte existante, sans la recalculer
nouveaux <- umap_transform(X[501:600, ], modele)
# Groupes lus sur la carte, pour vérification (à croiser avec les produits préférés)
groupe <- kmeans(carte, centers = 4, nstart = 10)$cluster
print(table(groupe))
print(round(head(nouveaux), 2))
plot(carte, col = groupe, pch = 19, xlab = "UMAP 1", ylab = "UMAP 2")
# Carte des goûts clients : UMAP en Python
import pandas as pd
import umap
from sklearn.cluster import KMeans
notes = pd.read_csv("notes_produits.csv")
# Une ligne par client, une colonne par produit, notes centrées sur la moyenne du client
M = notes.pivot_table(index="id_client", columns="id_produit", values="note")
X = M.sub(M.mean(axis=1), axis=0).fillna(0)
# Les 500 premiers clients servent à construire la carte
reducteur = umap.UMAP(n_neighbors=15, min_dist=0.1, metric="cosine", random_state=42)
carte = pd.DataFrame(reducteur.fit_transform(X.iloc[:500]), index=X.index[:500], columns=["x", "y"])
# Les 100 derniers sont placés sur la carte existante, sans la recalculer
nouveaux = pd.DataFrame(reducteur.transform(X.iloc[500:]), index=X.index[500:], columns=["x", "y"])
# Groupes lus sur la carte, pour vérification (à croiser avec les produits préférés)
carte["groupe"] = KMeans(n_clusters=4, n_init=10, random_state=42).fit_predict(carte[["x", "y"]])
print(carte["groupe"].value_counts().sort_index())
print(carte.groupby("groupe")[["x", "y"]].mean().round(2))
print(nouveaux.head().round(2))
Uniform Manifold Approximation and Projection. La méthode a été publiée en 2018 par Leland McInnes, John Healy et James Melville. Elle repose sur la topologie et les graphes de voisinage, mais s'utilise comme t-SNE : on donne un tableau, on obtient une carte.
Oui, c'est courant, par exemple avec HDBSCAN. On projette alors plutôt en 5 à 10 dimensions avec un min_dist proche de 0, et on vérifie les groupes obtenus sur les données d'origine. Sur une carte 2D faite pour la présentation, le clustering est plus fragile.
L'optimisation avance par étapes aléatoires. Sans graine fixée, la carte change, parfois simplement par rotation ou symétrie. On fixe la graine (random_state, set.seed) pour une présentation, et on vérifie que les groupes restent stables d'une graine à l'autre.
Excellent sur les voisinages locaux, mais plus lent et incapable de placer de nouvelles lignes sur une carte existante.
Voir la fiche → la version linéaireAxes interprétables et calcul instantané. Souvent appliquée avant UMAP pour débruiter les données.
Voir la fiche → le duo classiqueClustering par densité, souvent appliqué aux sorties d'UMAP pour trouver les groupes sans fixer leur nombre.
Voir la fiche →Dataistudio forme les équipes au machine learning et à l'IA, sur des cas concrets.
Nous utilisons des cookies de mesure d'audience et de suivi publicitaire pour comprendre la fréquentation du site et l'efficacité de nos annonces. Rien n'est déposé sans votre accord. En savoir plus