Mesurer la qualité d’un regroupement avec la largeur de silhouette, l’indice de Dunn et l’indice de Rand corrigé
Validez les résultats de regroupement en R. Utilisez des mesures internes (graphique de silhouette, indice de Dunn) pour juger à quel point vos regroupements sont compacts et séparés, et des mesures externes (indice de Rand corrigé, VI de Meila) pour comparer les regroupements à une vérité terrain connue — le tout avec factoextra et fpc::cluster.stats().
Date de publication
24 juin 2026
Modifié
7 juillet 2026
AstucePoints clés
La validation de regroupement mesure la qualité d’un regroupement — pour ne pas prendre du bruit aléatoire pour de la structure, ni choisir le mauvais algorithme.
La validation interne n’utilise que les données : la largeur de silhouette évalue à quel point chaque point se situe bien dans son regroupement, et l’indice de Dunn récompense les regroupements compacts et bien séparés.
Une silhouette négative signale un point qui se trouve probablement dans le mauvais regroupement — lisez-le directement sur le graphique de silhouette.
La validation externe compare les regroupements à une vérité terrain connue : l’indice de Rand corrigé (−1 à 1) et le VI de Meila quantifient l’accord.
Calculez tout en un seul appel avec fpc::cluster.stats(), et tracez la silhouette avec factoextra::fviz_silhouette().
Vous avez exécuté un k-means, obtenu trois regroupements, et le graphique semble raisonnable. Mais est-il bon ? Les algorithmes de regroupement découperont volontiers du pur bruit en groupes d’apparence nette — donc avant d’agir sur un regroupement, vous devez le valider.
La validation de regroupement est la procédure qui évalue la qualité d’un résultat de regroupement. Elle compte dans deux situations : vous voulez éviter de trouver des motifs dans des données aléatoires, et vous voulez comparer deux algorithmes de regroupement et garder le meilleur.
Les statistiques de validation se répartissent en trois classes :
Validation interne — n’utilise que l’information interne du regroupement (distances intra- et inter-regroupements), sans référence externe. Utile pour juger la qualité et estimer le nombre de regroupements.
Validation externe — compare les regroupements à un résultat connu de manière externe, comme de vraies étiquettes de classe. Surtout utilisée pour choisir le bon algorithme quand vous connaissez la vérité terrain.
Validation relative — fait varier un paramètre (comme k) pour un même algorithme et compare les résultats. C’est ce que font les méthodes de nombre optimal de regroupements.
Cette leçon couvre les deux premières. Nous jugerons un regroupement avec des mesures internes (largeur de silhouette, indice de Dunn), puis le confronterons à une réponse connue avec des mesures externes (indice de Rand corrigé, VI de Meila).
Les données
Nous utiliserons le jeu de données intégré iris. Il a un avantage caché pour cette leçon : nous connaissons le vrai groupement — les trois espèces — donc nous pouvons utiliser les espèces comme vérité terrain externe pour tester si nos regroupements ont retrouvé la structure réelle.
Nous écartons la colonne Species (c’est la réponse que nous mettons de côté) et nous standardisons, parce que les quatre mesures sont sur des échelles différentes.
# Excluding the column "Species" at position 5df <- iris[, -5]# Standardize (mean 0, sd 1 per column)df <-scale(df)head(df)
Mesures internes : qu’est-ce qui fait un “bon” regroupement ?
L’objectif du partitionnement est de découper les données de sorte que les objets d’un même regroupement soient aussi semblables que possible, et que les objets de regroupements différents soient aussi distincts que possible. Autrement dit : faible distance moyenne intra-regroupement, grande distance moyenne inter-regroupements.
Les indices de validation interne capturent cela avec deux idées :
Compacité (cohésion) — à quel point les objets sont-ils proches au sein d’un regroupement ? Une plus faible variation intra-regroupement est meilleure.
Séparation — à quel point les regroupements différents sont-ils éloignés ? Une plus grande distance inter-regroupements est meilleure.
La plupart des indices combinent les deux, grosso modo comme \(Index = (\alpha \times Separation) / (\beta \times Compactness)\), où \(\alpha\) et \(\beta\) sont des poids. Nous utiliserons les deux plus courants : la largeur de silhouette et l’indice de Dunn.
Exécuter le regroupement
Nous regroupons avec eclust() (regroupement amélioré, de factoextra). Il enveloppe les fonctions standard (kmeans, pam, hclust, …) en un seul appel et — pratique pour la validation — attache automatiquement l’information de silhouette au résultat.
Exécutez le k-means avec k = 3 sur les données standardisées et visualisez les regroupements :
library(factoextra)df <-scale(iris[, -5])# K-means clustering with k = 3set.seed(123)km.res <-eclust(df, "kmeans", k =3, nstart =25, graph =FALSE)# Visualize the clustersfviz_cluster(km.res, geom ="point", ellipse.type ="norm",palette ="jco", ggtheme =theme_minimal())
Les trois regroupements sont bien séparés sur le plan des premières composantes principales : le regroupement 1 (bleu) est nettement à l’écart, tandis que les regroupements 2 et 3 (or et gris) sont plus proches et se chevauchent légèrement — un premier indice visuel qu’ils seront plus difficiles à distinguer. Les statistiques de validation ci-dessous mettent des chiffres sur cette intuition.
Coefficient de silhouette
La largeur de silhouette mesure à quel point chaque observation est bien regroupée. Pour une observation \(i\), elle compare deux distances :
\(a_i\) — la distance moyenne de \(i\) aux autres points de son propre regroupement (à quel point il s’y intègre).
\(b_i\) — la distance moyenne de \(i\) aux points du regroupement voisin le plus proche (à quelle distance se trouve la plus proche alternative).
La largeur de silhouette est alors \(S_i = (b_i - a_i) / \max(a_i, b_i)\), qui se situe toujours entre −1 et 1 :
Proche de 1 — l’objet est bien regroupé (bien plus proche de son propre groupe que de tout autre).
Autour de 0 — l’objet se situe entre deux regroupements.
Négative — l’objet est probablement dans le mauvais regroupement ; un autre regroupement est plus proche.
fviz_silhouette() dessine une barre par observation, regroupée et colorée par regroupement, et affiche la largeur de silhouette moyenne par regroupement :
Lisez le graphique : les barres hautes sont des points regroupés avec confiance ; la ligne en pointillés est la largeur de silhouette moyenne globale. Le regroupement 1 a les barres les plus hautes et les plus uniformes (c’est l’espèce nettement séparée), tandis que les regroupements 2 et 3 sont plus courts et quelques barres passent sous zéro — ce sont les points pris entre les deux groupes qui se chevauchent.
Vous pouvez extraire directement les valeurs de silhouette du résultat :
library(factoextra)df <-scale(iris[, -5])set.seed(123)km.res <-eclust(df, "kmeans", k =3, nstart =25, graph =FALSE)# Average silhouette width of each clusterkm.res$silinfo$clus.avg.widths
[1] 0.6363162 0.3933772 0.3473922
# The total average (mean of all individual silhouette widths)km.res$silinfo$avg.width
[1] 0.4599482
# The size of each clusterkm.res$size
[1] 50 53 47
Repérez maintenant les points mal assignés — ceux dont la silhouette est négative — et voyez de quel regroupement ils sont en réalité les plus proches (leur neighbor) :
library(factoextra)df <-scale(iris[, -5])set.seed(123)km.res <-eclust(df, "kmeans", k =3, nstart =25, graph =FALSE)# Silhouette width of each observation (cluster, neighbor, sil_width)sil <- km.res$silinfo$widths[, 1:3]# Objects with a negative silhouetteneg_sil_index <-which(sil[, "sil_width"] <0)sil[neg_sil_index, , drop =FALSE]
Une poignée d’observations ont une silhouette négative : chacune a été assignée à un regroupement mais se situe en réalité plus près de son regroupement neighbor. Ce sont exactement les points de la zone de chevauchement entre les deux espèces semblables — le signe que les données ne se divisent pas parfaitement en trois, et non un bug dans votre code.
Indice de Dunn
L’indice de Dunn est une seconde mesure interne. Il est construit à partir de deux quantités :
La séparation minimale — la plus petite distance entre des objets de regroupements différents.
Le diamètre maximal — la plus grande distance entre des objets au sein d’un même regroupement.
L’indice de Dunn est leur rapport :
\[
D = \frac{min.separation}{max.diameter}
\]
Si les données ont des regroupements compacts et bien séparés, les diamètres sont petits et les écarts entre regroupements sont grands — donc un indice de Dunn plus grand signifie un meilleur regroupement. (Contrairement à la silhouette, il n’a pas de borne supérieure fixe, il est donc surtout utile pour comparer des regroupements des mêmes données.)
Calculez-le — ainsi que des dizaines d’autres statistiques internes — avec fpc::cluster.stats(). Passez-lui une matrice de distances et les affectations de regroupement :
library(factoextra)library(fpc)df <-scale(iris[, -5])set.seed(123)km.res <-eclust(df, "kmeans", k =3, nstart =25, graph =FALSE)# All internal validation statistics for the k-means clusteringkm_stats <-cluster.stats(dist(df), km.res$cluster)# Dunn indexkm_stats$dunn
[1] 0.02649665
cluster.stats() renvoie une longue liste — voici celles qui valent la peine d’être connues :
within.cluster.ss — somme des carrés intra-regroupement (l’objectif du k-means) ; plus petit est plus resserré.
average.within / average.between — distance moyenne intra- / inter-regroupements. Vous voulez within petit et between grand.
clus.avg.silwidths — les largeurs de silhouette moyennes par regroupement (les mêmes valeurs que ci-dessus).
dunn, dunn2 — l’indice de Dunn et une variante.
corrected.rand, vi — les mesures externes, quand vous passez aussi un regroupement de référence (section suivante).
library(fpc)df <-scale(iris[, -5])set.seed(123)km.res <- factoextra::eclust(df, "kmeans", k =3, nstart =25, graph =FALSE)km_stats <-cluster.stats(dist(df), km.res$cluster)# A few useful internal statisticskm_stats$within.cluster.ss # within-cluster sum of squares
[1] 138.8884
km_stats$average.within # average distance within clusters
[1] 1.224431
km_stats$average.between # average distance between clusters
[1] 3.130708
Mesures externes : avons-nous retrouvé les vrais groupes ?
Les mesures internes vous disent si les regroupements sont compacts et séparés — mais pas s’ils correspondent à la réalité. Lorsque vous connaissez les vraies étiquettes, la validation externe compare vos regroupements à celles-ci.
Pour iris, nous savons qu’il y a exactement trois espèces, donc nous pouvons demander : le regroupement k-means correspond-il à la vraie structure des espèces ?
Commencez par un tableau croisé des vraies espèces contre les regroupements assignés :
Le tableau raconte l’histoire : les 50 setosa atterrissent dans un seul regroupement (parfaitement retrouvé), mais versicolor et virginica sont scindées — la majeure partie de chacune va dans un regroupement, mais une douzaine environ passent de l’autre côté. Les deux espèces semblables sont la source de chaque silhouette négative vue plus haut.
Pour mettre un seul chiffre sur cet accord, utilisez l’indice de Rand corrigé et le VI de Meila, tous deux renvoyés par cluster.stats() lorsque vous passez les étiquettes de référence comme premier regroupement et vos regroupements comme alternative :
library(fpc)df <-scale(iris[, -5])set.seed(123)km.res <- factoextra::eclust(df, "kmeans", k =3, nstart =25, graph =FALSE)# Species as the external ground truthspecies <-as.numeric(iris$Species)clust_stats <-cluster.stats(d =dist(df), species, km.res$cluster)# Corrected Rand index (-1 = no agreement, 1 = perfect)clust_stats$corrected.rand
[1] 0.6201352
# Meila's VI (variation of information; lower = more agreement)clust_stats$vi
[1] 0.7477749
Interprétez les deux nombres :
Indice de Rand corrigé — la fraction de paires de points classées de manière cohérente (même regroupement et même espèce, ou différents dans les deux), ajustée pour le hasard. Il va de −1 (aucun accord) à 1 (parfait). Une valeur autour de 0.62 signifie un accord substantiel mais imparfait — exactement ce à quoi on s’attend quand une espèce est parfaitement retrouvée et deux sont en partie confondues.
VI de Meila (variation de l’information) — une distance issue de la théorie de l’information entre les deux partitions : 0 signifie identiques, et plus c’est grand, plus il y a de désaccord. C’est un autre angle sur le même écart.
Parce que la validation externe a besoin de la vérité terrain, son véritable usage est la sélection d’algorithme : exécutez le k-means, le PAM et la classification hiérarchique sur un jeu de données étiqueté, calculez l’indice de Rand corrigé pour chacun, et gardez l’algorithme qui retrouve le mieux les groupes connus — le déroulé décrit dans choisir le meilleur algorithme de regroupement.
🟢 Avec un agent IA
Demandez à Prova« mes regroupements sont-ils réels, ou est-ce du bruit ? » — elle répond avec du code fviz_silhouette(), cluster.stats() et Dunn/Rand que vous pouvez exécuter sur vos propres données, puis vous aide à lire le graphique de silhouette et à décider si le regroupement mérite confiance. The runtime is the judge.Demandez à Prova →
Problèmes courants
Certains points ont une silhouette négative — mon regroupement est-il faux ? Pas nécessairement. Une silhouette négative signifie que ce point se trouve plus près d’un regroupement voisin que du sien — il est dans le chevauchement entre deux groupes semblables. Quelques négatifs (comme à la frontière versicolor/virginica d’iris) sont normaux. Beaucoup de négatifs, ou une faible largeur de silhouette moyenne globale, voilà le vrai signal d’alerte — essayez un autre k ou un autre algorithme.
Laquelle utiliser — validation interne ou externe ? Utilisez la validation externe quand vous connaissez les vraies étiquettes (vous choisissez un algorithme sur un jeu de référence étiqueté) : l’indice de Rand corrigé et le VI vous disent quel algorithme retrouve le mieux la vérité. Utilisez la validation interne (silhouette, Dunn) pour de vraies données non étiquetées — c’est tout ce que vous avez, et elle juge si les regroupements sont compacts et séparés.
Quel indice rapporter — silhouette, Dunn ou Rand ? La largeur de silhouette est la plus intuitive et la plus facile à lire (par point et globalement), donc rapportez-la par défaut. L’indice de Dunn est pratique pour comparer plusieurs regroupements des mêmes données (plus grand est meilleur), mais il n’a pas d’échelle fixe. L’indice de Rand corrigé ne s’applique que lorsque vous disposez d’étiquettes de vérité terrain.
Questions fréquentes
NoteQu’est-ce qu’un bon score de silhouette ?
La largeur de silhouette varie de −1 à 1. En règle générale, une moyenne au-dessus de ~0.5 indique une structure raisonnable, 0.25–0.5 est faible (les regroupements se chevauchent), et proche ou en dessous de 0 signifie aucun regroupement réel. Au niveau de chaque point, des valeurs proches de 1 sont bien regroupées, proches de 0 se situent entre les regroupements, et les valeurs négatives sont probablement mal assignées. Tracez-la avec fviz_silhouette() et lisez à la fois la moyenne globale et les barres individuelles.
NoteQuelle est la différence entre validation de regroupement interne et externe ?
La validation interne (largeur de silhouette, indice de Dunn) n’utilise que les données elles-mêmes — distances intra- et inter-regroupements — pour juger si les regroupements sont compacts et bien séparés. La validation externe (indice de Rand corrigé, VI de Meila) compare les regroupements à une vérité terrain connue, comme de vraies étiquettes de classe, et sert surtout à choisir le meilleur algorithme. Utilisez l’interne pour de vraies données non étiquetées, l’externe quand vous avez les réponses.
NoteQu’est-ce que l’indice de Rand corrigé et comment l’interpréter ?
L’indice de Rand corrigé (ajusté) mesure l’accord entre deux partitions — vos regroupements et un étiquetage de référence — ajusté pour le hasard. Il va de −1 (aucun accord) à 0 (aléatoire) jusqu’à 1 (accord parfait). Calculez-le en R avec fpc::cluster.stats(d, reference, clustering)$corrected.rand. Une valeur comme 0.62 signifie une récupération substantielle mais imparfaite des groupes connus.
NoteQu’est-ce que l’indice de Dunn en regroupement ?
L’indice de Dunn est le rapport de la distance inter-regroupements minimale au diamètre intra-regroupement maximal. Des regroupements compacts et bien séparés donnent de grands écarts et de petits diamètres, donc un indice de Dunn plus élevé est meilleur. Il n’a pas de borne supérieure fixe, il est donc surtout utile pour comparer des regroupements des mêmes données. Obtenez-le avec fpc::cluster.stats(dist(df), clusters)$dunn.
NoteComment calculer des statistiques de validation de regroupement en R ?
Utilisez fpc::cluster.stats(d, clustering) avec une matrice de distances issue de dist(). Elle renvoie l’indice de Dunn ($dunn), la somme des carrés intra-regroupement ($within.cluster.ss), les distances moyennes intra/inter, et les largeurs de silhouette par regroupement en un seul appel. Ajoutez un étiquetage de référence — cluster.stats(d, reference, clustering) — pour obtenir aussi l’indice de Rand corrigé ($corrected.rand) et le VI de Meila ($vi). Tracez la silhouette séparément avec factoextra::fviz_silhouette().
Testez vos connaissances
ImportantExercice : valider un regroupement PAM
Adaptez le déroulé au PAM (k-medoids) au lieu du k-means. Complétez le code pour qu’il regroupe les données iris standardisées avec le PAM (k = 3), trace le graphique de silhouette, et rapporte l’indice de Rand corrigé contre les vraies espèces.
# eclust's clustering function is a string: "kmeans", "pam", "hclust", ...# The cluster assignments live in pam.res$cluster.
library(factoextra)
library(fpc)
df <- scale(iris[, -5])
set.seed(123)
pam.res <- eclust(df, "pam", k = 3, graph = FALSE)
fviz_silhouette(pam.res, palette = "jco", ggtheme = theme_classic())
species <- as.numeric(iris$Species)
cluster.stats(d = dist(df), species, pam.res$cluster)$corrected.rand
# Compare this Rand index to the k-means one (~0.62) to pick the better algorithm.
library(factoextra)library(fpc)df <-scale(iris[, -5])set.seed(123)pam.res <-eclust(df, "pam", k =3, graph =FALSE)fviz_silhouette(pam.res, palette ="jco", ggtheme =theme_classic())species <-as.numeric(iris$Species)cluster.stats(d =dist(df), species, pam.res$cluster)$corrected.rand# Compare this Rand index to the k-means one (~0.62) to pick the better algorithm.
NoteVérification rapide : quel énoncé est correct ?
Une largeur de silhouette négative signifie que l’observation est très bien regroupée.
L’indice de Rand corrigé exige une vérité terrain connue (étiquettes externes) pour être calculé.
Un indice de Dunn plus petit indique un regroupement meilleur, plus compact et plus séparé.
AstuceAfficher la réponse
L’énoncé 2 est correct. L’indice de Rand corrigé compare vos regroupements à un étiquetage de référence externe, vous avez donc besoin des vraies étiquettes. L’énoncé 1 est faux — une silhouette négative signale un point mal assigné (il est plus proche d’un regroupement voisin). L’énoncé 3 est faux — un indice de Dunn plus grand est meilleur, parce qu’il signifie une grande séparation par rapport au diamètre des regroupements.
Conclusion
Vous avez validé un regroupement k-means d’iris de deux façons. En interne, le graphique de silhouette et les largeurs par regroupement ont montré un regroupement nettement séparé et deux qui se chevauchent (avec quelques points à silhouette négative sur la frontière), et l’indice de Dunn a résumé le compromis compacité-vs-séparation en un seul nombre. En externe, le tableau croisé plus l’indice de Rand corrigé (~0.62) et le VI de Meila ont quantifié à quel point les regroupements ont retrouvé les vraies espèces. Le déroulé pratique : jugez la qualité avec la silhouette et l’indice de Dunn sur n’importe quelles données, et — quand vous avez des étiquettes — utilisez l’indice de Rand corrigé pour choisir l’algorithme qui retrouve le mieux la vérité.
Vous préférez un livre ? Practical Guide to Cluster Analysis in R est disponible en PDF téléchargeable — toutes les leçons de cette série, hors ligne et à vous.
Prouvez que vous savez le faire. Maîtrisez toute la série Analyse de clustering en R — suivez votre parcours, construisez des projets et obtenez un certificat.
@online{2026,
author = {},
title = {Statistiques de validation de regroupement en R},
date = {2026-06-24},
url = {https://www.datanovia.com/learn/machine-learning/clustering/cluster-validation-statistics},
langid = {fr}
}