Une courbe qui montre comment la prédiction d'un modèle évolue quand une variable varie, toutes les autres étant prises telles qu'elles sont dans les données. On voit d'un coup d'œil si l'effet est linéaire, à seuil, en U ou nul. C'est le meilleur moyen de vérifier qu'un modèle opaque a appris quelque chose de cohérent avec le métier.
Pour savoir comment l'âge joue sur le tarif, on reprend tout le portefeuille et on fait comme si chaque assuré avait 18 ans, puis 19, puis 20… En moyennant les tarifs à chaque âge, on obtient la courbe de l'effet de l'âge, le reste du profil étant inchangé.
Par exemple tous les âges de 18 à 84 ans, ou 20 à 50 points régulièrement espacés pour une variable continue.
Pour chaque âge de la grille, on remplace l'âge de tous les contrats par cette valeur, sans toucher aux autres variables, et on fait prédire le modèle.
La moyenne des prédictions à chaque âge donne la courbe PDP. Les courbes individuelles, une par contrat (courbes ICE), montrent si tout le monde suit la moyenne.
Une Random Forest prédit le nombre de sinistres par an de 6 000 contrats, d'après l'âge, la puissance, la zone et le bonus-malus. Avant de s'en servir pour tarifer, l'actuaire veut vérifier ce que le modèle a appris sur l'âge.
Sur le jeu d'exemple, la fréquence prédite est proche de 0,37 à 0,39 sinistre par an entre 21 et 24 ans, chute à 0,19 à 25 ans, puis se stabilise entre 0,10 et 0,12 à partir de 30 ans. Le modèle a appris un seuil net à 25 ans, que l'actuaire peut traduire en tranche tarifaire.
La courbe doit avoir un sens métier. Aux extrémités, elle repose sur peu de contrats : ici, la valeur à 18 ans (0,29) est plus basse qu'à 21 ans, probablement un effet de bord du modèle, dont il faut se méfier. Les courbes ICE confirment que presque tous les contrats voient leur fréquence baisser entre 22 et 50 ans, avec une ampleur variable.
Noms donnés pour R (pdp) et Python (scikit-learn, module inspection).
Les valeurs auxquelles on force la variable. Pour l'âge, chaque année ; pour un montant, 20 à 50 points. Par défaut, scikit-learn coupe les 5 % extrêmes (percentiles).
Les courbes individuelles révèlent les interactions : si elles se croisent ou divergent, l'effet dépend d'autres variables et la moyenne seule est trompeuse.
Le calcul coûte une prédiction de toute la base par point de grille. Sur de gros volumes, un échantillon de quelques milliers de lignes suffit.
Pour un classifieur, choisir entre probabilité et log-odds. En probabilité, la lecture est plus naturelle, mais les effets semblent plus faibles près de 0 et de 1.
# Fréquence de sinistres selon l'âge : dépendance partielle (PDP) en R
library(ranger)
library(pdp)
sin <- read.csv("sinistres.csv")
sin$zone <- factor(sin$zone)
sin$frequence <- sin$nb_sinistres / sin$exposition # fréquence annuelle
# Modèle boîte noire ; les contrats sont tirés en proportion de leur exposition
modele <- ranger(frequence ~ age_conducteur + puissance_cv + zone + bonus_malus, data = sin,
num.trees = 300, min.node.size = 50, case.weights = sin$exposition, seed = 42)
# PDP : on donne à TOUS les contrats l'âge 18, puis 19... 84 ans, et on moyenne les prédictions
courbe <- partial(modele, pred.var = "age_conducteur", train = sin,
pred.grid = data.frame(age_conducteur = 18:84))
print(round(courbe[courbe$age_conducteur %in% c(18, 21, 24, 25, 26, 30, 40, 50, 60, 70, 84), ], 3))
# ICE : la même chose contrat par contrat (200 contrats), à 22 ans puis à 50 ans
ice <- partial(modele, pred.var = "age_conducteur", train = sin[1:200, ], ice = TRUE,
pred.grid = data.frame(age_conducteur = c(22, 50)))
a22 <- ice[ice$age_conducteur == 22, ]
a50 <- ice[ice$age_conducteur == 50, ]
ecart <- a22$yhat[order(a22$yhat.id)] - a50$yhat[order(a50$yhat.id)]
cat("Surcroît de fréquence à 22 ans vs 50 ans, déciles 1, 5 et 9 :", round(quantile(ecart, c(0.1, 0.5, 0.9)), 3), "\n")
# Fréquence de sinistres selon l'âge : dépendance partielle (PDP) en Python
import pandas as pd
from sklearn.ensemble import RandomForestRegressor
from sklearn.inspection import partial_dependence
sin = pd.read_csv("sinistres.csv")
X = pd.get_dummies(sin[["age_conducteur", "puissance_cv", "zone", "bonus_malus"]]).astype(float)
y = sin["nb_sinistres"] / sin["exposition"] # fréquence annuelle
# Modèle boîte noire, pondéré par l'exposition (un contrat de 3 mois compte moins)
modele = RandomForestRegressor(n_estimators=300, min_samples_leaf=50, random_state=42)
modele.fit(X, y, sample_weight=sin["exposition"])
# PDP : on donne à TOUS les contrats l'âge 18, puis 19... 84 ans, et on moyenne les prédictions
pdp = partial_dependence(modele, X, features=["age_conducteur"], percentiles=(0, 1), grid_resolution=100)
courbe = pd.Series(pdp["average"][0], index=pdp["grid_values"][0].astype(int))
print(courbe.loc[[18, 21, 24, 25, 26, 30, 40, 50, 60, 70, 84]].round(3))
# ICE : la même courbe contrat par contrat (200 contrats), pour vérifier que tous suivent la moyenne
ice = partial_dependence(modele, X.iloc[:200], features=["age_conducteur"], kind="individual",
percentiles=(0, 1), grid_resolution=100)
ages = ice["grid_values"][0] # âges présents parmi ces 200 contrats
ecart = pd.Series(ice["individual"][0][:, ages == 22][:, 0] - ice["individual"][0][:, ages == 50][:, 0])
print("Surcroît de fréquence à 22 ans vs 50 ans, déciles 1, 5 et 9 :", ecart.quantile([0.1, 0.5, 0.9]).round(3).tolist())
C'est une courbe qui montre la prédiction moyenne d'un modèle en fonction d'une variable, les autres variables gardant leurs valeurs observées. Elle a été proposée par Friedman en 2001 pour les modèles de gradient boosting et s'applique à tout modèle.
La PDP trace la moyenne des prédictions pour chaque valeur de la variable. Les courbes ICE (Individual Conditional Expectation) tracent la même chose individu par individu. La PDP est la moyenne des courbes ICE : quand celles-ci ont des formes différentes, la PDP cache une interaction.
Quand la variable étudiée est fortement corrélée à d'autres. La PDP crée alors des combinaisons irréalistes, comme un conducteur de 20 ans avec 30 ans de permis. Les courbes ALE (Accumulated Local Effects) ne comparent que des individus proches de la réalité et restent fiables dans ce cas.
Dit quelles variables comptent. La PDP montre ensuite comment elles jouent.
Voir la fiche → l'effet individu par individuLes graphiques de dépendance SHAP donnent une information proche, contrat par contrat, et montrent la dispersion des effets autour de la moyenne.
Voir la fiche → la courbe intégrée au modèleUn modèle lisible dont chaque effet est déjà une courbe. Parfois suffisant, sans boîte noire.
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