Régressions linéaires avec R

Régressions simples, multiples et validation des modèles

L'essentiel de cette page !

Faire une régression linéaire entre x et y, une fonction affine, c'est facile ! Mais quand Y dépend de plusieurs variables X1, X2, X3... Cela demande un peu plus de méthodologie. Voici une démarche à appliquer point à point.

L'objectif est toujours d'établir la relation qu'il existe entre Y et les autres variables. 

Mais attention, n'oublions pas qu'il est impossible de connaître la vérité ou d'être certain de la reconnaître.

Si la régression linéaire trouve ses limites, on peut passer aux modèles généralisés avec glm().

Étape 0 - Partons d'un exemple ! Imaginons un échantillon d'une population, dont on a la taille, le poids et l'IMC (Indice de Masse Corporelle) !

Essayons de voir si on peut retrouver la relation entre taille, poids et IMC sachant qu'on connait pour une fois la réponse IMC = poids/(taille/100)²

Simulons ce jeu de données :

nb = 180 ; poids <- round(rnorm(nb,65,11),0)  ; imc <- rnorm(nb,22,5) ; # IMC 

taille <- round(sqrt(poids/imc)*100,0) ; taille_bis <- round(rnorm(nb,170,11),0)

taille_biss <- round(rnorm(nb,170,11),0) ; taille <- round((taille+taille_bis+taille_biss)/3,0)

imc <- round(poids/(taille/100)^2,1)

compil <- data.frame(poids,taille,imc) # Compilation des valeurs

Etape 1 - Décrire le jeu de données afin de comprendre les relations entre Y (l'IMC) et les variables X1 et X2 (poids et taille)

plot(compil) # Permet d'établir directement une relation entre toutes les variables d'un data.frame.

On voit ainsi que poids et IMC sont bien liés et que l'IMC a tendance à baisser si la taille augmente.


1.1- Établir un lissage de la relation poids // IMC. 

Un lissage permet de se donner une idée précise de la relation existante entre deux variables et d'estimer la linéarité de cette relation !

On peut utiliser la commande par défaut scatterplot() de la librairie car :

library(car)

scatterplot(imc~poids, data=compil, regLine=list(method=lm, lty=1, lwd=2, col="red"))

On y voit ainsi figurer la courbe de lissage moyenne, les courbes de lissage des intervalles de confiance et une régression obtenue par les moindres carrés (en rouge ici)


Le lissage peut aussi se faire manuellement avec la fonction lowess() :

plot(imc~poids,pch=16,data=compil) # équivalent de plot(compil$poids, compil$imc, pch=16)

# Je réalise un lissage de mes valeurs

P <- lowess(data$poids, data$imc,f=0.33,iter=1) # Lissage local sur 33% des valeurs

P2 <- lowess(data$poids, data$imc,f=0.66,iter=1) # Lissage plus global sur 66% des valeurs

Attention, superposer un polygone translucide qui figure un lissage des intervalles de confiance n'est pas une moindre affaire ! On ne le représentera pas ici car il faut créer sa fonction : fonction qui va faire glisser une fenêtre et calculer à chaque fois un intervalle de confiance. L'ensemble sera affiché avec la fonction polygone().

Dans tous les cas : scatterplot() ou plot() + lowess() permettent de voir qu'il existe une relation entre poids et IMC qui pourrait être étudiée !

1.2 - Décrire les relations statistiques entre les variables X1, X2... et Y avec les fonctions cor(), cor.test() et le R²

round(cor(compil),2)

Le tableau renvoyé permet d'un seul coup d'œil de voir le niveau de corrélation entre les variables.

Mais cela ne suffit pas, une faible corrélation peut être très significative. Un paramètre peut jouer un peu mais de façon certaine.

       poids taille   imc

poids   1.00   0.48  0.78

taille  0.48   1.00 -0.17

imc     0.78  -0.17  1.00

install.packages(corrplot)

library(corrplot)

corrplot(cor(compil))

En savoir plus sur les corrélogramme en tenant compte aussi de la significativité des corrélation.

# Je teste une relation linéaire entre poids et imc

cor.test(compil$imc,compil$poids)

cor.test(compil$imc,compil$taille)

La p-value renvoyé à chaque fois montre ici un lien significatif entre poids et imc et légèrement significatif entre taille et IMC. 

Remarque : la méthode par défaut ici est la méthode de Pearson. Il en existe d'autres.

Si R² = 1, le nuage est très allongé, X et Y tracent une droite.

Si R² = 0, le nuage se disperse dans tous les sens et une régression linéaire ne permettra pas de faire des prédictions.

# Je calcule mon R²

cor(compil$imc,compil$poids)^2

cor(compil$imc,compil$taille)^2

A ce stade, la relation poids - IMC est bien établie. On voit en revanche que la relation taille - IMC a un R² proche de 0.

Faut-il renoncer à la taille dans notre régression ? On sait bien que non ! Cela nous invite à rester méfiant et à ne pas exclure une variable si le R² seul ou la p-value nous pousse à renoncer.

Étape 2 - Réaliser le modèle de régression linéaire

Réaliser la régression linéaire.

Je tente un premier modèle de régression :

reg1 <- lm(imc~poids, data=compil)

J'affiche le résultat :

plot(imc~poids,pch=16,data=compil)

abline(reg1,col="red",lwd=2)

Je décris ma régression avec les commandes :

Extraire les p-values de chaque coefficient :

summary(reg1)[[4]][,4]

Extraire la p-value finale de la régression

str(summary(reg1))

# Extraction de la p-value

pf(summary(reg1)$fstatistic[1],summary(reg1)$fstatistic[2],summary(reg1)$fstatistic[3],lower.tail=FALSE)

Étape 3 - Contrôler le modèle de régression linéaire

En paraphrasant statistique-et-logiciel-r.com, on sait qu'on peut valider une relation linéaire entre X et Y si les résidus :

C'est quoi un résidu ? C'est la différence entre valeur réelle et sa projection sur la droite de régression : entre pratique et théorie.

Tous les graphiques nécessaires à ce qui va suivre s'affichent en une seule fois avec la commande plot(reg1).

La fonction valreg() pour valider un modèle de régression

On peut s'éviter toutes les étapes qui suivent en utilisant la fonction valreg() qui compile cet ensemble :

install.packages("devtools") ; require(devtools) # Risque d'erreur si RTools non installé.

devtools::install_github("Antoine-Masse/KefiR")

library("KefiR")

valreg(reg, plot=T, analyse=T)

3.0- On va vérifier d'abord que le modèle de régression semble adapté.

Le test dit de "validité de spécification" permet de vérifier que la moyenne des résidus est de 0. On vérifie donc la linéarité du modèle qui peut être mise à mal (courbure ?) si on a oublié une variable explicative importante [Desgraupes].

Dans ce but, le test rainbow compare le modèle initial à un modèle construit sur un sous-échantillon constitué des valeurs centrales de l’échantillon. S’il n’y a pas adéquation des deux modèles, le test conclut à une mauvaise spécification.

On peut d'abord commencer par un contrôle visuel :

plot(reg1, which = 1) 

Sur ce graphique, la ligne rouge doit être approximativement horizontale s'il y a bien une relation linéaire en X et Y. 

Ici, cette relation se vérifie mais on voit qu'elle n'est pas parfaite !

Vérification l'adéquation par le test de Rainbow (adéquation : p-value > 0,05)

install.packages("lmtest") ; library("lmtest") ; 

raintest(reg1) # test de rainbow

Il y a adéquation du modèle de régression si la p-value est supérieur à 0,05.

3.1- Indépendance des résidus

Les résidus ne doivent pas être liés les uns aux autres. En gros : on ne doit pas pouvoir anticiper en résidu par la connaissance d'un autre résidu.

On veut éviter les phénomènes d'auto-corrélation : les résidus augmenteraient ensemble dans une zone donnée et seraient liés les uns aux résidus précédents ou suivants (cas typiques lorsque X est un enregistrement du temps).

Vérification par le test de Durbin-Watson (indépendance : p-value > 0,05)

Cela se vérifie avec le test de Durbin-Watson : il faut une p-value supérieure à 0,05 pour avoir indépendance.

durbinWatsonTest(reg1) # nécessite la librairie car

dwtest(reg1) # nécessite la librairie lmtest

Attention : 0,05 n'est qu'une limite, il ne faut pas renoncer si on a 0,03 !

Autre remarque : ce test n'évalue que l'autocorrélation entre résidus et le résidus qui suit directement (n+1) et non ceux séparés d'un intervalle (résidus+2) qui pourraient être autocorrélés dans un phénomène cyclique.

On peut aussi visualiser l'indépendance avec ce graphique suivant :

library(stats)

acf(residuals(reg1), main="Regression IMC = f(poids)")

L'interprétation de ce graphique se fait de la manière suivante :

3.2- Distribution normale des résidus

On peut vérifier que les résidus suivent la loi normal avec un histogramme classique (cela devrait dessiner une courbe de gauss approximativement).

hist(residuals(reg1),col="yellow",freq=F)

densite <- density(residuals(reg1)) # estimer la densité que représente ces différentes valeurs

lines(densite, col = "red",lwd=3) # Superposer une ligne de densité à l'histogramme


Plus pertinent encore est de faire appel au diagramme Quantile-Quantile ou QQ plot.

plot(reg1, which = 2) # plot(reg1, 2) 

Le principe de ce diagramme est de découper le jeu de données en boîte contenant le même nombre de données (ex : les quartiles sont 3 quantiles qui permettent de découper un jeu de données en 4 boîtes qui contiennent chacune 25% des données).

Si la distribution suit une loi normale, les quantiles de résidus devraient s'organiser de la même façon que les quantiles théoriques de la fonction de régression linéaire. On devrait donc avoir un alignement entre quantiles des résidus et quantiles théoriques.

Attention : Si on n'observe pas d'alignement sur le QQ-plot, la régression risque de ne pas être pertinente.

Vérification par le test de Shapiro-Wilk (normalité : p-value > 0,05)

Un test permet de trancher sur la normalité de la distribution des résidus : c'est le test de normalité de Shapiro-Wilk

shapiro.test(residuals(reg1))

On peut considérer qu'il y a normalité tant que la p-value reste supérieure à 0,05 (mais on le rappelle que c'est une frontière floue : on peut tolérer 0,03).

3.3- Vérifier que la variance des résidus est constante (distribution homogène)

Pour cela on trace le graphique suivant qui met en relation les racines carrées des résidus (résidus standardisés) en fonction des valeurs théoriques (fitted-values) de Y prédites par l'équation de la régression.

plot(reg1, which = 3)

On cherche ici une courbe rouge plane. L'homogénéité est à rejeter si celle-ci n'est pas horizontale.

De plus, ce graphique est l'occasion de vérifier si certains points se regroupent, ce qui indiquerait un défaut d'indépendance.


Vérification par le test de Breush-Pagan (homogénéité : p-value > 0,05)

Le test de  Breush-Pagan permet de vérifier objectivement l'homogénéité des résidus (et donc l'hétéroscédasticité vs homoscédasticité).

install.packages("lmtest") ; library("lmtest") ; 

bptest(reg1) # librairie lmtest

ncvTest(reg1) # librairie car

L'homogénéité est rejeté si la p-value est inférieure à 0,05. Dans cet exemple, la relation poids/imc serait acceptée.

Vérification par le test de Goldfeld-Quandt (homogénéité : p-value > 0,05)

D'autres sources suggèrent de faire le test de Goldfeld-Quandt.

library("lmtest")

gqtest(reg1)

D'autres proposent un 3ème test, celui de White supposé plus capable sur les modèles complexes à détecter l'hétéroscédasticité mais moins puissant que Breusch-Pagan sur les modèles simples.

3.4- Évaluer les points qui ont une grande influence sur la régression afin de les écarter s'il s'agit de points potentiellement aberrants.

La distance de Cook permet d'évaluer les points qui auront une (trop) grande influence sur le modèle de régression.

Le graphique suivant permet de voir les points normaux et trop influents.

plot(reg1, which = 5) 

Les point trop influents sortent de la ligne pointillé rouge (distance de Cook).

Ici, les points sont tellement normaux qu'on n'aperçoit même pas cette ligne !!!

Aucun problème donc. Pour voir des exemple où la distance de Cook est traversée :  voir le lien suivant.

Étape 4 - Estimer la pertinence du modèle

Voici quelques indices qui permettent de prouver qu'un modèle de régression est bon.

Certains sont pertinents pour les régressions multiples et comparer plusieurs modèles. C'est le cas du RSS, de l'AIC, du BIC, du MSE.

En revanche, biais, variance et R² ajusté peuvent déjà  s'utiliser sur une simple régression à une seule variable.

Plus le RSS est petit, mieux c'est !

Le risque du RSS est qu'il peut être bon si notre régression est absurde est modélisant le bruit. Autre inconvénient, le RSS varie avec le nombre d'individus.

Plus le R² ajusté est proche de 1, mieux c'est !  

Plus l'AIC est petit, mieux c'est !

Plus le BIC est petit, mieux c'est !

Plus le MSE est petit, mieux c'est !

Plus le biais est petit, mieux c'est !

Moins ils bougent, mieux c'est !

Nous reparlerons plus tard du RSS, de l'AIC, du BIC et du MSE...

On ne parlera dans l'immédiat que du R² ajusté et de la variance.

4.1- Valider la pertinence des coefficients par les p-values et R² ajusté

On peut afficher de nombreux éléments via la fonction summary() - résultats ci-contre.

summary(reg1) # A regarder : Adjusted R-squared:

Coefficients:

                    Estimate Std. Error t value Pr(>|t|)    

(Intercept)  7.34412    0.93488   7.856 3.62e-13 ***

poids        0.22290    0.01395  15.979  < 2e-16 ***


Residual standard error: 2.264 on 178 degrees of freedom

Multiple R-squared:  0.5892,    Adjusted R-squared:  0.5869 

F-statistic: 255.3 on 1 and 178 DF,  p-value: < 2.2e-16

4.2- La variance du modèle de régression

La fonction confint() permet d'accéder facilement aux intervalles de confiance sur les coefficients.

coef(reg1) # affiche les coefficients du modèle

confint(reg1, level = 0.95) # affiche les coefficients min et max correspondant aux intervalles de confiance à 95%

                       2.5 %    97.5 %

(Intercept) 5.4992456 9.1889919

poids       0.1953758 0.2504326

Il est possible de visualiser la variance graphiquement.

La fonction predict() en paramètrage "prediction" va renvoyer le domaine où se situeraient toutes les droites possibles. matplot() pourra afficher le tout.

# Où se trouvent les droites possibles du fait de la fluctuation des coefficients ?

new <- data.frame(poids = seq(30, 50, 0.5),taille<-rep(mean(taille),41))

yy <- predict(reg2, new, interval="prediction")

matplot(new$poids,yy,lty=c(1,3,3), type="l",ylab="predicted y" ,col=c('black','green','green'))

Étape 5 - Régression multiple

Lorsque l'on a plusieurs variables, la fonction lm() reste pertinente. Il faut juste en maîtriser la syntaxe.

A cette syntaxe, on peut ajouter d'autres fonctions pour permettre des régression polynomiales avec poly() ou d'autres transformations avec I().

Exemples :

Créons donc des modèles de régressions pour essayer de retrouver la relation entre IMC et poids / taille

reg2 <- lm(imc~poids+taille,data=compil)

reg3 <- lm(imc~poids*taille,data=compil)

reg4 <- lm(imc~poids*poly(taille,2),data=compil)

reg5 <- lm(imc~poids:taille,data=compil)

reg6 <- lm(imc~poids*I(taille^2),data=compil)

reg7 <- lm(imc~poids*I(1/(taille/100)^2)+0,data=compil)

reg8 <- lm(imc~poids:I(1/(taille/100)^2)+0,data=compil)# C'est le vrai modèle où IMC = poids/taille_en_cm² - pas de valeur B

La fonction coef() permet d'afficher l'ensemble des coefficients de la régression.

coef(reg4)

La librairie Zelig vaut la peine de se détourner : elle permet de faire des régression multiples et d'estimer la répartition probable de mes valeurs en tenant compte des autres variables (ce qui est très difficile lorsqu'on a plusieurs variables).

library("Zelig")

# Régression simple IMC en fonction du poids

out <-  zelig(imc~poids, data=compil, model='ls')

summary(out)

setx(out,poids=c(50:80))->out

sim(out) -> out

plot(out)

summary(out) # description de chaque point

# Régression multiple IMC en fonction du poids et de la taille

out2 <-  zelig(imc~poids*taille, data=compil, model='ls')

summary(out2)

setx(out2,poids=c(50:80))->out2 # simulation pour des poids de 50 à 80 kg

sim(out2) -> out2 # simulation des poids

plot(out2) # affichage

summary(out)

out2$coefficient


On voit ici que le domaine de prévision est beaucoup plus fiable si on fait une régression multiple qui intègre la taille.

Étape 6 - Sélectionner le meilleur modèle

6.1- Comparer les R² ajusté. 

On y accède avec summary() sinon on peut regarder les R² non ajustés (très proches, moins fiables).

summary(reg1)  # 0.5892249

summary(reg2)  # 0.9868673

summary(reg3)  # 0.9958284

summary(reg4)  # 0.9998804

summary(reg5)  # 0.354403

summary(reg6)  # 0.992617

summary(reg7)  # 1

summary(reg8)  # 1

On voit ici que le modèle reg1 qui ne dépend que du poids n'est pas pertinent à côté des autres, tout comme reg5.

Il faudrait maintenant comparer les modèles reg2, reg3, reg4, reg6, reg7 et reg8.

Il faut surtout ne pas prendre celui qui a le meilleur R² ajusté ! Car on pourrait avoir un modèle trop complexe derrière. Mieux vaut un modèle un peu moins bon mais simple !

6.2- Comparer les modèles de régression avec la fonction anova().

La fonction anova() permet de faire des comparaisons entre modèles. 

anova(reg2,reg3,reg4,reg6,reg7)

Il suffit de regarder le RSS (en gras) pour savoir quelle est le meilleur modèle. Le 3ème (reg4) et le cinquième (reg7).

On peut comparer ces deux modèles reg4 et reg7.

anova(reg4,reg7) # L'absence d'étoiles indique bien que ces modèles peuvent être considérés comme équivalent en termes de relations linéaires.

Attention : cette fonction d'un point de vue mathématique semble adaptée uniquement pour des modèles imbriqués.

Si on remonte à l'étape 5, on voit bien que reg2 est imbriqué dans reg3. C'est donc possible de les comparer. En revanche, on ne peut comparer reg2 à reg5 (aucun ne contient l'autre modèle). Ajoutons que reg2 et reg5 peuvent toutefois être comparés à reg4 qui contient ces deux régressions.

Enfin, on voit qu'il n'est pas particulièrement pertinent de comparer reg4 et reg7 par anova !

Model 1: imc ~ poids + taille

Model 2: imc ~ poids * taille

Model 3: imc ~ poids * poly(taille, 2)

Model 4: imc ~ poids * I(taille^2)

Model 5: imc ~ poids * I(1/(taille/100)^2)

  Res.Df     RSS Df Sum of Sq       F    Pr(>F)    

1    177 29.1601                                   

2    176  9.2627  1   19.8973 13036.4 < 2.2e-16 ***

3    174  0.2656  2    8.9972  2947.4 < 2.2e-16 ***

4    176 16.3934 -2  -16.1278  5283.3 < 2.2e-16 ***

5    176  0.1515  0   16.2419                      

---

Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

6.3- Comparer les modèles de régression par l'intermédiaire des RSS.

Calculer les RSS des modèles : ce calcul peut se faire de la façon suivante - sans passer par la fonction anova().

sum(reg7$residuals^2) # sommes des résidus mis au carré pour le modèle reg7

6.4- Comparer les modèles de régression par l'intermédiaire des AIC.

Pour comparer l'AIC, on peut utiliser les fonctions extractAIC() et AIC(). Bien que ces deux fonctions ne renvoient pas la même valeurs d'AIC. Pas d'inquiétude, c'est juste qu'elle n'additionnent pas à la base de leurs calculs la même constante.

L'essentiel est de toujours utiliser la même fonction.

extractAIC() renvoie deux valeurs : la première, le nombre de variables et l'AIC qui, rappelons-le, doit être aussi petit que possible.

extractAIC(reg1) # 2.0000 296.1014 

extractAIC(reg2) # 3.0000 -321.6283

extractAIC(reg3) # 4.0000 -526.0523

extractAIC(reg4) # 6.000 -1161.387

extractAIC(reg5) # 2.0000 377.4847

extractAIC(reg6) # 4.0000 -423.2939

extractAIC(reg7) # 3.000 -1266.462

extractAIC(reg8) # 1.000 -1269.127

On voit que le modèle reg4 et reg7 jugés aussi bon que la réalité (reg8) ont pourtant 4 à 6 variables contre une seule ! (en réalité 2 car la formule poids/taille^2 est interprétée comme une seule variable dans reg8)

6.5- Comparer les modèles de régression par l'intermédiaire des BIC.

On peut comparer les BIC de chaque modèle avec la fonction BIC.

On rappelle que le BIC pénalise encore plus le nombre de variables que l'AIC.

BIC(reg1) # 878.7482

BIC(reg2) # 186.8721

BIC(reg3) # 128.4066

BIC(reg4) # -516.1518

BIC(reg5) # 936.2825

BIC(reg6) # 231.072

BIC(reg7) # -742.7517

BIC(reg8) # -753.0865

Il apparait très clairement que les seuls modèles à même de rivaliser avec la vérité (reg8) sont reg4 et reg7 avec une nette préférence pour reg7 qui est un modèle plus simple que reg4.

6.6- Comparer la colinéarité des variables 

La fonction vif() de la librairie car permet de comparer la colinéarité des variables. Les valeurs renvoyées par vif doivent être basses sinon les variables ont tendance à évoluer dans la même direction.

library(car)

vig(reg2)  # pas de colinéarité

vif(reg4) # colinéarité

vif(reg7) # colinéarité

Le mieux est d'en calculer directement la racine carré avec sqrt() : cela permet de savoir dans quelle mesure l'écart-type d'une variable est influencé par sa colinéarité avec une autre. On peut, par exemple, se fixer un seuil de 10 et éliminer les variables qui dépassent ce seuil.

Ainsi  : Mes analyses précédentes (RSS, AIC, BIC) montrent que reg7 serait un bon modèle.

Les valeurs renvoyées par vif()  suggèrent de se débarrasser de "poids:I(1/(taille/100)^2)" et on retrouverait ainsi la vérité, reg8 !

6.7- Ajouter ou supprimer des variables avec les fonctions add1(), drop1() et update() 

La fonction update permet de modifier un modèle existant en y ajoutant ou en y supprimant des variables.

Un exemple ou je vais supprimer la variable espèce d'une régression : 

data(iris)

lm(Sepal.Length~.,data=iris) -> reg

regressor<-update(reg,~.-Species)

summary(regressor)

La fonction drop1() ou son pendant (add1()) permettent de voir ce qui se passe si on ajoute ou supprime une variable. Il ne change pas réellement le modèle mais nous donnes des infos (AIC, BIC, p-values...).

Son grand avantage est lorsqu'on a fait une régression en fonction d'une variable catégoriel, lm() nous fera une régression en fonction de chaque catégorie : drop1() va regrouper tout cela pour clarifier le problème...

Exemple : j'ai fait une variable sur le jeu de données iris en fonction notamment de la variable Species. Il y a 3 espèces (versicolor, virginica et setosa) : lm()) va faire une régression pour chaque espèce selon la logique "pas versicolor" = 0 et "versicolor" = 1.

De ce fait, Species apparait plusieurs fois dans le modèle. drop1() évite ce problème.

data(iris)

lm(Sepal.Length~.,data=iris) -> reg

summary(reg)

drop1(reg) 

Étape 7 - Optimiser son modèle de régression

Partons volontairement d'une régression sale ! J'ai fait une régression croisée polynomiale où Y dépend de X1, X1^2, X2, X2^2 et des produits des ces éléments mais aussi des inverses...

reg9 <- lm(imc~poly(poids,2)*poly(taille,2)*poly(I(1/taille),2)*poly(I(1/poids),2))

La fonction step() est capable de nettoyer ces modèles. step() va avancer pas à pas pour supprimer des coefficients et réoptimiser les autres sans que la régression ne perte de sa qualité.

On peut paramétrer strep() de 3 façons :

summary(reg9)

reg9_prim <-  step(reg9,direction="both")

summary(reg9_prim)

anova(reg9,reg9_prim) # l'anova ne montre pas d'amélioration de reg9_prim par rapport à reg9


extractAIC(reg9)

extractAIC(reg9_prim)

On voit ici que l'AIC a baissé un peu et que j'ai réussi de passer de 25 variables à 9 variables ! J'en ai éliminé 16 !

La fonction update() permet d'ajouter ou de retirer manuellement des variables.

summary(reg9_prim)

reg9_update <- update(reg9_prim,.~.-1) # je retire l'intercept

summary(reg9_update)

reg9_update <- update(reg9_update,.~.-poly(poids, 2)) # je retire les polynomes du poids

reg9_update <- update(reg9_update,.~.-poly(I(1/taille), 2)) # je retire les polynomes de l'inverse de la taille

reg9_update <- update(reg9_update,.~.+I(poids/(taille/100)^2)) # j'introduis la formule réelle du modèle

extractAIC(reg9_prim) ; extractAIC(reg9_update) # j'ai bien baissé mon AIC

reg9_update <- step(reg9_update) # je peux encore utiliser step pour éliminer ce qui peut l'être

summary(reg9_update) # Je suis ainsi arrivé à retrouver mon modèle

Étape 8 - Validation du modèle

Pour valider un modèle, il existe plusieurs approches :

Une fois le modèle validé :

Un bootstrap va permettre de remixer l'échantillon qui a servi pour l'obtention du modèle (en retirant certains points et en dupliquant d'autres).

On va ainsi se faire une idée précise de la variance et du biais.

Comment faire : il suffit de demander à être formé

Voici aussi une petite illustration du potentielle du machine learning : le bootstrap

Étape 9 - Faire des prédictions

La commande predict est excellente pour pouvoir prédire les valeurs possibles à partir d'un modèle de régression.

Elle permet aussi d'anticiper la fiabilité de nos valeurs.

# Pour que predict() fonctionne, les données de prédictions doivent être sous forme de data.frame.

new <- data.frame(poids = seq(30, 50, 0.5),taille<-rep(mean(taille),41))

pred_droites <- predict(reg2, new, interval="confidence",level=0.95)

En paramétrage confidence (+ level=0.95), predict() prédit des valeurs à partir d'un modèle de régression et donne les intervalles de confiance des estimations.

# Trace les trois courbes

matplot(new$poids,pred_droites,lty=c(1,2,2), type="l",xlab ='x',ylab="predicted y",col=c('black','blue','blue'))

Étape 10 - Afficher des régressions multiples en modélisant des nappes

10.1- Régression en 2D

On peut très facilement afficher une régression linéaire si on a (sans compter l'intercept) 1 seul ou 2 coefficients.

Si j'ai une seule variable et une relation du type y = ax + b, je peux utiliser la fonction abline().

D'autres fonctions ci-dessus sont très utiles telles matplot() ou encore les affichages de régressions obtenues avec Zelig (cf. ci-dessus).

10.2- Régression simple en 3D : 2 coefficients = 1 plan.

Si mon modèle de régression implique deux coefficients directeurs appliqués à deux variables, la régression donnera un plan dans un graphique 3d.

C'est le cas du modèle de régression 2 illustré ci-dessus que l'on peut comparer à reg1 qui ne faisait varier l'IMC qu'en fonction du poids.

reg1 <- lm(imc~poids,data=compil)

reg2 <- lm(imc~poids+taille,data=compil)

On peut maintenant afficher le graphique avec en rouge (reg1) et en bleu (reg2)

library("rgl")

plot3d(imc~poids+taille,radius=2,expand=1.5,box=F,size=4)

# reg1

planes3d(a=reg1$coefficients[2], b=0, c=-1, d=reg1$coefficients[1], col='red',alpha=0.5)

# reg2

planes3d(a=reg2$coefficients[2], b=reg2$coefficients[3], c=-1, d=reg2$coefficients[1], col='blue',alpha=0.5)

10.3- Régression simple en 3D : n coefficients dérivés de 2 variables.

Imaginons que je veux illustrer la relation entre Y et de nombreuses transformations de deux variables, je peux alors faire une transformation.

Je définis l'étendue des valeurs de X1 et de X2 que je compte tester.

my_seq_poids <- seq(min(poids), max(poids), length = 40)

my_seq_taille <- seq(min(taille), max(taille), length = 40)

Je combine les deux étendues de X1 et X2 pour créer une Grille de valeurs possibles

Grille<-expand.grid(poids=my_seq_poids,taille=my_seq_taille)

J'utilise la comme predict() pour simuler toutes les valeurs d'IMC possible pour les combinaisons de X1 et X2

Nappe<- predict(reg2,Grille)

Nappe<- matrix(Nappe,nrow=40, ncol=40,byrow=F)

Je trace le graphique 3D et j'ajoute la nappe

library("plot3Drgl")

scatter3Drgl(poids, taille, imc,  pch=16 ,cex=1,col="black")

colfunc<-colorRampPalette(c("black","blue")) # couleurs utilisées

colors <- (colfunc(40))

# Nappe de la régression 2 en noir & bleu

persp3Drgl(x=my_seq_poids,y=my_seq_taille,z=Nappe,col=colors,alpha=0.5 ,add=T)

Je peux ajouter d'autres régressions

Nappe<- predict(reg8,Grille)

Nappe<- matrix(Nappe,nrow=40, ncol=40,byrow=F)

colfunc<-colorRampPalette(c("blue","cyan","yellow","red","#990000"))

colors <- (colfunc(40))

# Nappe de la régression 8 en arc en ciel, le vrai modèle

persp3Drgl(x=my_seq_poids,y=my_seq_taille,z=Nappe,col=colors,alpha=0.5 ,add=T)

10.3- Et si j'ai plus de 2 variables ?

Impossible de les voir !!! Mais ce problème reste le même sans régression. Il faudra alors penser à l'ACP ou sinon, modéliser pour deux variables et fixer les valeurs des autres variables.

Exemple : si j'avais une variable supplémentaire X3

Grille<-expand.grid(poids=my_seq_poids,taille=my_seq_taille)

Grille <- data.frame(Grille,X3=rep(12,40^2)) # Permet de fixer la variable X3 à 12.

Il ne reste qu'à suivre le code ci-dessus avec la fonction predict()...

Mais attention : si les autres variables ont un rôle à jouer dans les prédictions : cela ne donnera rien.

Étape 11 - Gérer les variables colinéaires

Certains variables sont colinéaires. Parfois aussi, on a plusieurs Y (Y1, Y2, Y3) à mettre en relation avec plusieurs X (X1, X2, X3)...

Comment faire : il suffit de demander à être formé