Un algorithme qui fusionne pas à pas les éléments les plus proches, jusqu'à ne former qu'un seul groupe. Le résultat est un arbre, le dendrogramme, que l'on coupe à la hauteur voulue pour obtenir plus ou moins de groupes. On voit ainsi toute la structure des données avant de choisir.
Un arbre généalogique à l'envers. On part des individus, on réunit les deux plus proches parents, puis les familles les plus proches, jusqu'à l'ancêtre commun.
On calcule la distance entre toutes les paires d'éléments. Ici, deux produits sont proches s'ils se retrouvent souvent dans les mêmes tickets de caisse.
Et on recommence. La distance entre deux groupes dépend du lien choisi : moyenne des distances, plus proche voisin, plus lointain, ou Ward qui minimise la dispersion.
Chaque fusion est tracée à sa hauteur, c'est-à-dire à sa distance. Couper l'arbre à une hauteur donnée fournit les groupes. Un grand saut de hauteur signale une coupe naturelle.
Pour chaque ticket, la liste des produits achetés parmi 28 références : pain, beurre, pâtes, sauce tomate, bière, couches, etc. On construit un tableau produits × tickets.
Coupé à la hauteur 0,8, l'arbre isole 6 duos ou trios : pain et beurre, pâtes, sauce tomate et parmesan, bière et chips, fromage et vin rouge, café et biscuits, couches et lingettes. De quoi organiser un rayon, un menu de site ou une promotion croisée.
La distance de Jaccard entre deux produits vaut 1 moins la part de tickets communs parmi ceux qui contiennent l'un ou l'autre. Elle reste élevée ici, car chaque produit est acheté seul la plupart du temps. On valide les groupes avec les chefs de rayon, pas seulement avec un indicateur.
Pas d'hyperparamètre à optimiser, mais trois choix qui changent l'arbre. Noms donnés pour R (hclust) et Python (scipy).
Euclidienne sur des chiffres standardisés, Jaccard ("binary" en R) sur des présences 0 / 1, corrélation pour des profils. C'est elle qui définit « se ressembler ».
average : moyenne des distances entre groupes, bon compromis. complete : groupes compacts. single : chaînes allongées. ward.D2 : groupes homogènes, à utiliser avec une distance euclidienne.
Couper là où les fusions font un grand saut de hauteur. On peut aussi demander un nombre de groupes (k en R, criterion="maxclust" en Python).
# Univers produits à partir des tickets : classification hiérarchique en R
tickets <- read.csv("tickets_caisse.csv")
# Une ligne par produit, une colonne par ticket : 1 si le produit est dans le ticket
presence <- (table(tickets$produit, tickets$id_ticket) > 0) * 1
# Méthode "binary" = distance de Jaccard : part des tickets non communs
distances <- dist(presence, method = "binary")
# Fusion pas à pas des produits les plus proches, lien moyen entre groupes
arbre <- hclust(distances, method = "average")
print(round(tail(arbre$height, 8), 3))
plot(arbre, hang = -1, main = "Proximité des produits dans les paniers")
# Coupe de l'arbre à la hauteur 0,8 : les produits qui partagent souvent un panier
groupes <- cutree(arbre, h = 0.8)
for (g in unique(groupes)) {
if (sum(groupes == g) > 1) cat(g, ":", names(groupes)[groupes == g], "\n")
}
# Univers produits à partir des tickets : classification hiérarchique en Python
import pandas as pd
from scipy.spatial.distance import pdist, squareform
from scipy.cluster.hierarchy import linkage, fcluster
tickets = pd.read_csv("tickets_caisse.csv")
# Une ligne par produit, une colonne par ticket : 1 si le produit est dans le ticket
presence = pd.crosstab(tickets["produit"], tickets["id_ticket"]) > 0
# Distance de Jaccard : 1 - (tickets communs / tickets contenant l'un ou l'autre)
distances = pdist(presence.values, metric="jaccard")
# Fusion pas à pas des produits les plus proches, lien moyen entre groupes
arbre = linkage(distances, method="average")
print("Hauteurs des 8 dernières fusions :", arbre[-8:, 2].round(3))
# Coupe de l'arbre à la hauteur 0.8 : les produits qui partagent souvent un panier
groupes = pd.Series(fcluster(arbre, t=0.8, criterion="distance"), index=presence.index)
for g, produits in groupes.groupby(groupes):
if len(produits) > 1:
print(g, ", ".join(produits.index))
Chaque feuille est un élément. Deux branches qui se rejoignent forment un groupe, et la hauteur de la jonction indique leur distance. Plus la jonction est basse, plus les éléments se ressemblent. On coupe l'arbre horizontalement pour obtenir les groupes.
La CAH ne demande pas de fixer le nombre de groupes à l'avance et montre tous les niveaux de regroupement, mais elle devient lente au-delà de quelques dizaines de milliers de lignes. K-means passe à l'échelle mais impose k. Une pratique courante : CAH sur un échantillon pour choisir k, puis K-means sur toute la base.
Ward est le choix par défaut pour des données numériques standardisées : il produit des groupes homogènes et de tailles comparables. Le lien moyen convient à toute distance, comme Jaccard. Le lien simple est à éviter en segmentation, car il forme des chaînes.
Rapide sur des centaines de milliers de lignes, mais demande de fixer k. On peut choisir k avec un arbre sur un échantillon.
Voir la fiche → les règles du panierDonne des règles « qui achète A achète B » avec leur confiance et leur lift, plutôt que des familles.
Voir la fiche → même matrice, k fixéTravaille sur la même matrice de distances et désigne un élément représentatif par groupe.
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