Le K-means ne sait traiter que des chiffres, le K-modes que des catégories. Le K-prototypes combine les deux : une distance euclidienne pour les variables numériques, un comptage des désaccords pour les catégorielles. C'est la méthode directe pour segmenter un portefeuille ou une base clients qui mélange âges, montants, zones et types de contrat.
Un recruteur qui compare des candidats : il mesure l'écart d'âge et d'années d'expérience, puis ajoute une pénalité fixe chaque fois que le diplôme ou la région diffère.
Chaque prototype a une valeur pour chaque variable numérique et une modalité pour chaque variable catégorielle, par exemple 45 ans, 9 CV, zone urbaine.
La distance additionne l'écart numérique (somme des carrés) et un poids fixe, gamma ou lambda, par catégorie en désaccord.
Chaque prototype prend la moyenne de ses membres pour les chiffres et la modalité la plus fréquente pour les catégories. On itère jusqu'à ce que les affectations ne bougent plus.
Âge du conducteur, puissance du véhicule, coefficient bonus-malus, et zone de circulation (urbaine, périurbaine, rurale). La sinistralité n'entre pas dans le calcul : elle sert à lire les segments ensuite.
Chaque contrat est rangé dans un segment décrit par un âge moyen, une puissance moyenne, un bonus-malus moyen et une zone dominante. L'actuaire compare ensuite la fréquence de sinistres de chaque segment pour orienter la tarification ou la prévention.
La qualité statistique se juge au coût total de la partition, comparé pour plusieurs valeurs de k. La qualité métier se juge à l'écart de fréquence de sinistres par année d'exposition entre segments. Des segments de sinistralité identique n'apportent rien au tarif.
Noms donnés pour R (clustMixType) et Python (kmodes). Les variables numériques sont standardisées avant tout.
Nombre de segments. On compare le coût total pour plusieurs valeurs (méthode du coude), puis on retient la valeur qui donne des segments nommables et utiles au métier.
Poids d'un désaccord sur une catégorie face aux écarts numériques. Trop faible, la zone est quasi ignorée. Trop fort, les segments se calquent sur les zones. Les deux packages l'estiment par défaut à partir des données ; on le fixe à la main si le métier l'exige.
Nombre de départs différents. Le résultat dépend des prototypes initiaux : on garde le meilleur de plusieurs essais. 5 à 10 suffisent en général.
# Portefeuille auto : K-prototypes en R
library(clustMixType)
sinistres <- read.csv("sinistres.csv")
numeriques <- c("age_conducteur", "puissance_cv", "bonus_malus")
# Variables numériques standardisées, la zone reste un facteur
X <- data.frame(scale(sinistres[, numeriques]), zone = factor(sinistres$zone))
set.seed(42)
kp <- kproto(X, k = 4, nstart = 5, verbose = FALSE)
cat("Poids donné à la zone (lambda) :", round(kp$lambda, 2), "\n")
# Profil de chaque segment en unités d'origine, et répartition par zone
sinistres$segment <- kp$cluster
print(aggregate(cbind(age_conducteur, puissance_cv, bonus_malus) ~ segment, data = sinistres, FUN = mean))
print(table(sinistres$segment, sinistres$zone))
# Fréquence de sinistres par année d'exposition, segment par segment
frequence <- tapply(sinistres$nb_sinistres, sinistres$segment, sum) /
tapply(sinistres$exposition, sinistres$segment, sum)
print(round(frequence, 3))
# Portefeuille auto : K-prototypes en Python
import pandas as pd
from kmodes.kprototypes import KPrototypes
sinistres = pd.read_csv("sinistres.csv")
numeriques = ["age_conducteur", "puissance_cv", "bonus_malus"]
# Variables numériques standardisées, la zone reste une catégorie
X = (sinistres[numeriques] - sinistres[numeriques].mean()) / sinistres[numeriques].std()
X["zone"] = sinistres["zone"]
# categorical : position de la colonne catégorielle ; gamma estimé si non fourni
kp = KPrototypes(n_clusters=4, init="Cao", n_init=5, random_state=42)
sinistres["segment"] = kp.fit_predict(X.to_numpy(), categorical=[3])
print("Poids donné à la zone (gamma) :", round(kp.gamma, 2))
# Profil de chaque segment et fréquence de sinistres par année d'exposition
profil = sinistres.groupby("segment").agg(contrats=("zone", "size"), age=("age_conducteur", "mean"),
puissance=("puissance_cv", "mean"), bonus_malus=("bonus_malus", "mean"),
zone=("zone", lambda z: z.mode()[0]),
sinistres=("nb_sinistres", "sum"), exposition=("exposition", "sum"))
profil["frequence"] = profil["sinistres"] / profil["exposition"]
print(profil.round(2).to_string())
Le K-means traite des variables numériques avec des moyennes. Le K-modes traite des variables catégorielles avec des modalités dominantes et un comptage des désaccords. Le K-prototypes, proposé par Zhexue Huang en 1997, combine les deux dans une seule distance.
Par défaut, les packages l'estiment à partir de la dispersion des données. On vérifie ensuite que la variable catégorielle joue un rôle raisonnable : si chaque segment contient les zones dans les mêmes proportions que la base, son poids est trop faible pour compter.
Oui, pour les variables numériques. Sinon une variable exprimée en grandes unités, comme un montant en euros, domine la distance. La standardisation rend aussi le poids des catégories plus facile à interpréter.
Même algorithme, sans catégories. Il faut alors encoder la zone en colonnes 0/1, ce qui pèse mal dans la distance.
Voir la fiche → l'alternative robusteAvec une distance de Gower, il accepte aussi les données mixtes et résiste mieux aux extrêmes. Plus lent sur les grandes bases.
Voir la fiche → l'approche factorielleRésume d'abord les variables qualitatives en axes numériques, sur lesquels on lance ensuite une classification.
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