Introduction à R · L2 · Section 4/6
Modèles statistiques
Progression
#Modèles statistiques : ajuster, diagnostiquer, évaluer
R brille lorsqu'il s'agit d'ajuster un modèle, de l'interpréter et de l'évaluer. La séance procède en deux étages : les modèles classiques (lm, glm) où tout est lisible dans summary, puis l'infrastructure tidymodels qui industrialise découpage, prétraitement et évaluation.
#Prérequis et objectifs
- Prérequis : le jeu
notes.csvde la section Manipulation (variablesnote,heures_revision,filiere), et le nuage de points de la section Visualisation.- Ajuster une régression linéaire, lire ses coefficients, son R², ses diagnostics.
- Formuler une prédiction et en mesurer l'erreur.
- Structurer un flux supervisé complet avec tidymodels : découpage, recette, ajustement, évaluation.
#La régression linéaire en une ligne
1modele <- lm(note ~ heures_revision, data = notes)2summary(modele)Sortie commentée, morceau par morceau :
1Coefficients:2 Estimate Std. Error t value Pr(>|t|)3(Intercept) 7.9882 0.7591 10.52 2e-064heures_revision 0.7647 0.1043 7.33 5.7e-055 6Residual standard error: 1.089 on 8 degrees of freedom7Multiple R-squared: 0.8704, Adjusted R-squared: 0.8542- Ordonnée à l'origine (7.99) : note prédite sans révision. Sans intérêt métier ici (qui passe un examen avec zéro heure de révision ?), elle ancre la droite.
- Pente (0.76) : chaque heure de révision supplémentaire vaut environ 0,76 point. C'est la quantité qui répond à la question.
- Erreur standard et t : la pente estimée avec ses marges ; t de 7,33 dit que la pente est très significativement différente de zéro.
- R² (0.87) : 87 pour cent de la variance des notes est expliquée par la durée de révision. Sur le nuage de points de la section Visualisation, les points sont serrés autour de la droite : c'est ce que chiffre le R².
Prédire et vérifier :
1# Prédiction pour une révision de 6 heures2predict(modele, newdata = data.frame(heures_revision = 6))3# Attendu : 7.99 + 0.76 * 6 ≈ 12.64 5# Prédictions sur les données observées, avec l'erreur6notes_pred <- broom::augment(modele, data = notes)7notes_pred |>8 dplyr::select(etudiant, note, .fitted, .resid)9# Les résidus oscillent autour de 0 ; Iris (3 h, 10.5) ressort avec le plus grand résidu positif#Diagnostic : vérifier les hypothèses
Une régression n'est exploitable que si ses hypothèses tiennent. Les quatre graphiques de plot(modele) donnent la checklist :
- Résidus contre valeurs prédites : nuage sans structure (linéarité, homoscédasticité). Un entonnoir signale une variance croissante.
- QQ-plot : les résidus suivent la droite normale (normalité). Des queues incurvées la rejettent.
- Scale-location : la racine des résidus standardisés doit rester horizontale.
- Résidus contre levier : aucun point hors des bandes de Cook (points influents).
1par(mfrow = c(2, 2))2plot(modele)3par(mfrow = c(1, 1))Avec nos dix points simulés, ces graphiques valent surtout comme exercice : petits échantillons, rien de net. Sur données réelles, c'est ici qu'un point aberrant ou une relation courbe se dénonce avant qu'on n'interprète une pente fallacieuse.
#Ajouter un facteur : la régression multiple
1modele2 <- lm(note ~ heures_revision + filiere, data = notes)2summary(modele2)filiere étant qualitative à trois niveaux, R en fait deux indicatrices, la première (eco par ordre alphabétique) servant de référence. Les coefficients filieremaths et filiereinfo se lisent comme des écarts à cette référence, à heures de révision fixées : la filière ajoute-t-elle un effet propre une fois la révision prise en compte ? Sur notre jeu où la note est générée par la seule révision, ces coefficients sont attendus proches de zéro et non significatifs : belle occasion de rencontrer une absence d'effet.
#tidymodels : industrialiser le flux supervisé
Sur un vrai problème de classification, le flux complet exige découpage train/test, prétraitement, ajustement, évaluation : autant d'étapes où une erreur silencieuse (par exemple normaliser avant le découpage) fausse tout. tidymodels structure chaque étape.
Exemple : prédire la réussite (note au-dessus de 10) à partir des révisions et de la filière.
1library(tidymodels)2 3notes_cls <- notes |> mutate(reussite = factor(note > 10))4 5set.seed(123)6split <- initial_split(notes_cls, prop = 0.75, strata = reussite) # strate : garder les proportions7train <- training(split)8test <- testing(split)9 10recette <- recipe(reussite ~ heures_revision + filiere, data = train) |>11 step_dummy(all_nominal_predictors()) |> # indicatrices pour la filière12 step_normalize(all_numeric_predictors()) # centrage-réduction des révisions13 14flux <- workflow() |>Points de lecture :
initial_split(..., strata = reussite)conserve la proportion de réussite dans train et test : sur un petit jeu, sans stratification, un tirage peut vider une classe du test.- La
recipevit dans le workflow : les paramètres de normalisation sont estimés sur train uniquement puis appliqués à test, sans fuite d'information. metricsrend exactitude et kappa. Avec si peu de données, ces chiffres sont indicatifs ; leur intérêt est pédagogique.
#Exercice : évaluer correctement
Expliquez pourquoi chacune de ces deux procédures est biaisée, puis corrigez-la sous tidymodels :
- Normaliser
heures_revisionsur le jeu complet avant le découpage train/test. - Choisir le modèle qui maximise l'exactitude mesurée sur le jeu de test, en réessayant dix configurations.
#Atelier
- Ajoutez une validation croisée (
vfold_cv, 5 replis) sur le jeu d'entraînement et comparez régression logistique et arbre de décision (decision_tree()) viafit_resamplesetcollect_metrics. - Évaluez le modèle retenu sur le test : matrice de confusion (
conf_mat) et courbe ROC avecroc_curveetautoplot. - Rédigez la conclusion dans un rapport Quarto : coefficients ou règles retenues, performances avec leur intervalle, limites (taille du jeu, variables absentes). Un rapport honnête vaut mieux qu'un chiffre flatteur.