La version de K-means qui met à jour ses centres à partir de petits paquets de lignes tirés au hasard, au lieu de relire toute la base à chaque tour. Sur des millions de clients, elle va bien plus vite et peut même apprendre à partir d'un fichier lu morceau par morceau, pour des groupes très proches de ceux de K-means.
Pour placer 4 points de rendez-vous dans une ville, inutile d'interroger tous les habitants à chaque ajustement. On interroge quelques centaines de passants, on déplace un peu les points, et on recommence avec d'autres passants.
Comme K-means, souvent par tirage espacé (k-means++), sur un échantillon de la base.
À chaque itération, quelques centaines de clients seulement. Chacun est rattaché au centre le plus proche.
Chaque centre se rapproche des clients du paquet qui lui sont rattachés, d'un pas qui diminue à mesure qu'il a déjà vu beaucoup de clients. On enchaîne les paquets jusqu'à stabilité.
Panier moyen, achats par mois, jours depuis le dernier achat, nombre de catégories, part d'achats en promotion. Ici 2 000 clients pour l'exemple ; en réalité des millions, stockés dans un fichier ou une base.
Le code Python lit le fichier par morceaux de 500 lignes et met à jour les centres à chaque morceau. Les 4 segments obtenus sont quasi identiques à ceux d'un K-means classique : accord (ARI) de 0,993 sur 1.
L'indice de Rand ajusté (ARI) compare deux segmentations : 1 si elles sont identiques, 0 si l'accord est dû au hasard. On vérifie une fois sur un échantillon que le mini-batch rejoint K-means, puis on profite du gain de temps sur la base entière.
Noms donnés pour R (ClusterR) et Python (scikit-learn).
Le nombre de groupes k. On le choisit sur un échantillon, par la méthode du coude ou la silhouette, comme pour K-means.
Le nombre de lignes par paquet, 1 024 par défaut dans scikit-learn, 10 dans ClusterR. Des paquets plus grands donnent des centres plus stables ; quelques centaines à quelques milliers est un bon compromis.
Le nombre de départs différents, pour ne pas rester bloqué sur une mauvaise solution. En mode flux avec partial_fit, il n'y a qu'un départ : les premiers paquets comptent beaucoup.
Obligatoire, comme pour K-means. En flux, on apprend moyennes et écarts-types sur un échantillon représentatif, puis on les applique à chaque paquet.
# Segmentation clients par paquets : Mini-batch K-means en R
library(ClusterR)
clients <- read.csv("clients_segmentation.csv")
variables <- c("panier_moyen", "achats_par_mois", "recence_jours", "nb_categories", "part_promo")
X <- scale(clients[, variables])
# Chaque itération ne regarde qu'un paquet de 256 clients tirés au hasard
modele <- MiniBatchKmeans(X, clusters = 4, batch_size = 256, num_init = 10, max_iters = 100,
initializer = "kmeans++", seed = 42)
clients$segment <- as.vector(predict_MBatchKMeans(X, modele$centroids))
# Comparaison avec un K-means classique sur toute la base
set.seed(42)
km <- kmeans(X, centers = 4, nstart = 10)
print(table(mini_batch = clients$segment, kmeans = km$cluster))
# Profil moyen de chaque segment, en unités d'origine
print(round(aggregate(clients[, variables], by = list(segment = clients$segment), FUN = mean), 2))
# Segmentation clients par paquets : Mini-batch K-means en Python
import pandas as pd
from sklearn.preprocessing import StandardScaler
from sklearn.cluster import KMeans, MiniBatchKMeans
from sklearn.metrics import adjusted_rand_score
variables = ["panier_moyen", "achats_par_mois", "recence_jours", "nb_categories", "part_promo"]
# Standardisation apprise sur un échantillon de 1 000 clients
echantillon = pd.read_csv("clients_segmentation.csv", nrows=1000)
echelle = StandardScaler().fit(echantillon[variables])
# Le fichier est lu par paquets de 500 lignes, jamais chargé en entier
modele = MiniBatchKMeans(n_clusters=4, random_state=42)
for passe in range(10):
for paquet in pd.read_csv("clients_segmentation.csv", chunksize=500):
modele.partial_fit(echelle.transform(paquet[variables]))
# Comparaison avec un K-means classique sur toute la base
clients = pd.read_csv("clients_segmentation.csv")
X = echelle.transform(clients[variables])
segments_mb = modele.predict(X)
segments_km = KMeans(n_clusters=4, n_init=10, random_state=42).fit_predict(X)
print("Accord avec K-means (ARI, 1 = identique) :", round(adjusted_rand_score(segments_km, segments_mb), 3))
print(clients.groupby(segments_mb)[variables].mean().round(2))
K-means recalcule les centres à partir de toute la base à chaque itération. Mini-batch K-means les met à jour à partir de petits paquets tirés au hasard. Il est beaucoup plus rapide sur de gros volumes, pour des groupes légèrement moins compacts.
Très proches en général, mais pas identiques : les centres se stabilisent autour de la même solution avec un peu de bruit. Sur le jeu d'exemple, l'accord mesuré par l'ARI est de 0,993. On le vérifie sur un échantillon avant de passer à la base entière.
Avec partial_fit dans scikit-learn : on lit le fichier par morceaux, par exemple avec l'option chunksize de pandas, et on met à jour le modèle morceau par morceau. La standardisation est apprise au préalable sur un échantillon.
Relit toute la base à chaque tour. Un peu plus précis, parfait jusqu'à quelques centaines de milliers de lignes.
Voir la fiche → l'autre option grand volumeRésume la base en une passe dans un arbre de micro-groupes, puis les regroupe. Adapté aux flux et aux très grandes bases.
Voir la fiche → à l'opposéDes centres qui sont de vrais clients. Plus robuste, mais réservé aux bases de taille modeste.
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