Un algorithme de la famille de DBSCAN qui ne fixe pas de rayon. Il range les points dans un ordre de parcours par densité et note pour chacun sa distance d'accessibilité. Le graphe obtenu montre les groupes comme des vallées, et l'on en extrait des groupes à l'échelle voulue sans relancer le calcul.
Un randonneur parcourt un territoire en allant toujours vers le village voisin le plus proche. En notant la distance de chaque étape, il dessine un relief : les vallées sont les villes, les pics les zones désertes entre elles.
Pour chaque point, la distance de cœur est la distance à son minPts-ième voisin : petite dans une zone dense, grande dans une zone clairsemée.
On part d'un point, puis on visite toujours le point non visité le plus facile à atteindre depuis ceux déjà vus. Chaque point reçoit sa distance d'accessibilité au moment où il est atteint.
Tracée dans l'ordre de visite, la distance d'accessibilité forme des vallées : ce sont les groupes. Couper à une hauteur donne à peu près le résultat d'un DBSCAN de ce rayon ; plusieurs coupes donnent plusieurs échelles.
Panier moyen, achats par mois, jours depuis le dernier achat, nombre de catégories, part d'achats en promotion. Aucune colonne cible, et aucune hypothèse sur le nombre de segments.
À l'échelle fine (rayon 0,5), trois segments denses apparaissent : occasionnels, réguliers, clients inactifs portés sur les promos. Les 396 clients hors groupe ont un panier moyen élevé : les gros clients sont trop dispersés pour former une zone dense. À l'échelle large (0,8), presque tout fusionne en un seul bloc.
Pas de score unique : on regarde quelles vallées du graphe restent nettes quand on change d'échelle. Un groupe qui n'existe qu'à une échelle précise est fragile. Ici, les gros clients méritent une analyse à part plutôt qu'un segment forcé.
Noms donnés pour R (paquet dbscan) et Python (scikit-learn).
Le nombre de voisins qui définit une zone dense. Il lisse le graphe : plus il est grand, moins il y a de petites vallées parasites. Ici, 30 pour une base de 2 000 clients.
La hauteur de coupe du graphe, qui produit des groupes comme un DBSCAN de ce rayon. On peut en tester plusieurs sans refaire le calcul principal.
L'autre façon d'extraire les groupes : repérer les pentes raides du graphe (extractXi en R, cluster_method="xi" par défaut en Python). Pratique pour des groupes emboîtés, mais sensible : ici, elle ne retrouve pas les segments, d'où la coupe par rayon.
# Segmentation clients à plusieurs échelles : OPTICS en R
library(dbscan)
clients <- read.csv("clients_segmentation.csv")
variables <- c("panier_moyen", "achats_par_mois", "recence_jours", "nb_categories", "part_promo")
X <- scale(clients[, variables])
# Un seul calcul : l'ordre des clients et leur distance d'accessibilité
modele <- optics(X, minPts = 30)
plot(modele) # graphe d'accessibilité : chaque vallée est un groupe
# Lecture du même ordre à deux échelles (0 = hors groupe)
fin <- extractDBSCAN(modele, eps_cl = 0.5)$cluster
large <- extractDBSCAN(modele, eps_cl = 0.8)$cluster
print(table(fin))
print(table(large))
# Profil des groupes à l'échelle fine
print(round(aggregate(clients[, variables], by = list(groupe = fin), FUN = mean), 2))
# Segmentation clients à plusieurs échelles : OPTICS en Python
import pandas as pd
from sklearn.preprocessing import StandardScaler
from sklearn.cluster import OPTICS, cluster_optics_dbscan
clients = pd.read_csv("clients_segmentation.csv")
variables = ["panier_moyen", "achats_par_mois", "recence_jours", "nb_categories", "part_promo"]
X = StandardScaler().fit_transform(clients[variables])
# Un seul calcul : l'ordre des clients et leur distance d'accessibilité
modele = OPTICS(min_samples=30).fit(X)
# Lecture du même ordre à deux échelles (-1 = hors groupe)
for rayon in [0.5, 0.8]:
groupes = cluster_optics_dbscan(reachability=modele.reachability_, core_distances=modele.core_distances_,
ordering=modele.ordering_, eps=rayon)
print("Rayon", rayon, ":", pd.Series(groupes).value_counts().sort_index().to_dict())
# Profil des groupes à l'échelle fine
clients["groupe"] = cluster_optics_dbscan(reachability=modele.reachability_, core_distances=modele.core_distances_,
ordering=modele.ordering_, eps=0.5)
print(clients.groupby("groupe")[variables].mean().round(2).to_string())
L'axe horizontal suit l'ordre de parcours des points, l'axe vertical leur distance d'accessibilité. Les vallées sont des groupes denses : plus elles sont profondes, plus le groupe est serré. Les pics séparent les groupes, et une vallée à l'intérieur d'une autre signale un sous-groupe.
DBSCAN produit des groupes pour un rayon eps donné. OPTICS calcule un ordre et des distances qui contiennent les résultats de DBSCAN pour tous les rayons inférieurs à eps. On choisit l'échelle après coup, en regardant le graphe.
Les deux explorent toutes les densités. HDBSCAN choisit automatiquement les groupes les plus stables : c'est le bon choix pour une segmentation directe. OPTICS laisse l'analyste décider en lisant le graphe d'accessibilité : c'est un outil d'exploration.
Le même principe avec un rayon fixé. Plus rapide, mais il faut connaître le bon rayon à l'avance.
Voir la fiche → l'extraction automatiqueExplore aussi toutes les échelles, puis choisit seul les groupes les plus stables. Le choix par défaut quand on veut un résultat sans exploration.
Voir la fiche → l'autre vue multi-échelleUn arbre de fusions à couper à la hauteur voulue. Même idée de lecture à plusieurs niveaux, fondée sur les distances plutôt que sur la densité.
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