La tarification en assurance Multirisque Habitation (MRH) consiste à déterminer une prime adaptée au niveau de risque présenté par chaque assuré.
L’objectif de ce projet est de construire un modèle statistique permettant d’estimer le coût annuel des sinistres à partir de différentes caractéristiques du contrat et du logement.
Nous utiliserons une régression linéaire multiple afin d’étudier l’influence de plusieurs variables explicatives sur le coût annuel des sinistres.
Les principales étapes seront :
Les données utilisées sont simulées à des fins pédagogiques.
Nous chargeons les packages nécessaires au traitement des données, à la visualisation et à la modélisation statistique.
knitr::opts_chunk$set(
echo = TRUE,
warning = FALSE,
message = FALSE
)
library(kableExtra)
library(tidyverse)
library(knitr)
library(lmtest)
library(car)
library(corrplot)
set.seed(2026)
tidyverse : manipulation, nettoyage et visualisation des
données.
knitr : création et mise en forme des tableaux dans le
rapport.
lmtest : réalisation de tests statistiques sur le modèle
de régression.
car : diagnostic du modèle, notamment l’analyse de la
multicolinéarité avec le VIF.
set.seed() : permet d’obtenir les mêmes résultats lors
de chaque simulation.
kableExtra : permet de mettre en forme et d’améliorer
l’apparence des tableaux générés avec kable() dans R
Markdown.
Nous considérons un portefeuille fictif de 5 000 contrats.
Les variables utilisées sont :
age : âge du souscripteur ;surface : surface du logement ;capital_mobilier : capital mobilier assuré ;zone : niveau de risque géographique ;type_logement : appartement ou maison ;anciennete : ancienneté du logement ;alarme : présence ou non d’une alarme ;nb_pieces : nombre de pièces ;sinistres_3ans : nombre de sinistres observés au cours
des trois dernières années ;cout_sinistre : coût annuel moyen des sinistres.n <- 5000
mrh <- data.frame(
id = 1:n,
age = pmin(
pmax(
round(rnorm(n, mean = 48, sd = 15)),
20
),
85
),
surface = pmax(
round(rnorm(n, mean = 82, sd = 30), 1),
25
),
capital_mobilier = pmax(
round(rlnorm(n, log(35000), 0.55)),
5000
),
zone = sample(
c("Faible", "Moyenne", "Forte"),
n,
replace = TRUE,
prob = c(0.45, 0.40, 0.15)
),
type_logement = sample(
c("Appartement", "Maison"),
n,
replace = TRUE,
prob = c(0.60, 0.40)
),
anciennete = pmax(
round(rnorm(n, 28, 18)),
0
),
alarme = sample(
c("Non", "Oui"),
n,
replace = TRUE,
prob = c(0.72, 0.28)
),
nb_pieces = pmax(
round(rnorm(n, 3.5, 1.3)),
1
),
sinistres_3ans = rpois(n, lambda = 0.55)
)
Nous construisons maintenant le coût annuel moyen des sinistres.
Dans notre simulation, nous supposons que le coût dépend notamment :
effet_zone <- ifelse(
mrh$zone == "Faible",
0,
ifelse(
mrh$zone == "Moyenne",
55,
125
)
)
effet_logement <- ifelse(
mrh$type_logement == "Maison",
75,
0
)
effet_alarme <- ifelse(
mrh$alarme == "Oui",
-35,
0
)
mrh$cout_sinistre <- 230 + 2.8 * mrh$surface + 0.0045 * mrh$capital_mobilier + 18 * mrh$sinistres_3ans + 1.4 * mrh$anciennete + 10 * mrh$nb_pieces + 0.7 * mrh$age + effet_zone + effet_logement + effet_alarme + rnorm(n, 0, 115)
mrh$cout_sinistre <- pmax(
mrh$cout_sinistre,
20
)
La variable zone représente le niveau de risque associé au logement
assuré. Elle permet de distinguer les contrats selon trois catégories de
risque : Faible, Moyenne et
Forte.
Cette classification permet de prendre en compte le fait que certains logements peuvent présenter un niveau de risque différent des autres. Dans notre modèle de tarification, cette variable sera utilisée comme une variable qualitative afin d’étudier son influence sur le coût des sinistres.
Nous définissons donc zone comme une variable de type facteur, en précisant l’ordre des différentes catégories :
mrh$zone <- factor(
mrh$zone,
levels = c(
"Faible",
"Moyenne",
"Forte"
)
)
mrh$type_logement <- factor(
mrh$type_logement
)
mrh$alarme <- factor(
mrh$alarme
)
head(mrh,5)
## id age surface capital_mobilier zone type_logement anciennete alarme
## 1 1 56 112.9 27823 Moyenne Maison 0 Non
## 2 2 32 108.3 77862 Forte Maison 31 Non
## 3 3 50 99.5 36481 Faible Appartement 14 Non
## 4 4 47 93.6 12321 Faible Maison 36 Oui
## 5 5 38 41.4 70967 Faible Appartement 18 Oui
## nb_pieces sinistres_3ans cout_sinistre
## 1 6 2 674.8709
## 2 5 1 1305.8634
## 3 4 0 752.3198
## 4 2 0 665.8493
## 5 3 1 693.3925
str(mrh)
## 'data.frame': 5000 obs. of 11 variables:
## $ id : int 1 2 3 4 5 6 7 8 9 10 ...
## $ age : num 56 32 50 47 38 20 37 33 50 41 ...
## $ surface : num 112.9 108.3 99.5 93.6 41.4 ...
## $ capital_mobilier: num 27823 77862 36481 12321 70967 ...
## $ zone : Factor w/ 3 levels "Faible","Moyenne",..: 2 3 1 1 1 2 3 2 2 2 ...
## $ type_logement : Factor w/ 2 levels "Appartement",..: 2 2 1 2 1 1 2 2 1 1 ...
## $ anciennete : num 0 31 14 36 18 42 8 37 0 41 ...
## $ alarme : Factor w/ 2 levels "Non","Oui": 1 1 1 2 2 2 1 2 1 1 ...
## $ nb_pieces : num 6 5 4 2 3 4 5 3 3 3 ...
## $ sinistres_3ans : int 2 1 0 0 1 0 1 0 2 0 ...
## $ cout_sinistre : num 675 1306 752 666 693 ...
statistiques <- summary(mrh)
kable(
as.data.frame(statistiques),
format = "html",
caption = "Statistiques descriptives des variables de la base MRH",
digits = 2,
align = "c"
) %>%
kable_styling(
bootstrap_options = c("striped", "hover", "condensed"),
full_width = FALSE,
position = "center"
)
| Var1 | Var2 | Freq |
|---|---|---|
| id | Min. : 1 | |
| id | 1st Qu.:1251 | |
| id | Median :2500 | |
| id | Mean :2500 | |
| id | 3rd Qu.:3750 | |
| id | Max. :5000 | |
| age | Min. :20.00 | |
| age | 1st Qu.:38.00 | |
| age | Median :48.00 | |
| age | Mean :48.03 | |
| age | 3rd Qu.:58.00 | |
| age | Max. :85.00 | |
| surface | Min. : 25.00 | |
| surface | 1st Qu.: 62.20 | |
| surface | Median : 82.05 | |
| surface | Mean : 82.75 | |
| surface | 3rd Qu.:102.60 | |
| surface | Max. :197.50 | |
| capital_mobilier | Min. : 5000 | |
| capital_mobilier | 1st Qu.: 24329 | |
| capital_mobilier | Median : 35056 | |
| capital_mobilier | Mean : 40909 | |
| capital_mobilier | 3rd Qu.: 51292 | |
| capital_mobilier | Max. :403452 | |
| zone | Faible :2222 | |
| zone | Moyenne:2010 | |
| zone | Forte : 768 | |
| zone | NA | |
| zone | NA | |
| zone | NA | |
| type_logement | Appartement:2947 | |
| type_logement | Maison :2053 | |
| type_logement | NA | |
| type_logement | NA | |
| type_logement | NA | |
| type_logement | NA | |
| anciennete | Min. : 0.00 | |
| anciennete | 1st Qu.:16.00 | |
| anciennete | Median :29.00 | |
| anciennete | Mean :28.88 | |
| anciennete | 3rd Qu.:41.00 | |
| anciennete | Max. :94.00 | |
| alarme | Non:3579 | |
| alarme | Oui:1421 | |
| alarme | NA | |
| alarme | NA | |
| alarme | NA | |
| alarme | NA | |
| nb_pieces | Min. :1.00 | |
| nb_pieces | 1st Qu.:3.00 | |
| nb_pieces | Median :4.00 | |
| nb_pieces | Mean :3.51 | |
| nb_pieces | 3rd Qu.:4.00 | |
| nb_pieces | Max. :8.00 | |
| sinistres_3ans | Min. :0.0000 | |
| sinistres_3ans | 1st Qu.:0.0000 | |
| sinistres_3ans | Median :0.0000 | |
| sinistres_3ans | Mean :0.5558 | |
| sinistres_3ans | 3rd Qu.:1.0000 | |
| sinistres_3ans | Max. :5.0000 | |
| cout_sinistre | Min. : 273.6 | |
| cout_sinistre | 1st Qu.: 695.0 | |
| cout_sinistre | Median : 813.4 | |
| cout_sinistre | Mean : 825.8 | |
| cout_sinistre | 3rd Qu.: 945.0 | |
| cout_sinistre | Max. :2341.0 |
mean(mrh$cout_sinistre)
## [1] 825.7796
mrh %>%
group_by(zone) %>%
summarise(
`Nombre de contrats` = n(),
`Coût moyen (€)` = mean(cout_sinistre),
`Médiane (€)` = median(cout_sinistre),
`Écart-type (€)` = sd(cout_sinistre)
) %>%
kable(
format = "html",
digits = 2,
caption = "Coût annuel des sinistres par zone",
align = "c"
) %>%
kable_styling(
bootstrap_options = c("striped", "hover", "condensed"),
full_width = FALSE,
position = "center"
)
| zone | Nombre de contrats | Coût moyen (€) | Médiane (€) | Écart-type (€) |
|---|---|---|---|---|
| Faible | 2222 | 783.39 | 772.75 | 189.65 |
| Moyenne | 2010 | 841.38 | 828.75 | 186.21 |
| Forte | 768 | 907.61 | 899.03 | 180.33 |
ggplot(
mrh,
aes(
x = surface,
y = cout_sinistre
)
) +
geom_point(
alpha = 0.25
) +
geom_smooth(
method = "lm",
se = TRUE
) +
labs(
title = "Relation entre la surface et le coût des sinistres",
x = "Surface du logement (m²)",
y = "Coût annuel moyen (€)"
) +
theme_minimal()
On constate dans un premier temps que les logements de grande superficie semblent présenter une fréquence de sinistres plus faible. On observe également une relation entre la surface du logement et le montant des sinistres. Ces premières observations suggèrent que la superficie pourrait constituer une variable explicative pertinente dans la modélisation du coût des sinistres.
ggplot(
mrh,
aes(
x = zone,
y = cout_sinistre
)
) +
geom_boxplot() +
labs(
title = "Distribution du coût annuel selon la zone",
x = "Zone",
y = "Coût annuel moyen (€)"
) +
theme_minimal()
Nous étudions les corrélations entre les variables quantitatives.
variables_num <- mrh %>%
select(
age,
surface,
capital_mobilier,
anciennete,
nb_pieces,
sinistres_3ans,
cout_sinistre
)
matrice_cor <- cor(variables_num)
matrice_cor
## age surface capital_mobilier anciennete
## age 1.000000000 -0.0165931007 0.0224013898 0.008171312
## surface -0.016593101 1.0000000000 -0.0001516193 0.011168398
## capital_mobilier 0.022401390 -0.0001516193 1.0000000000 -0.018782653
## anciennete 0.008171312 0.0111683979 -0.0187826526 1.000000000
## nb_pieces 0.002695129 0.0032078948 0.0076058779 0.008448339
## sinistres_3ans -0.013889191 0.0089135307 0.0010193594 -0.006139641
## cout_sinistre 0.057501474 0.4336410305 0.5804663017 0.127993626
## nb_pieces sinistres_3ans cout_sinistre
## age 0.002695129 -0.013889191 0.05750147
## surface 0.003207895 0.008913531 0.43364103
## capital_mobilier 0.007605878 0.001019359 0.58046630
## anciennete 0.008448339 -0.006139641 0.12799363
## nb_pieces 1.000000000 -0.002021059 0.06856479
## sinistres_3ans -0.002021059 1.000000000 0.06974394
## cout_sinistre 0.068564794 0.069743936 1.00000000
La matrice de corrélation permet de mesurer la force et le sens de la relation linéaire entre les différentes variables quantitatives. Les coefficients sont compris entre -1 et 1 : une valeur proche de 1 indique une relation positive forte, tandis qu’une valeur proche de -1 indique une relation négative forte.
Pour faciliter l’interprétation, nous représentons cette matrice graphiquement :
corrplot( matrice_cor, method = "color", type = "upper", addCoef.col = "black",
tl.col = "black", tl.srt = 45, number.cex = 0.7 )
Le capital mobilier et le coût des sinistres présentent une corrélation positive, ce qui est cohérent : plus la valeur des biens assurés est élevée, plus le montant potentiel d’un sinistre peut être important. De même, la surface du logement est positivement corrélée au coût des sinistres. Les logements plus grands peuvent contenir davantage de biens matériels et présenter des montants de dommages potentiellement plus élevés, ce qui peut expliquer cette relation.
Nous divisons le portefeuille en :
set.seed(2026)
index <- sample(1:nrow(mrh),size = 0.80 * nrow(mrh))
train <- mrh[index, ]
test <- mrh[-index, ]
nrow(train)
## [1] 4000
nrow(test)
## [1] 1000
Nous estimons le modèle :
\[ C_i = \beta_0 + \beta_1 Age_i + \beta_2 Surface_i + \beta_3 Capital_i + \beta_4 Zone_i + \beta_5 Type_i + \beta_6 Anciennete_i + \beta_7 Alarme_i + \beta_8 Pieces_i + \beta_9 Sinistres_i + \epsilon_i \]
où \(C_i\) représente le coût annuel des sinistres.
modele <- lm(
cout_sinistre ~ age + surface + capital_mobilier + zone + type_logement +
anciennete + alarme + nb_pieces + sinistres_3ans,data = train
)
summary(modele)
##
## Call:
## lm(formula = cout_sinistre ~ age + surface + capital_mobilier +
## zone + type_logement + anciennete + alarme + nb_pieces +
## sinistres_3ans, data = train)
##
## Residuals:
## Min 1Q Median 3Q Max
## -408.80 -79.01 0.59 77.65 410.18
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) 2.202e+02 1.079e+01 20.400 < 2e-16 ***
## age 7.257e-01 1.263e-01 5.746 9.80e-09 ***
## surface 2.849e+00 6.191e-02 46.016 < 2e-16 ***
## capital_mobilier 4.571e-03 7.346e-05 62.227 < 2e-16 ***
## zoneMoyenne 5.794e+01 3.959e+00 14.635 < 2e-16 ***
## zoneForte 1.307e+02 5.369e+00 24.340 < 2e-16 ***
## type_logementMaison 7.145e+01 3.698e+00 19.322 < 2e-16 ***
## anciennete 1.507e+00 1.069e-01 14.097 < 2e-16 ***
## alarmeOui -3.574e+01 4.029e+00 -8.870 < 2e-16 ***
## nb_pieces 9.678e+00 1.392e+00 6.952 4.19e-12 ***
## sinistres_3ans 1.621e+01 2.429e+00 6.672 2.87e-11 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 114.8 on 3989 degrees of freedom
## Multiple R-squared: 0.6496, Adjusted R-squared: 0.6487
## F-statistic: 739.6 on 10 and 3989 DF, p-value: < 2.2e-16
Le modèle présente un R² de 63,92 %, ce qui signifie qu’environ 63,9 % de la variabilité du coût des sinistres est expliquée par les variables du modèle.
Le test de Fisher est significatif avec une p-value inférieure à 0,05. Le modèle est donc globalement significatif.
Toutes les variables introduites sont également significatives au seuil de 5 %. On observe notamment une relation positive entre le coût des sinistres et la surface, le capital mobilier, l’ancienneté et le nombre de sinistres passés. À l’inverse, la présence d’une alarme est associée à une diminution du coût estimé des sinistres.
Ces résultats constituent une première analyse qui devra être complétée par les tests de validation du modèle.
coef_table <- summary(modele)$coefficients
kable(
coef_table,
digits = 4,
caption = "Résultats de la régression linéaire"
)
| Estimate | Std. Error | t value | Pr(>|t|) | |
|---|---|---|---|---|
| (Intercept) | 220.1926 | 10.7938 | 20.3999 | 0 |
| age | 0.7257 | 0.1263 | 5.7464 | 0 |
| surface | 2.8489 | 0.0619 | 46.0155 | 0 |
| capital_mobilier | 0.0046 | 0.0001 | 62.2269 | 0 |
| zoneMoyenne | 57.9366 | 3.9589 | 14.6345 | 0 |
| zoneForte | 130.6850 | 5.3692 | 24.3399 | 0 |
| type_logementMaison | 71.4496 | 3.6979 | 19.3216 | 0 |
| anciennete | 1.5072 | 0.1069 | 14.0969 | 0 |
| alarmeOui | -35.7404 | 4.0293 | -8.8702 | 0 |
| nb_pieces | 9.6783 | 1.3922 | 6.9520 | 0 |
| sinistres_3ans | 16.2059 | 2.4290 | 6.6719 | 0 |
Un coefficient positif signifie qu’une augmentation de la variable correspondante est associée à une augmentation du coût attendu, toutes choses égales par ailleurs.
Pour les variables qualitatives, les coefficients sont interprétés relativement à la modalité de référence.
Nous testons :
\[ H_0 : \beta_1 = \beta_2 = ... = \beta_p = 0 \]
contre :
\[ H_1 : \text{au moins un coefficient est différent de zéro}. \]
Le test ANOVA permet d’étudier si les variables explicatives apportent une contribution significative au modèle. Il compare la variabilité expliquée par le modèle à la variabilité résiduelle.
On utilise la fonction anova() pour analyser la
significativité des variables du modèle.
anova(modele)
## Analysis of Variance Table
##
## Response: cout_sinistre
## Df Sum Sq Mean Sq F value Pr(>F)
## age 1 533919 533919 40.525 2.161e-10 ***
## surface 1 27666963 27666963 2099.959 < 2.2e-16 ***
## capital_mobilier 1 51073387 51073387 3876.537 < 2.2e-16 ***
## zone 2 8419263 4209631 319.517 < 2.2e-16 ***
## type_logement 1 4826449 4826449 366.334 < 2.2e-16 ***
## anciennete 1 2630457 2630457 199.655 < 2.2e-16 ***
## alarme 1 1061733 1061733 80.587 < 2.2e-16 ***
## nb_pieces 1 641184 641184 48.667 3.536e-12 ***
## sinistres_3ans 1 586482 586482 44.515 2.871e-11 ***
## Residuals 3989 52555082 13175
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
Une p-value inférieure à 5 % indique que la variable étudiée contribue significativement à l’explication du coût des sinistres.
Le test ANOVA montre que toutes les variables du modèle sont statistiquement significatives, avec des p-values inférieures à 5 %.
On remarque notamment que la surface, le capital mobilier et la zone présentent une contribution importante à l’explication du coût des sinistres.
On peut donc rejeter l’hypothèse nulle \(H_0\) et conclure que les variables introduites apportent une information significative dans l’explication du coût des sinistres.
Chaque coefficient est associé à un test :
\[ H_0 : \beta_j = 0 \]
contre :
\[ H_1 : \beta_j \neq 0. \]
Les résultats sont disponibles dans :
summary(modele)$coefficients
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) 220.192611785 1.079381e+01 20.399898 4.522217e-88
## age 0.725742808 1.262959e-01 5.746370 9.798970e-09
## surface 2.848947161 6.191276e-02 46.015510 0.000000e+00
## capital_mobilier 0.004570936 7.345591e-05 62.226934 0.000000e+00
## zoneMoyenne 57.936587456 3.958893e+00 14.634541 2.786212e-47
## zoneForte 130.685026822 5.369177e+00 24.339864 3.997985e-122
## type_logementMaison 71.449551157 3.697907e+00 19.321620 1.379989e-79
## anciennete 1.507155949 1.069141e-01 14.096892 4.462974e-44
## alarmeOui -35.740414282 4.029260e+00 -8.870219 1.081110e-18
## nb_pieces 9.678291612 1.392152e+00 6.952035 4.188210e-12
## sinistres_3ans 16.205946063 2.428972e+00 6.671936 2.871449e-11
La p-value permet de mesurer l’évidence statistique contre l’hypothèse d’un coefficient nul.
Nous commençons par examiner graphiquement les résidus.
qqnorm(
residuals(modele),
main = "QQ-plot des résidus"
)
qqline(
residuals(modele)
)
Nous réalisons également un test de Shapiro-Wilk sur un échantillon de résidus.
set.seed(2026)
residus_test <- sample(
residuals(modele),
500
)
shapiro.test(
residus_test
)
##
## Shapiro-Wilk normality test
##
## data: residus_test
## W = 0.99736, p-value = 0.6112
Le test de Shapiro-Wilk donne une statistique (W=0{,}99765) et une p-value de (0{,}7141). Comme cette p-value est supérieure au seuil de 5 %, nous ne rejetons pas l’hypothèse nulle de normalité des résidus.
Ainsi, les résidus peuvent être considérés comme compatibles avec une distribution normale. L’hypothèse de normalité des résidus est donc vérifiée pour le modèle.
L’hypothèse d’homoscédasticité signifie :
\[ Var(\epsilon_i) = \sigma^2. \]
Nous utilisons le test de Breusch-Pagan.
bptest(modele)
##
## studentized Breusch-Pagan test
##
## data: modele
## BP = 6.9278, df = 10, p-value = 0.7322
Le test de Breusch-Pagan donne une statistique \(BP=8{,}4532\) et une p-value de \(0{,}5847\). Comme cette p-value est supérieure au seuil de 5 %, nous ne rejetons pas l’hypothèse nulle d’homoscédasticité.
On peut donc considérer que la variance des résidus est constante. L’hypothèse d’homoscédasticité des résidus est ainsi respectée pour le modèle.
Nous utilisons le Variance Inflation Factor (VIF).
vif(modele)
## GVIF Df GVIF^(1/(2*Df))
## age 1.001967 1 1.000983
## surface 1.001538 1 1.000769
## capital_mobilier 1.002291 1 1.001145
## zone 1.005908 2 1.001474
## type_logement 1.001034 1 1.000517
## anciennete 1.002492 1 1.001245
## alarme 1.003348 1 1.001673
## nb_pieces 1.001772 1 1.000886
## sinistres_3ans 1.000963 1 1.000481
Un VIF élevé peut signaler une forte corrélation entre certaines variables explicatives.
plot(
fitted(modele),
residuals(modele),
xlab = "Valeurs ajustées",
ylab = "Résidus",
main = "Résidus en fonction des valeurs ajustées"
)
abline(
h = 0,
lty = 2
)
Nous utilisons la distance de Cook.
cook <- cooks.distance(
modele
)
plot(
cook,
type = "h",
main = "Distance de Cook",
xlab = "Observation",
ylab = "Distance de Cook"
)
abline(
h = 4 / nrow(train),
lty = 2
)
test$prediction <- predict(
modele,
newdata = test
)
test$prediction <- pmax(
test$prediction,
0
)
head(
test[
,
c(
"cout_sinistre",
"prediction"
)
]
)
## cout_sinistre prediction
## 1 674.8709 929.5253
## 6 632.4885 659.1775
## 17 755.7494 867.2672
## 26 797.4414 826.3638
## 34 731.5580 774.2729
## 36 768.4072 822.3726
Nous calculons trois indicateurs :
\[ MAE = \frac{1}{n} \sum_{i=1}^{n} |Y_i-\hat{Y_i}| \]
\[ RMSE = \sqrt{ \frac{1}{n} \sum_{i=1}^{n} (Y_i-\hat{Y_i})^2 } \]
\[ MAPE = \frac{100}{n} \sum_{i=1}^{n} \left| \frac{Y_i-\hat{Y_i}}{Y_i} \right| \]
MAE <- mean(
abs(
test$cout_sinistre -
test$prediction
)
)
RMSE <- sqrt(
mean(
(
test$cout_sinistre -
test$prediction
)^2
)
)
MAPE <- mean(
abs(
(
test$cout_sinistre -
test$prediction
) /
test$cout_sinistre
)
) * 100
performance <- data.frame(
Indicateur = c(
"MAE",
"RMSE",
"MAPE"
),
Valeur = c(
MAE,
RMSE,
MAPE
)
)
kable(
performance,
digits = 2
)
| Indicateur | Valeur |
|---|---|
| MAE | 89.96 |
| RMSE | 112.39 |
| MAPE | 11.67 |
Sur l’échantillon de test, le modèle présente une MAE de 91,31 €, ce qui signifie que l’erreur absolue moyenne entre le coût réel et le coût prédit est d’environ 91 €.
La RMSE est de 116,48 €. Elle est supérieure à la MAE, ce qui indique que certaines erreurs de prédiction sont plus importantes et pénalisent davantage la RMSE.
Enfin, le MAPE est de 12,40 %, ce qui signifie que l’erreur absolue moyenne en pourcentage est d’environ 12,4 %. Ces indicateurs montrent que le modèle fournit des prédictions relativement proches des coûts observés sur l’échantillon de test.
ggplot(
test,
aes(
x = cout_sinistre,
y = prediction
)
) +
geom_point(
alpha = 0.30
) +
geom_abline(
slope = 1,
intercept = 0,
linetype = "dashed"
) +
labs(
title = "Coût observé versus coût prédit",
x = "Coût observé (€)",
y = "Coût prédit (€)"
) +
theme_minimal()
Dans cette approche simplifiée, nous assimilons le coût annuel prédit au coût pur.
\[ Prime\ pure_i = \widehat{C_i} \]
test$prime_pure <- test$prediction
summary(
test$prime_pure
)
## Min. 1st Qu. Median Mean 3rd Qu. Max.
## 422.1 726.5 822.0 835.1 922.9 1635.6
Nous ajoutons plusieurs chargements :
| Chargement | Taux |
|---|---|
| Sécurité | 10 % |
| Gestion | 12 % |
| Acquisition | 8 % |
| Marge | 5 % |
Ainsi :
\[ Prime = Prime\ pure \times (1+10\%+12\%+8\%+5\%) \]
soit :
\[ Prime = Prime\ pure \times 1.35 \]
test$prime_commerciale <-
test$prime_pure * 1.35
head(
test[
,
c(
"id",
"zone",
"surface",
"cout_sinistre",
"prime_pure",
"prime_commerciale"
)
]
)
## id zone surface cout_sinistre prime_pure prime_commerciale
## 1 1 Moyenne 112.9 674.8709 929.5253 1254.8591
## 6 6 Moyenne 68.1 632.4885 659.1775 889.8896
## 17 17 Forte 110.7 755.7494 867.2672 1170.8108
## 26 26 Faible 25.0 797.4414 826.3638 1115.5911
## 34 34 Faible 52.9 731.5580 774.2729 1045.2684
## 36 36 Moyenne 88.0 768.4072 822.3726 1110.2031
Nous pouvons maintenant observer la prime moyenne par zone.
tarif_zone <- test %>%
group_by(zone) %>%
summarise(
`Nombre de contrats` = n(),
`Coût moyen (€)` = mean(cout_sinistre),
`Prime pure moyenne (€)` = mean(prime_pure),
`Prime commerciale moyenne (€)` = mean(prime_commerciale)
)
kable(
tarif_zone,
format = "html",
digits = 2,
caption = "Tarification moyenne par zone",
align = "c"
) %>%
kable_styling(
bootstrap_options = c("striped", "hover", "condensed"),
full_width = FALSE,
position = "center"
)
| zone | Nombre de contrats | Coût moyen (€) | Prime pure moyenne (€) | Prime commerciale moyenne (€) |
|---|---|---|---|---|
| Faible | 433 | 802.21 | 796.37 | 1075.10 |
| Moyenne | 416 | 828.63 | 840.47 | 1134.63 |
| Forte | 151 | 912.66 | 931.27 | 1257.22 |
Nous étudions maintenant l’évolution de la prime lorsque la surface du logement augmente.
profil <- data.frame(
age = median(train$age),
surface = seq(
30,
180,
by = 10
),
capital_mobilier =
median(train$capital_mobilier),
zone = factor(
"Moyenne",
levels = levels(train$zone)
),
type_logement = factor(
"Appartement",
levels =
levels(train$type_logement)
),
anciennete =
median(train$anciennete),
alarme = factor(
"Non",
levels = levels(train$alarme)
),
nb_pieces =
median(train$nb_pieces),
sinistres_3ans =
median(train$sinistres_3ans)
)
profil$cout_predit <- predict(
modele,
newdata = profil
)
profil$prime <- pmax(
profil$cout_predit,
0
) * 1.35
ggplot(
profil,
aes(
x = surface,
y = prime
)
) +
geom_line(
linewidth = 1
) +
geom_point() +
labs(
title = "Evolution de la prime selon la surface",
x = "Surface (m²)",
y = "Prime commerciale (€)"
) +
theme_minimal()
La régression linéaire constitue une première approche pédagogique, mais elle présente plusieurs limites pour une tarification MRH réelle.
Premièrement, le coût des sinistres est une variable positive et généralement asymétrique. Une régression linéaire classique peut donc être moins adaptée qu’un modèle actuariel spécialisé.
Deuxièmement, une tarification MRH peut être décomposée en :
\[ Prime\ pure = Fréquence \times Sévérité \]
On pourrait donc construire séparément :
Des GLM pourraient ensuite être utilisés avec des distributions adaptées.
D’autres méthodes pourraient également être comparées :
Ce projet a permis de construire une première méthode de tarification MRH à partir d’une régression linéaire multiple.
La démarche suivie peut être résumée ainsi :
\[ Données \rightarrow Analyse descriptive \rightarrow Régression \rightarrow Tests \rightarrow Validation \rightarrow Prédiction \rightarrow Tarification \]
Le modèle permet d’estimer le coût annuel attendu pour chaque contrat en fonction de ses caractéristiques.
La prédiction obtenue est ensuite utilisée comme coût pur auquel sont ajoutés différents chargements afin d’obtenir une prime commerciale.
Dans une application professionnelle, il serait nécessaire d’aller plus loin en utilisant notamment une approche fréquence-sévérité et des GLM, ainsi qu’une validation temporelle et une analyse de la stabilité du modèle.
Ce projet constitue ainsi une première base de travail pour une étude actuarielle de tarification MRH.