En apprentissage non supervisé, il n’y a pas de cible à prédire. On cherche une structure cachée dans les données. Le clustering (partitionnement) regroupe les observations qui se ressemblent : segments de clients, familles de produits, profils de comportement.
Comment fonctionne K-means ?
K-means cherche k groupes dont chaque point est proche du centre (centroïde) de son groupe :
- placer k centres initiaux (scikit-learn utilise par défaut l’initialisation
k-means++, qui écarte les centres les uns des autres) ; - affecter chaque point au centre le plus proche ;
- recalculer chaque centre comme la moyenne des points de son groupe ;
- répéter 2 et 3 jusqu’à ce que les centres ne bougent plus.
L’algorithme minimise l’inertie : la somme des distances au carré entre chaque point et son centre.
Premier clustering
from sklearn.datasets import make_blobs
from sklearn.cluster import KMeans
# 500 points répartis en 4 nuages (la vraie appartenance y n'est pas utilisée)
X, _ = make_blobs(n_samples=500, centers=4, cluster_std=1.0, random_state=42)
km = KMeans(n_clusters=4, random_state=0)
labels = km.fit_predict(X) # un numéro de cluster par point : 0, 1, 2 ou 3
print(km.cluster_centers_) # coordonnées des 4 centres
print(km.inertia_) # inertie finale (environ 949)
print(km.predict([[0, 0]])) # affecter un nouveau point
Remarquez que fit ne reçoit pas de y. Les numéros de cluster sont arbitraires : le « cluster 2 » n’est pas plus grand ou meilleur que le « cluster 0 », et relancer avec une autre graine peut permuter les numéros.
Initialisation et reproductibilité
K-means peut converger vers une solution moyenne selon les centres de départ. Le paramètre n_init lance plusieurs initialisations et garde celle de plus faible inertie. Depuis scikit-learn 1.4, sa valeur par défaut est "auto" (une seule initialisation avec k-means++). Fixez random_state pour obtenir des résultats reproductibles.
L’échelle des features compte
K-means calcule des distances euclidiennes : une feature exprimée en milliers domine celles exprimées en unités. Sur le jeu Wine, la proline (des centaines à plus de 1 600) écrase les autres mesures.
from sklearn.datasets import load_wine
from sklearn.pipeline import make_pipeline
from sklearn.preprocessing import StandardScaler
from sklearn.metrics import adjusted_rand_score
X, y = load_wine(return_X_y=True) # y ne sert qu'à juger le résultat a posteriori
brut = KMeans(n_clusters=3, random_state=0).fit_predict(X)
norme = make_pipeline(StandardScaler(), KMeans(n_clusters=3, random_state=0)).fit_predict(X)
print(adjusted_rand_score(y, brut)) # environ 0.37
print(adjusted_rand_score(y, norme)) # environ 0.90
L’indice de Rand ajusté (ARI) compare deux partitions : 1 = identiques, environ 0 = accord dû au hasard. Il ne sert que lorsque l’on dispose, à titre de contrôle, de vraies étiquettes ; en situation réelle, on n’en a généralement pas.
Limites de K-means
- k doit être choisi à l’avance (leçon suivante) ;
- il suppose des groupes compacts, de forme à peu près sphérique et de tailles comparables ;
- il est sensible aux valeurs extrêmes, qui déplacent les centres ;
- chaque point est affecté à un cluster, même s’il est isolé.
Pour des groupes de formes complexes ou en présence de bruit, on utilisera DBSCAN ou le clustering hiérarchique (leçon 3).
Exercices
Les solutions et les tests restent sur le serveur. Dans l'espace étudiant, ton code est exécuté et corrigé, et le tuteur donne des indices avant la solution.
Premier K-means
Appliquez
KMeans(n_clusters=3, random_state=0)surX. Stockez le modèle danskm, les étiquettes danslabelset l’inertie dansinertie.from sklearn.datasets import make_blobs from sklearn.cluster import KMeans X, _ = make_blobs(n_samples=300, centers=3, cluster_std=0.8, random_state=1) km = ... labels = ... inertie = ...Standardiser avant de regrouper
Sur le jeu Wine, construisez
pipe, un pipelineStandardScaler+KMeans(n_clusters=3, random_state=0), et stockez ses étiquettes danslabels_norme. Calculez ensuite l’ARI avec les vraies classes (ari_norme) et comparez avec l’ARI d’unKMeans(n_clusters=3, random_state=0)sur les données brutes (ari_brut).from sklearn.datasets import load_wine from sklearn.cluster import KMeans from sklearn.pipeline import make_pipeline from sklearn.preprocessing import StandardScaler from sklearn.metrics import adjusted_rand_score X, y = load_wine(return_X_y=True) pipe = ... labels_norme = ... ari_norme = ... ari_brut = ...
Quiz de fin de leçon
Que minimise K-means ?
- Le nombre de clusters
- L'inertie : somme des distances au carré aux centres
- L'accuracy
- La variance expliquée
Pourquoi standardiser les données avant K-means ?
- Pour réduire le nombre de clusters
- Parce que les distances sont dominées par les features de grande échelle
- Parce que KMeans refuse les données brutes
- Pour obtenir des numéros de cluster ordonnés
Que reçoit la méthode fit de KMeans ?
- X et y
- Seulement X
- Seulement y
- Le nombre de clusters
La suite du cours
- Choisir le nombre de clusters : coude et silhouette15 min
- DBSCAN et clustering hiérarchique15 min
- Réduire la dimension avec l'ACP (PCA)15 min
- Visualiser et interpréter des segments20 min