Clustering hiérarchique
Apprenez le clustering hiérarchique en Python avec scikit-learn et SciPy : méthodes de liaison, dendrogrammes et comparaison avec K-Means.
Le clustering hiérarchique est un algorithme d'apprentissage automatique non supervisé qui regroupe des points de données dans une arborescence de clusters imbriqués — sans exiger que vous spécifiiez le nombre de clusters à l'avance. Cette page explique comment fonctionne l'algorithme, la différence entre les approches agglomérative et divisive, comment choisir une méthode de liaison, et comment implémenter et visualiser le clustering hiérarchique en Python avec scikit-learn et SciPy.
Qu'est-ce que le clustering hiérarchique ?
Le clustering hiérarchique construit une hiérarchie de clusters en fusionnant ou en divisant itérativement des groupes de points de données sur la base d'une mesure de distance (ou de similarité). Le résultat est représenté sous la forme d'un dendrogramme — un diagramme en forme d'arbre où l'axe y indique la distance à laquelle les clusters sont fusionnés et les feuilles représentent des points de données individuels.
Contrairement au K-Means, le clustering hiérarchique ne nécessite pas de choisir le nombre de clusters avant d'exécuter l'algorithme. Vous exécutez l'algorithme une seule fois, puis vous « coupez » le dendrogramme à un seuil de distance choisi pour obtenir n'importe quel nombre de clusters.
Quand utiliser le clustering hiérarchique
Utilisez le clustering hiérarchique quand :
- Vous ne connaissez pas le nombre de clusters à l'avance et souhaitez explorer plusieurs options à partir d'une seule exécution.
- Votre jeu de données est de taille petite à moyenne (des milliers de lignes, pas des millions) — le coût mémoire O(n²) de l'algorithme le rend peu pratique pour les très grands jeux de données.
- Vous avez besoin de relations entre clusters interprétables (le dendrogramme révèle clairement l'historique des fusions).
- Vos clusters peuvent ne pas être sphériques — les méthodes hiérarchiques avec une liaison complète ou moyenne gèrent mieux les formes non globulaires que le K-Means.
Clustering agglomératif vs divisif
Il existe deux stratégies principales :
| Stratégie | Direction | Fonctionnement |
|---|---|---|
| Agglomératif (ascendant) | Commencer avec chaque point comme son propre cluster, puis fusionner répétitivement les deux clusters les plus proches. | Le plus courant ; utilisé par AgglomerativeClustering de scikit-learn et linkage de SciPy. |
| Divisif (descendant) | Commencer avec tous les points dans un seul cluster, puis diviser récursivement le plus grand cluster. | Rarement utilisé en pratique ; computationnellement coûteux. |
Cette page se concentre sur le clustering agglomératif, qui est ce que la plupart des praticiens entendent par « clustering hiérarchique ».
Comment fonctionne l'algorithme
Le clustering agglomératif suit ces étapes :
- Traiter chacun des n points de données comme son propre cluster (n clusters au total).
- Calculer la matrice des distances — les distances par paires entre tous les clusters.
- Fusionner les deux clusters ayant la plus petite distance en un nouveau cluster.
- Mettre à jour la matrice des distances pour refléter le nouveau cluster.
- Répéter les étapes 3–4 jusqu'à ce qu'il ne reste qu'un seul cluster.
Le résultat final est un dendrogramme codant toutes les n-1 étapes de fusion.
Méthodes de liaison
La méthode de liaison contrôle comment la distance entre deux clusters est calculée à chaque étape de fusion. Le choix affecte significativement la forme et la qualité des clusters.
| Méthode | Distance entre les clusters A et B | Idéale pour |
|---|---|---|
| Ward | Augmentation de la variance totale intra-cluster après fusion | Clusters compacts de taille approximativement égale (choix par défaut) |
| Complete | Distance maximale entre tout point de A et tout point de B | Clusters compacts ; évite le chaînage |
| Average | Distance moyenne entre toutes les paires (un de A, un de B) | Compromis équilibré entre single et complete |
| Single | Distance minimale entre tout point de A et tout point de B | Détection de clusters allongés ou de forme irrégulière ; sujet au « chaînage » |
La liaison Ward est le point de départ le plus utilisé. Si vos clusters sont allongés ou non convexes, essayez la liaison average ou single.
Mise à l'échelle des données avant le clustering
Étant donné que le clustering hiérarchique repose sur des calculs de distance, les données avec de grandes plages numériques dominent la matrice des distances et faussent les résultats. Commencez toujours par mettre vos données à l'échelle.
from sklearn.preprocessing import StandardScaler
scaler = StandardScaler()
X_scaled = scaler.fit_transform(X)StandardScaler centre chaque variable à la moyenne 0 et à la variance unitaire. Consultez le chapitre Scale pour des alternatives telles que MinMaxScaler et RobustScaler.
Implémenter le clustering hiérarchique avec scikit-learn
La classe AgglomerativeClustering de scikit-learn ajuste le modèle et attribue les étiquettes de clusters en une seule étape. Elle ne produit pas de dendrogramme — utilisez SciPy (présenté dans la section suivante) pour cela.
Étape 1 — Générer et mettre à l'échelle les données
from sklearn.datasets import make_blobs
from sklearn.preprocessing import StandardScaler
# 150 points in 3 natural clusters
X, y_true = make_blobs(n_samples=150, centers=3, cluster_std=0.6, random_state=42)
scaler = StandardScaler()
X_scaled = scaler.fit_transform(X)make_blobs crée un jeu de données synthétique reproductible, de sorte que cet exemple s'exécute sans aucun fichier CSV.
Étape 2 — Ajuster le clustering agglomératif
from sklearn.cluster import AgglomerativeClustering
hc = AgglomerativeClustering(n_clusters=3, linkage='ward')
labels = hc.fit_predict(X_scaled)
print(labels[:10])
# e.g. [2 2 0 1 0 1 2 2 0 1]fit_predict ajuste le modèle et renvoie l'étiquette de cluster (0, 1 ou 2) pour chaque point de données en un seul appel.
Étape 3 — Visualiser les clusters
import matplotlib.pyplot as plt
colors = ['red', 'blue', 'green']
for cluster_id in range(3):
mask = labels == cluster_id
plt.scatter(X_scaled[mask, 0], X_scaled[mask, 1],
s=60, label=f'Cluster {cluster_id + 1}')
plt.title('Agglomerative Clustering (Ward linkage, k=3)')
plt.xlabel('Feature 1 (scaled)')
plt.ylabel('Feature 2 (scaled)')
plt.legend()
plt.tight_layout()
plt.show()Dendrogrammes avec SciPy
Le dendrogramme est la sortie la plus distinctive du clustering hiérarchique. Il vous permet de choisir visuellement le nombre de clusters en coupant l'arbre à différentes hauteurs. Le module scipy.cluster.hierarchy de SciPy fournit à la fois linkage (pour construire l'arbre) et dendrogram (pour le tracer).
Construction et tracé d'un dendrogramme
from scipy.cluster.hierarchy import dendrogram, linkage
from sklearn.datasets import make_blobs
from sklearn.preprocessing import StandardScaler
import matplotlib.pyplot as plt
# Use a smaller dataset so the dendrogram is readable
X, _ = make_blobs(n_samples=30, centers=3, cluster_std=0.6, random_state=42)
scaler = StandardScaler()
X_scaled = scaler.fit_transform(X)
# Build the linkage matrix
Z = linkage(X_scaled, method='ward')
# Plot
plt.figure(figsize=(12, 5))
dendrogram(Z, leaf_rotation=90, leaf_font_size=8)
plt.title('Dendrogram (Ward linkage)')
plt.xlabel('Sample index')
plt.ylabel('Merge distance')
plt.tight_layout()
plt.show()Lire le dendrogramme
- Les feuilles (en bas) représentent des points de données individuels.
- Les lignes horizontales représentent des fusions. La hauteur d'une ligne est égale à la distance entre les deux clusters fusionnés.
- Couper l'arbre à une hauteur donnée vous donne le nombre de clusters sous cette coupe.
Pour choisir k, cherchez la ligne verticale la plus haute qui n'est pas coupée par une ligne horizontale — cet écart suggère le nombre de clusters le plus naturel.
Couper le dendrogramme pour attribuer des étiquettes
Après avoir construit la matrice de liaison Z, utilisez fcluster pour couper l'arbre au nombre de clusters souhaité :
from scipy.cluster.hierarchy import linkage, fcluster
from sklearn.datasets import make_blobs
from sklearn.preprocessing import StandardScaler
import numpy as np
X, _ = make_blobs(n_samples=150, centers=3, cluster_std=0.6, random_state=42)
scaler = StandardScaler()
X_scaled = scaler.fit_transform(X)
Z = linkage(X_scaled, method='ward')
# Cut the tree to get exactly 3 clusters
labels = fcluster(Z, t=3, criterion='maxclust')
print('Unique cluster IDs:', np.unique(labels)) # [1 2 3] (1-indexed)
print('Sizes:', np.bincount(labels[labels > 0])) # [50 50 50]Notez que les étiquettes de fcluster sont indexées à partir de 1 (commencent à 1), contrairement aux étiquettes indexées à partir de 0 de scikit-learn.
Comparaison des méthodes de liaison
La méthode de liaison modifie significativement les formes et les tailles des clusters. Voici comment comparer les quatre méthodes sur le même jeu de données :
from sklearn.cluster import AgglomerativeClustering
from sklearn.datasets import make_blobs
from sklearn.preprocessing import StandardScaler
import matplotlib.pyplot as plt
import numpy as np
X, _ = make_blobs(n_samples=150, centers=3, cluster_std=0.6, random_state=42)
scaler = StandardScaler()
X_scaled = scaler.fit_transform(X)
methods = ['ward', 'complete', 'average', 'single']
fig, axes = plt.subplots(1, 4, figsize=(16, 4))
for ax, method in zip(axes, methods):
hc = AgglomerativeClustering(n_clusters=3, linkage=method)
labels = hc.fit_predict(X_scaled)
ax.scatter(X_scaled[:, 0], X_scaled[:, 1], c=labels, cmap='Set1', s=30)
ax.set_title(f'{method.capitalize()} linkage')
ax.set_xticks([])
ax.set_yticks([])
plt.suptitle('Linkage method comparison (k=3)', y=1.02)
plt.tight_layout()
plt.show()Clustering hiérarchique vs K-Means
| Caractéristique | Clustering hiérarchique | K-Means |
|---|---|---|
| Nombre de clusters | À choisir après l'exécution (inspecter le dendrogramme) | Doit être spécifié avant l'exécution |
| Passage à l'échelle | Espace O(n²) — difficile au-delà de ~10 000 lignes | O(n·k·i) — s'adapte à des millions de points |
| Déterminisme | Entièrement déterministe | Dépend de l'initialisation aléatoire |
| Formes des clusters | Flexible (surtout avec la liaison single/average) | Suppose des clusters sphériques |
| Interprétabilité | Le dendrogramme montre tout l'historique des fusions | Les centroïdes sont facilement interprétables |
Utilisez le clustering hiérarchique pour l'analyse exploratoire sur des jeux de données de petite taille ; passez au K-Means (ou DBSCAN) lorsque vous avez des millions de lignes ou connaissez déjà le nombre de clusters.
Pièges courants
Oublier de mettre à l'échelle les données. Sans mise à l'échelle des données, une variable mesurée en milliers (par exemple, le revenu) domine une variable mesurée en chiffres simples (par exemple, la note d'âge), produisant des clusters trompeurs.
Utiliser la liaison Ward avec des distances non euclidiennes. La liaison Ward n'est valide qu'avec la distance euclidienne. Pour d'autres métriques de distance (par exemple, cosinus, Manhattan), utilisez la liaison complete ou average et passez metric= explicitement.
Interpréter des dendrogrammes sur de très grands jeux de données. Un dendrogramme avec 10 000 feuilles est illisible. Utilisez p= et truncate_mode='lastp' dans dendrogram() de SciPy pour n'afficher que les p dernières fusions.
Traiter les identifiants de clusters comme stables. Les identifiants de clusters (0, 1, 2) sont des étiquettes arbitraires. Lors de la comparaison de deux exécutions, faites correspondre les clusters par contenu, pas par numéro.
Conclusion
Le clustering hiérarchique est un algorithme flexible et interprétable qui ne nécessite pas de choisir k à l'avance. Vous construisez le dendrogramme complet une fois, puis vous le coupez à n'importe quel niveau. La liaison Ward avec un prétraitement StandardScaler est la valeur par défaut la plus sûre. Pour les très grands jeux de données, préférez le K-Means pour les performances.
Chapitres connexes :
- Scale — pourquoi et comment standardiser les données avant le clustering
- K-Means — l'alternative de clustering plat pour les grands jeux de données
- SciPy Tutorial — plus d'informations sur la bibliothèque de calcul scientifique SciPy
- Scatter Plot — visualiser des données multidimensionnelles avec Matplotlib