But du projet
Le contenu de ce document propose une analyse d’un jeu de données, ainsi qu’un travail de régression sur les différentes variables grâce au logiciel R Studio. Les données portent sur les ventes de maison aux Etats-Unis entre 2014 et 2015. Le but est donc de trouver les variables qui peuvent expliquer le prix de vente des maisons. Le jeu de données est disponible sur la plateforme Kaggle https://www.kaggle.com. Un travail en amont avant de commencer le projet a été nécessaire. En effet, des modifications personnelles ont été réalisées, notamment la conversion de certaines variables au format numérique (par exemple, la surface a été convertie en m² pour faciliter l’analyse), la création de variables complémentaires, la description complète des variables, ou encore, la modification des intitulés de variables afin d’en avoir une meilleure compréhension. NOTE : Pour ne pas surcharger le document, les codes similaires (comme les mêmes graphiques, mais pas avec les mêmes variables) ont été cachés, mais sont visibles dans le code source de cette page.
Chargement des librairies
Les librairies permettent d’importer des outils supplémentaires pour des calculs mathématiques scientifiques, des fonctions spécifiques, des options graphiques, etc.
# Graphiques / Tableau :
library(dplyr)
library(ggplot2)
library(gridExtra);library(kableExtra)
library(knitr)
library(leaflet)
library(markdown)
require(scales)
library(summarytools)
library(tidyr)
library(zoo)
# Mathématiques / Statistiques :
require(caTools)
library(corrplot)
library(glmnet)
library(ISLR)
library(leaps)
library(locfit)
library(MASS)
library(olsrr)
library(rpart);library(rpart.plot)Lecture des données, amélioration et création de variables
La première étape consiste à lire les données. Ensuite, j’ai : - transformé la date en “réelle” date, car elle était sous un format caractère. - crée une nouvelle variable qui reprend uniquement le mois et l’année de l’achat. - arrondi la latitude à 3 chiffres après la virgule pour que cela coïncide avec la longitude.
Analyse des données
Analyse globale des variables
Pour analyser les données rapidement et facilement, la fonction summary est adaptée.
Seulement, ce summary est assez lourd visuellement et ne contient pas que des informations pertinentes (moyennes des dates, minimums et maximums des mois, des longitudes, des latitudes…). Simplement un extrait de ce dernier est donc réalisé et est plus cohérent. Grâce à la sortie, ci-dessous, nous pouvons voir quelques résultats intéressants. Notamment, que la médiane du nombre de chambres est de 3, ou encore qu’en moyenne les salons ont une surface de 193 m². La surface au sol la plus petite est de 26.94 m², il s’agit sûrement d’un appartement. La plus vielle construction date de 1900, tandis que la maison la plus récente date de 2015 (année d’extraction du jeu de données). Cette sortie donne un très bon aperçu des données et permet d’anticiper les analyses graphiques et statistiques en fonction du type de données.
cols <- c("date_achat","chambres", "salle_de_bain", "m2_salon", "m2_terrain",
"m2_piece_a_vivre_voisin","m2_terrain_voisin",
"note_globale_construction","m2_surface_au_sol","m2_sous_sol",
"annee_construction","price")
tab = as.data.frame(descr(data[cols],
stats = c("min","q1", "med", "mean", "q3","max")))
rownames(tab)= c("Minimum", "Q1", "Médiane", "Moyenne", "Q3", "Maximum")
tab2 = as.data.frame(descr(data[cols], stats = c("n.valid","pct.valid")))
rownames(tab2)= c("Nombre de lignes NON vides", "Pourcentage de NON manquants")
kable(t(tab),align = "cccccccccc", digits = 1)%>%kable_styling(full_width = F)| Minimum | Q1 | Médiane | Moyenne | Q3 | Maximum | |
|---|---|---|---|---|---|---|
| annee_construction | 1900.0 | 1951.0 | 1975.0 | 1971.0 | 1997.0 | 2015.0 |
| chambres | 0.0 | 3.0 | 3.0 | 3.4 | 4.0 | 33.0 |
| m2_piece_a_vivre_voisin | 37.1 | 138.4 | 170.9 | 184.6 | 219.2 | 576.9 |
| m2_salon | 26.9 | 132.6 | 177.4 | 193.2 | 236.9 | 1257.9 |
| m2_sous_sol | 0.0 | 0.0 | 0.0 | 27.1 | 52.0 | 447.8 |
| m2_surface_au_sol | 26.9 | 110.6 | 144.9 | 166.1 | 205.3 | 874.2 |
| m2_terrain | 48.3 | 468.2 | 707.7 | 1403.5 | 992.9 | 153415.0 |
| m2_terrain_voisin | 60.5 | 473.8 | 707.9 | 1186.2 | 936.7 | 80936.4 |
| note_globale_construction | 1.0 | 7.0 | 7.0 | 7.7 | 8.0 | 13.0 |
| price | 75000.0 | 321950.0 | 450000.0 | 540088.1 | 645000.0 | 7700000.0 |
| salle_de_bain | 0.0 | 1.0 | 2.0 | 1.7 | 2.0 | 8.0 |
| Nombre de lignes NON vides | Pourcentage de NON manquants | |
|---|---|---|
| annee_construction | 21613 | 100 |
| chambres | 21613 | 100 |
| m2_piece_a_vivre_voisin | 21613 | 100 |
| m2_salon | 21613 | 100 |
| m2_sous_sol | 21613 | 100 |
| m2_surface_au_sol | 21613 | 100 |
| m2_terrain | 21613 | 100 |
| m2_terrain_voisin | 21613 | 100 |
| note_globale_construction | 21613 | 100 |
| price | 21613 | 100 |
| salle_de_bain | 21613 | 100 |
Enfin, j’ai analysé si certaines variables étaient vraiment intéressantes à ajouter au modèle. C’est-à-dire pas autant de modalités que de ventes.
tab_val_uniq =data.frame(Variables=c("code_postal","long","lat","année_construction"),
nb_de_valeur_unique = c(length(unique(data$code_postal)),
length(unique(data$long)),
length(unique(data$lat)),
length(unique(data$annee_construction))))
colnames(tab_val_uniq)= c("Variables", "Nb valeurs uniques")
kable(t(tab_val_uniq), align = "c") %>% kable_styling(full_width = F)| Variables | code_postal | long | lat | année_construction |
| Nb valeurs uniques | 70 | 752 | 582 | 116 |
Analyse graphique
Variable d’intérêt : le prix de vente de la maison
Pour commencer, j’analyse la variable d’intérêt, numériquement et graphiquement.
ggplot(data, aes(x=price)) + geom_histogram(aes(y=..density..),
colour="black", fill="#ABE1E7")+
geom_vline(aes(xintercept= mean(price), linetype="Moyenne"),color="#6ACA2B",size=2)+
scale_x_continuous(labels = function(y) format(y, scientific = FALSE))+
xlab("Prix de vente")+ylab("Densité")+ggtitle("Densité du prix de vente")Mathématiquement, les valeurs se présentent ainsi :
tab = as.data.frame(descr(data$price, stats = c("min","q1","med","mean", "q3","max")))
colnames(tab) = c("Prix de vente")
rownames(tab) = c("Minimum", "Q1", "Médiane", "Moyenne", "Q3", "Maximum")
kable(t(tab),align = "c" , digits = 1, row.names = TRUE)%>% kable_styling(full_width = F)| Minimum | Q1 | Médiane | Moyenne | Q3 | Maximum | |
|---|---|---|---|---|---|---|
| Prix de vente | 75000 | 321950 | 450000 | 540088.1 | 645000 | 7700000 |
Graphiquement, les valeurs se présentent ainsi :
G1 = ggplot(data, aes(y=price) ) +
geom_boxplot(fill = "#ABE1E7", colour = "#F3787A", alpha = 0.7) +
scale_y_continuous(labels = function(x) format(x, scientific = FALSE))+
theme(axis.text.x = element_blank() ,
axis.ticks = element_blank(),
axis.title.x = element_blank()) +
geom_point(data = data.frame(x = 0, y = mean(data$price)),
aes(x=x, y=y),
color = 'red')+
ylab("Prix de vente")+ggtitle("Répartition du prix de vente")
G2 = ggplot(data, aes(y=price) ) +
geom_boxplot(fill = "#ABE1E7", colour = "#F3787A", alpha = 0.7,
outlier.shape = NA) +
theme(axis.text.x = element_blank() ,
axis.ticks = element_blank(),
axis.title.x = element_blank()) +
geom_point(data = data.frame(x = 0, y = mean(data$price)),
aes(x=x, y=y),
color = 'red')+
scale_y_continuous(labels = function(x) format(x, scientific = FALSE) ,
limits=c(0, 1500000))+
ylab("Prix de vente")+
ggtitle("Répartition du prix de vente",
subtitle = "sans les outliers" )
grid.arrange(G1, G2, ncol=2, nrow = 1)Maintenant, regardons une évolution du prix de vente :
ggplot(data) + geom_line(aes(x = date_achat, y = price), color = "#569AF3") +
ggtitle("Prix de vente des maisons vendues",
subtitle ="De janvier 2014 à décembre 2015")+
scale_y_continuous(labels = function(x) format(x, scientific = FALSE))+
ylab("Prix de vente") +xlab("Date de l'achat")La graphique précédent est assez chargé, analysons plutôt la moyenne, par jour et ensuite par mois :
Avec d’autres variables :
Ces quatre graphiques montrent le prix en fonction d’une variable explicative. En bleu, apparaît la courbe de régression simple. En rouge apparaît la courbe de Loess, qui suit beaucoup plus les données et en gris l’intervalle de confiance correspondant. Le premier montre que la surface du salon en m² affecte le prix de vente. Plus la surface augmente, plus le prix augmente, c’est une relation positive. On peut voir qu’il y a comme un « entonnoir » : la dispersion de prix est faible pour une petite surface, mais très élevée pour une surface plus grande. Le deuxième graphique, le prix de vente en fonction de la surface au sol, montre un peu la même analyse, mais la relation est un peu moins forte, les deux courbes sont plus basses. Le troisième graphique, montre une nouvelle fois une relation positive : plus le nombre de chambres augmente, plus le prix augmente : on le voit clairement avec la courbe de la régression simple (en bleu). La courbe en rouge, montre plutôt une augmentation jusqu’à 8 chambres, mais ensuite le prix stagne : la courbe est un peu biaisée. Cela est dû à une donnée aberrante (33 chambres). Enfin, le dernier graphique montre une stagnation des prix dans le temps, l’année de construction n’affecte pas vraiment le prix de vente. Les deux courbes le montrent.
Variables explicatives
Analyse des ventes par mois :
Ce graphique, la fréquence des ventes par mois, permet de montrer les périodes plus favorable à la vente de biens bien immobiliers. Il s’agirait de la période d’avril à juillet.
ggplot(data.frame(table(data$mois_achat)), aes(x=Var1, y=Freq),) +
geom_bar(stat = "identity",fill="#E8BAF7") +
xlab(label = "Mois") + ylab(label = "Fréquence")+
ggtitle("Fréquence des ventes par mois")Analyse des ventes grâce à une cartographie :
Cette cartographie montre la localisation des maisons vendues. Il y a une concentration des ventes autour de la ville de Seattle. Les ventes sont donc plus urbaines que rurales. NOTE : Pour voir la cartographie en dynamique : https://rpubs.com/Alice05/612380
carte = data.frame(table(data$long, data$lat))
colnames(carte) = c("Longitude", "Latitude", "Nombre_de_ventes")
carte$Latitude = round(as.numeric(as.character(carte$Latitude)),3)
carte$Longitude = round(as.numeric(as.character(carte$Longitude)),3)
carte = subset(carte, Nombre_de_ventes != 0)
leaflet(carte) %>% addTiles() %>%
addCircles(lng = ~Longitude, lat = ~Latitude, weight = 1,
radius = ~ Nombre_de_ventes*100,
popup = ~paste("Nombre de ventes:", Nombre_de_ventes),
color = "#a500a5", fillOpacity = 0.5)| Nombre de chambres | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 33 |
| Fréquence | 13 | 199 | 2760 | 9824 | 6882 | 1601 | 272 | 38 | 13 | 6 | 3 | 1 | 1 |
Analyse du nombre de salles de bain :
Avec ce graphique, nous pouvons voir qu’en moyenne les biens bien immobiliers vendus comporte moins de deux salles de bain. De plus, grâce au tableau, nous voyons que la fréquence plus de 8 salles de bain est très faible : elles ne sont même pas visibles sur le graphique.
| Nombre de salles de bain | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
| Fréquence | 86 | 8355 | 10542 | 2228 | 338 | 48 | 12 | 2 | 2 |
Analyse des différentes surfaces en m² :
Ces trois diagrammes en boîte permettent de visualiser la répartition des maisons vendues en fonction de différentes surfaces mesurées en m². La moyenne peut être visualisée grâce au point rouge. Pour visualiser correctement le troisième graphique, les outliers ont été enlevés, sinon il était illisible.
Analyse des années de construction :
Ce graphique représente les années de construction des maisons qui ont été vendues. La plus vieille a été construite en 1900. L’année moyenne de construction est 1971. On voit, grâce à la densité qui apparaît également, qu’il y a eu beaucoup moins de constructions dans les années 30/40, mais un énorme pic, dans les années 2010.
ggplot(data, aes(x=annee_construction)) +
geom_histogram(aes(y=..density..), colour="black", fill="#ABE1E7") +
geom_vline(aes(xintercept= mean(annee_construction), linetype="Moyenne"),
color = "#6ACA2B", size=2)+
geom_vline(aes(xintercept= median(annee_construction), linetype="Médiane"),
color = "#C256F3", size=2)+
geom_density(alpha=.2, fill="#FF6666") +
scale_linetype_manual(name = "Indicateur", values = c(2, 2),
guide=guide_legend(override.aes = list(color= c("#C256F3","#6ACA2B"))))+
ggtitle("Répartition des années de construction des maisons vendues")Analyse de la note globale de construction :
La note globale de construction permet de noter la qualité de construction, ainsi que le design. En moyenne, les maisons vendues ont une note d’environ de 7 : c’est-à-dire une qualité moyenne.
annotation <- data.frame(
x = 11.5,
y = 7500,
label = c("Qualité de construction et du design :
1-3 : basse qualité
4-10: moyenne qualité
11-13 : haute qualité"))
ggplot(data, aes(x=note_globale_construction)) +
geom_bar(colour="black", fill="#ABE1E7") +
geom_vline(aes(xintercept= mean(note_globale_construction), linetype="Moyenne"),
color = "#6ACA2B", size=2)+
geom_vline(aes(xintercept= median(note_globale_construction), linetype="Médiane"),
color = "#C256F3", size=2)+
scale_linetype_manual(name = "Indicateur", values = c(2, 2),
guide = guide_legend(override.aes = list(color = c("#6ACA2B", "#C256F3"))))+
geom_label(data=annotation, aes( x=x, y=y, label=label),
color="#CD5D86",
size=2.5 ,fontface="bold", alpha = 0.3 )+
ggtitle("Répartition de la note de construction")Analyse des corrélations entre les variables et le prix de vente :
Analysons maintenant les corrélations entre les variables : un lien positif (en bleu) ou négatif (en rouge) entre les variables. On peut voir les corrélations entre toutes les variables, mais celles qui nous intéressent en particulier sont celles avec la variable “price”. (la fonction permet de calmculer les p.values).
cor.mtest <- function(mat, ...) {
mat <- as.matrix(mat);n <- ncol(mat);p.mat<- matrix(NA, n, n);diag(p.mat) <- 0
for (i in 1:(n - 1)) {
for (j in (i + 1):n) {tmp <- cor.test(mat[, i], mat[, j], ...)
p.mat[i, j] <- p.mat[j, i] <- round(tmp$p.value,2)}}
colnames(p.mat) <- rownames(p.mat) <- colnames(mat); p.mat}
corrplot(cor, method="color", col=col(200), type="upper",order="hclust",
addCoef.col = "black", tl.col="black", # Ajout du coefficient de corrélation
tl.srt=90, p.mat = cor.mtest(data[c(2:22)]), sig.level = 0.01, diag=F)Régressions
Dans cette partie, plusieurs régressions ont été effectuées en fonction de différentes méthodes et de différents critères de validation et d’évaluation de modèles. Des tableaux récapitulatifs des résultats seront visibles pour faciliter la comparaison des modèles.
NOTE : Les variables concernant la date d’achat, au format date, ne seront pas mise dans les régressions. Je les ai remplacées par 2 variables numériques : l’année et le mois de l’achat.
Régression générale
##
## Call:
## lm(formula = price ~ . - date_achat - date_mois_an, data = data)
##
## Residuals:
## Min 1Q Median 3Q Max
## -1273601 -98415 -8677 78157 4312074
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) -6.535e+07 9.898e+06 -6.602 4.16e-11 ***
## annee_achat 3.658e+04 4.690e+03 7.800 6.45e-15 ***
## mois_achat 1.316e+03 7.028e+02 1.873 0.0611 .
## chambres -3.594e+04 1.882e+03 -19.095 < 2e-16 ***
## salle_de_bain 5.195e+04 3.252e+03 15.975 < 2e-16 ***
## toilette_hors_sdb -7.072e+02 2.070e+03 -0.342 0.7326
## m2_salon 6.031e+05 4.280e+05 1.409 0.1588
## m2_terrain 1.230e+00 5.132e-01 2.398 0.0165 *
## m2_piece_a_vivre_voisin 2.397e+02 3.692e+01 6.491 8.69e-11 ***
## m2_terrain_voisin -4.050e+00 7.844e-01 -5.163 2.45e-07 ***
## nb_etage 4.033e+03 3.185e+03 1.266 0.2055
## vue_mer 5.906e+05 1.725e+04 34.238 < 2e-16 ***
## note_vue 5.280e+04 2.128e+03 24.806 < 2e-16 ***
## note_condition 2.654e+04 2.309e+03 11.492 < 2e-16 ***
## note_globale_construction 9.708e+04 2.138e+03 45.411 < 2e-16 ***
## m2_surface_au_sol -6.012e+05 4.280e+05 -1.405 0.1601
## m2_sous_sol -6.015e+05 4.280e+05 -1.405 0.1599
## annee_construction -2.675e+03 6.671e+01 -40.096 < 2e-16 ***
## code_postal -5.912e+02 3.281e+01 -18.020 < 2e-16 ***
## lat 6.039e+05 1.067e+04 56.587 < 2e-16 ***
## long -2.086e+05 1.305e+04 -15.981 < 2e-16 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 200200 on 21592 degrees of freedom
## Multiple R-squared: 0.7028, Adjusted R-squared: 0.7025
## F-statistic: 2553 on 20 and 21592 DF, p-value: < 2.2e-16
Tableau = data.frame(nb_var_explicatives = extractAIC(regTOT)[1]-1,
AIC = extractAIC(regTOT)[2],
BIC = BIC(regTOT),
CpMallows = ols_mallows_cp(regTOT, regTOT),
R_carre = round(sumregTOT$r.squared,4),
R_carre_ajuste = round(sumregTOT$adj.r.squared,4),
variable_enlevee = "aucune")
kable(Tableau, align = "ccccccc") %>% kable_styling(full_width = F)| nb_var_explicatives | AIC | BIC | CpMallows | R_carre | R_carre_ajuste | variable_enlevee |
|---|---|---|---|---|---|---|
| 20 | 527690.8 | 589203.5 | 21 | 0.7028 | 0.7025 | aucune |
Cette première régression montre que 15 variables sont plus ou moins significatives, c’est-à-dire potentiellement explicatives du prix de vente. Le but est de conserver des variables qui sont à la fois quantitativement significatives et statistiquement significatives. On identifie tout d’abord à la significativité de la p.value : Il y en a 13 avec une significativité très bien notée (*** / < 0.001). Une avec une bonne significativité (* / <0.05) et une autre avec une significativité moyenne (. / 0.0612). Mais il est également important de regarder si c’est quantitativement significatif : ceci est visible avec un coefficient qui n’est pas proche de 0. Il est assez important (1.316e+03). Par doute, nous conserverons ces variables dans le modèle même si la p.value n’est pas très significative. Le tableau résume les différents critères de sélection, et sera une base pour comparer si les autres modèles seront meilleurs au sens de ces critères.
Régression avec la méthode BACKWARD
Cette méthode descendante consiste à partir du modèle complet (cf. au-dessus), puis d’enlever une à une les variables les moins significatives. Et on renouvelle cela jusqu’à temps que le modèle devienne complètement significatif. En plus de la p.value, j’analyserai plusieurs critères de choix : AIC BIC Cp de Mallows R² et R² ajusté. Je retire la variable qui conduit à la plus grande amélioration des critères de choix. Je m’arrête lorsqu’aucune variable ne permet cette amélioration.
Je sais qu’il existe une fonction permettant de faire cela automatiquement, mais le faire manuellement m’a permis de comprendre encore plus les variables et d’affiner mon analyse en fonction des critères de choix.
reg1 = lm(price~ . - date_achat -date_mois_an - toilette_hors_sdb, data = data)
reg2 = lm(price~ . - date_achat -date_mois_an - toilette_hors_sdb - nb_etage,
data = data)
reg3 = lm(price~ . - date_achat -date_mois_an - toilette_hors_sdb - nb_etage -
m2_surface_au_sol,data = data)
reg4 = lm(price~ . - date_achat -date_mois_an - toilette_hors_sdb - nb_etage -
m2_surface_au_sol - mois_achat, data = data)
reg5 = lm(price~ . - date_achat -date_mois_an - toilette_hors_sdb - nb_etage -
m2_surface_au_sol - mois_achat - m2_terrain, data = data)| nb_var_explicatives | AIC | BIC | CpMallows | R_carre | R_carre_ajuste | variable_enlevee |
|---|---|---|---|---|---|---|
| 20 | 527690.8 | 589203.5 | 21.00000 | 0.7028 | 0.7025 | aucune |
| 19 | 527689.0 | 589193.6 | 19.11676 | 0.7028 | 0.7025 | toilette_hors_sdb |
| 18 | 527688.5 | 589185.2 | 18.67012 | 0.7028 | 0.7025 | nb_etage |
| 17 | 527688.5 | 589177.2 | 18.63014 | 0.7028 | 0.7025 | m2_surface_au_sol |
| 16 | 527690.0 | 589170.7 | 20.12883 | 0.7027 | 0.7025 | mois_achat |
| 15 | 527693.6 | 589166.3 | 23.75958 | 0.7026 | 0.7024 | m2_terrain |
Ce tableau, ci-dessus, résume les résultats que j’ai obtenu en pratiquant manuellement la méthode BACKWARD. Les 3 critères AIC BIC et Cp de Mallows doivent être le plus petit possible, le R² et le R² ajusté doivent être le plus grand possible. On peut voir la variable qui a été enlevée à chaque étape et donc le nombre de variables explicatives qui restent dans le modèle. On peut voir que je suis descendu jusqu’à 15 variables explicatives. Cependant, seul le BIC s’est amélioré. j’ai décidé de conserver cette ligne, car tous les indicateurs ne s’améliorent pas, mais la différence entre 16 et 15 est très faible. Il est donc assez raisonnable de rester à 15 variables.
Régression automatique BACKWARD
L’analyse que j’ai faite au-dessus peut être faite automatiquement par une fonction sur le logiciel R. Avec cette automatisation, on obtient presque le même nombre de variables à conserver dans le modèle. Cette méthode conserve les mêmes 15 variables explicatives, mais a décidé de conserver les variables m2_terrain et mois_achat , car la méthode travaille avec le critère AIC, qui effectivement est plus grand avec ces variables. La sortie suivante nous donne le déroulement de la méthode : variables conservées, variables exclues, les résultats de l’AIC à chaque étape. La dernière étape est donc le modèle que la méthode conseille de conserver.
## Start: AIC=527690.8
## price ~ (date_achat + annee_achat + mois_achat + chambres + salle_de_bain +
## toilette_hors_sdb + m2_salon + m2_terrain + m2_piece_a_vivre_voisin +
## m2_terrain_voisin + nb_etage + vue_mer + note_vue + note_condition +
## note_globale_construction + m2_surface_au_sol + m2_sous_sol +
## annee_construction + code_postal + lat + long + date_mois_an) -
## date_achat - date_mois_an
##
## Df Sum of Sq RSS AIC
## - toilette_hors_sdb 1 4.6814e+09 8.6569e+14 527689
## - nb_etage 1 6.4260e+10 8.6575e+14 527690
## - m2_surface_au_sol 1 7.9109e+10 8.6577e+14 527691
## - m2_sous_sol 1 7.9193e+10 8.6577e+14 527691
## - m2_salon 1 7.9616e+10 8.6577e+14 527691
## <none> 8.6569e+14 527691
## - mois_achat 1 1.4058e+11 8.6583e+14 527692
## - m2_terrain 1 2.3050e+11 8.6592e+14 527695
## - m2_terrain_voisin 1 1.0688e+12 8.6676e+14 527716
## - m2_piece_a_vivre_voisin 1 1.6895e+12 8.6738e+14 527731
## - annee_achat 1 2.4395e+12 8.6813e+14 527750
## - note_condition 1 5.2950e+12 8.7098e+14 527821
## - salle_de_bain 1 1.0232e+13 8.7592e+14 527943
## - long 1 1.0239e+13 8.7593e+14 527943
## - code_postal 1 1.3019e+13 8.7871e+14 528011
## - chambres 1 1.4618e+13 8.8030e+14 528051
## - note_vue 1 2.4671e+13 8.9036e+14 528296
## - vue_mer 1 4.7000e+13 9.1269e+14 528832
## - annee_construction 1 6.4456e+13 9.3014e+14 529241
## - note_globale_construction 1 8.2678e+13 9.4836e+14 529660
## - lat 1 1.2838e+14 9.9407e+14 530678
##
## Step: AIC=527689
## price ~ annee_achat + mois_achat + chambres + salle_de_bain +
## m2_salon + m2_terrain + m2_piece_a_vivre_voisin + m2_terrain_voisin +
## nb_etage + vue_mer + note_vue + note_condition + note_globale_construction +
## m2_surface_au_sol + m2_sous_sol + annee_construction + code_postal +
## lat + long
##
## Df Sum of Sq RSS AIC
## - nb_etage 1 6.2278e+10 8.6575e+14 527689
## - m2_surface_au_sol 1 7.8648e+10 8.6577e+14 527689
## - m2_sous_sol 1 7.8732e+10 8.6577e+14 527689
## - m2_salon 1 7.9152e+10 8.6577e+14 527689
## <none> 8.6569e+14 527689
## - mois_achat 1 1.4087e+11 8.6583e+14 527690
## - m2_terrain 1 2.3078e+11 8.6592e+14 527693
## - m2_terrain_voisin 1 1.0671e+12 8.6676e+14 527714
## - m2_piece_a_vivre_voisin 1 1.6894e+12 8.6738e+14 527729
## - annee_achat 1 2.4420e+12 8.6813e+14 527748
## - note_condition 1 5.2953e+12 8.7099e+14 527819
## - long 1 1.0244e+13 8.7594e+14 527941
## - code_postal 1 1.3015e+13 8.7871e+14 528009
## - salle_de_bain 1 1.3564e+13 8.7926e+14 528023
## - chambres 1 1.4986e+13 8.8068e+14 528058
## - note_vue 1 2.4667e+13 8.9036e+14 528294
## - vue_mer 1 4.6995e+13 9.1269e+14 528830
## - annee_construction 1 6.8524e+13 9.3422e+14 529333
## - note_globale_construction 1 8.2814e+13 9.4851e+14 529662
## - lat 1 1.2839e+14 9.9408e+14 530676
##
## Step: AIC=527688.5
## price ~ annee_achat + mois_achat + chambres + salle_de_bain +
## m2_salon + m2_terrain + m2_piece_a_vivre_voisin + m2_terrain_voisin +
## vue_mer + note_vue + note_condition + note_globale_construction +
## m2_surface_au_sol + m2_sous_sol + annee_construction + code_postal +
## lat + long
##
## Df Sum of Sq RSS AIC
## - m2_surface_au_sol 1 7.8583e+10 8.6583e+14 527688
## - m2_sous_sol 1 7.8674e+10 8.6583e+14 527688
## - m2_salon 1 7.9090e+10 8.6583e+14 527688
## <none> 8.6575e+14 527689
## - mois_achat 1 1.4095e+11 8.6589e+14 527690
## - m2_terrain 1 2.2649e+11 8.6598e+14 527692
## - m2_terrain_voisin 1 1.0830e+12 8.6684e+14 527714
## - m2_piece_a_vivre_voisin 1 1.6369e+12 8.6739e+14 527727
## - annee_achat 1 2.4334e+12 8.6819e+14 527747
## - note_condition 1 5.2513e+12 8.7101e+14 527817
## - long 1 1.0409e+13 8.7616e+14 527945
## - code_postal 1 1.2958e+13 8.7871e+14 528008
## - salle_de_bain 1 1.4645e+13 8.8040e+14 528049
## - chambres 1 1.4951e+13 8.8070e+14 528057
## - note_vue 1 2.4733e+13 8.9049e+14 528295
## - vue_mer 1 4.7034e+13 9.1279e+14 528830
## - annee_construction 1 6.9256e+13 9.3501e+14 529350
## - note_globale_construction 1 8.3957e+13 9.4971e+14 529687
## - lat 1 1.2962e+14 9.9537e+14 530702
##
## Step: AIC=527688.5
## price ~ annee_achat + mois_achat + chambres + salle_de_bain +
## m2_salon + m2_terrain + m2_piece_a_vivre_voisin + m2_terrain_voisin +
## vue_mer + note_vue + note_condition + note_globale_construction +
## m2_sous_sol + annee_construction + code_postal + lat + long
##
## Df Sum of Sq RSS AIC
## <none> 8.6583e+14 527688
## - mois_achat 1 1.4027e+11 8.6597e+14 527690
## - m2_terrain 1 2.2598e+11 8.6606e+14 527692
## - m2_terrain_voisin 1 1.0794e+12 8.6691e+14 527713
## - m2_piece_a_vivre_voisin 1 1.6428e+12 8.6748e+14 527727
## - annee_achat 1 2.4301e+12 8.6826e+14 527747
## - m2_sous_sol 1 2.7236e+12 8.6856e+14 527754
## - note_condition 1 5.2486e+12 8.7108e+14 527817
## - long 1 1.0412e+13 8.7624e+14 527945
## - code_postal 1 1.2959e+13 8.7879e+14 528008
## - salle_de_bain 1 1.4643e+13 8.8048e+14 528049
## - chambres 1 1.4966e+13 8.8080e+14 528057
## - note_vue 1 2.4717e+13 8.9055e+14 528295
## - vue_mer 1 4.7099e+13 9.1293e+14 528831
## - annee_construction 1 6.9237e+13 9.3507e+14 529349
## - note_globale_construction 1 8.3909e+13 9.4974e+14 529686
## - m2_salon 1 1.0148e+14 9.6731e+14 530082
## - lat 1 1.2959e+14 9.9542e+14 530701
Grâce à ce code, j’ai construit un tableau récapitulatif des résultats concernant le modèle que la méthode BACKWARD propose.
sumres.back = summary(res.back)
Tableau.backward = data.frame(nombre_var_explicatives= extractAIC(res.back)[1]-1 ,
AIC = extractAIC(res.back)[2], BIC = BIC(res.back),
CpMallows = ols_mallows_cp(res.back,regTOT),
R_carre = round(sumres.back$r.squared,4),
R_carre_ajuste = round(sumres.back$adj.r.squared,4))
kable(Tableau.backward, align = "ccccccc") %>% kable_styling(full_width = F)| nombre_var_explicatives | AIC | BIC | CpMallows | R_carre | R_carre_ajuste |
|---|---|---|---|---|---|
| 17 | 527688.5 | 589177.2 | 18.63014 | 0.7028 | 0.7025 |
Ensuite, ce code permet de voir, pour chaque nombre de variables conservées dans le modèle, quelles sont celles qui sont retenues. Ces dernières sont logiquement celles qui donnent les meilleurs résultats pour les différents critères.
res.back = regsubsets(price~ . - date_achat- date_mois_an, data = data,
method = "backward", nvmax = 20)
sumres.back = summary(res.back);sumres.back## Subset selection object
## Call: regsubsets.formula(price ~ . - date_achat - date_mois_an, data = data,
## method = "backward", nvmax = 20)
## 20 Variables (and intercept)
## Forced in Forced out
## annee_achat FALSE FALSE
## mois_achat FALSE FALSE
## chambres FALSE FALSE
## salle_de_bain FALSE FALSE
## toilette_hors_sdb FALSE FALSE
## m2_salon FALSE FALSE
## m2_terrain FALSE FALSE
## m2_piece_a_vivre_voisin FALSE FALSE
## m2_terrain_voisin FALSE FALSE
## nb_etage FALSE FALSE
## vue_mer FALSE FALSE
## note_vue FALSE FALSE
## note_condition FALSE FALSE
## note_globale_construction FALSE FALSE
## m2_surface_au_sol FALSE FALSE
## m2_sous_sol FALSE FALSE
## annee_construction FALSE FALSE
## code_postal FALSE FALSE
## lat FALSE FALSE
## long FALSE FALSE
## 1 subsets of each size up to 20
## Selection Algorithm: backward
## annee_achat mois_achat chambres salle_de_bain toilette_hors_sdb
## 1 ( 1 ) " " " " " " " " " "
## 2 ( 1 ) " " " " " " " " " "
## 3 ( 1 ) " " " " " " " " " "
## 4 ( 1 ) " " " " " " " " " "
## 5 ( 1 ) " " " " " " " " " "
## 6 ( 1 ) " " " " " " " " " "
## 7 ( 1 ) " " " " " " "*" " "
## 8 ( 1 ) " " " " "*" "*" " "
## 9 ( 1 ) " " " " "*" "*" " "
## 10 ( 1 ) " " " " "*" "*" " "
## 11 ( 1 ) "*" " " "*" "*" " "
## 12 ( 1 ) "*" " " "*" "*" " "
## 13 ( 1 ) "*" " " "*" "*" " "
## 14 ( 1 ) "*" " " "*" "*" " "
## 15 ( 1 ) "*" " " "*" "*" " "
## 16 ( 1 ) "*" " " "*" "*" " "
## 17 ( 1 ) "*" "*" "*" "*" " "
## 18 ( 1 ) "*" "*" "*" "*" " "
## 19 ( 1 ) "*" "*" "*" "*" " "
## 20 ( 1 ) "*" "*" "*" "*" "*"
## m2_salon m2_terrain m2_piece_a_vivre_voisin m2_terrain_voisin
## 1 ( 1 ) "*" " " " " " "
## 2 ( 1 ) "*" " " " " " "
## 3 ( 1 ) "*" " " " " " "
## 4 ( 1 ) "*" " " " " " "
## 5 ( 1 ) "*" " " " " " "
## 6 ( 1 ) "*" " " " " " "
## 7 ( 1 ) "*" " " " " " "
## 8 ( 1 ) "*" " " " " " "
## 9 ( 1 ) "*" " " " " " "
## 10 ( 1 ) "*" " " " " " "
## 11 ( 1 ) "*" " " " " " "
## 12 ( 1 ) "*" " " " " " "
## 13 ( 1 ) "*" " " " " " "
## 14 ( 1 ) "*" " " "*" " "
## 15 ( 1 ) "*" " " "*" "*"
## 16 ( 1 ) "*" "*" "*" "*"
## 17 ( 1 ) "*" "*" "*" "*"
## 18 ( 1 ) "*" "*" "*" "*"
## 19 ( 1 ) "*" "*" "*" "*"
## 20 ( 1 ) "*" "*" "*" "*"
## nb_etage vue_mer note_vue note_condition note_globale_construction
## 1 ( 1 ) " " " " " " " " " "
## 2 ( 1 ) " " " " " " " " "*"
## 3 ( 1 ) " " " " " " " " "*"
## 4 ( 1 ) " " " " " " " " "*"
## 5 ( 1 ) " " "*" " " " " "*"
## 6 ( 1 ) " " "*" "*" " " "*"
## 7 ( 1 ) " " "*" "*" " " "*"
## 8 ( 1 ) " " "*" "*" " " "*"
## 9 ( 1 ) " " "*" "*" " " "*"
## 10 ( 1 ) " " "*" "*" " " "*"
## 11 ( 1 ) " " "*" "*" " " "*"
## 12 ( 1 ) " " "*" "*" "*" "*"
## 13 ( 1 ) " " "*" "*" "*" "*"
## 14 ( 1 ) " " "*" "*" "*" "*"
## 15 ( 1 ) " " "*" "*" "*" "*"
## 16 ( 1 ) " " "*" "*" "*" "*"
## 17 ( 1 ) " " "*" "*" "*" "*"
## 18 ( 1 ) " " "*" "*" "*" "*"
## 19 ( 1 ) "*" "*" "*" "*" "*"
## 20 ( 1 ) "*" "*" "*" "*" "*"
## m2_surface_au_sol m2_sous_sol annee_construction code_postal lat long
## 1 ( 1 ) " " " " " " " " " " " "
## 2 ( 1 ) " " " " " " " " " " " "
## 3 ( 1 ) " " " " "*" " " " " " "
## 4 ( 1 ) " " " " "*" " " "*" " "
## 5 ( 1 ) " " " " "*" " " "*" " "
## 6 ( 1 ) " " " " "*" " " "*" " "
## 7 ( 1 ) " " " " "*" " " "*" " "
## 8 ( 1 ) " " " " "*" " " "*" " "
## 9 ( 1 ) " " " " "*" "*" "*" " "
## 10 ( 1 ) " " " " "*" "*" "*" "*"
## 11 ( 1 ) " " " " "*" "*" "*" "*"
## 12 ( 1 ) " " " " "*" "*" "*" "*"
## 13 ( 1 ) " " "*" "*" "*" "*" "*"
## 14 ( 1 ) " " "*" "*" "*" "*" "*"
## 15 ( 1 ) " " "*" "*" "*" "*" "*"
## 16 ( 1 ) " " "*" "*" "*" "*" "*"
## 17 ( 1 ) " " "*" "*" "*" "*" "*"
## 18 ( 1 ) "*" "*" "*" "*" "*" "*"
## 19 ( 1 ) "*" "*" "*" "*" "*" "*"
## 20 ( 1 ) "*" "*" "*" "*" "*" "*"
Pour faciliter la compréhension des différents résultats que nous donnent la méthode BACKWARD, des graphiques permettant de voir les différents critères sont très parlant et aide à prendre de décisions plus simplement.
GG1 = ggplot(data=data.frame(Nb_var = seq(1:20), Rcar =sumres.back$rsq))+
geom_line(aes(x = Nb_var, y = Rcar), color = "#569AF3") +
xlab("Nombre de variables explicatives") + ylab("R carré")+
geom_point(aes(x=which.max(sumres.back$rsq),
y=sumres.back$rsq[which.max(sumres.back$rsq)]),size=5, color="#CC10D5")
GG2 = ggplot(data=data.frame(Nb_var = seq(1:20), Rcar_ajus =sumres.back$adjr2))+
geom_line(aes(x = Nb_var, y = Rcar_ajus), color = "#569AF3") +
xlab("Nombre de variables explicatives") + ylab("R carré ajusté")+
geom_point(aes(x=which.max(sumres.back$adjr2),
y=sumres.back$adjr2[which.max(sumres.back$adjr2)]),size=5, color="#CC10D5")
GG3 = ggplot(data=data.frame(Nb_var = seq(1:20), cp =sumres.back$cp))+
geom_line(aes(x = Nb_var, y = cp), color = "#569AF3") +
xlab("Nombre de variables explicatives") + ylab("Cp de Mallows")+
geom_point(aes(x=which.min(sumres.back$cp),
y=sumres.back$adjr2[which.min(sumres.back$cp)]),size=5, color="#CC10D5")
GG4 = ggplot(data=data.frame(Nb_var = seq(1:20), BIC =sumres.back$bic))+
geom_line(aes(x = Nb_var, y = BIC), color = "#569AF3") +
xlab("Nombre de variables explicatives")+ylab("Critère d'information bayésien (BIC)")+
geom_point(aes(x=which.min(sumres.back$bic),
y=sumres.back$bic[which.min(sumres.back$bic)]),size=5, color="#CC10D5")
grid.arrange(GG1, GG2, GG3, GG4, ncol=2, nrow = 2)Les graphiques, ci-dessus permettent de voir quel est le nombre de variables que chaque critère retient. Le R² n’est pas un outil très satisfaisant : il augmente en même temps que le nombre de variables augmentent, il retiendra donc forcément le modèle à 20 variables explicatives. Voici un tableau qui reprend le nombre de variables explicatives retenues par chaque critère :
Tableau1 = data.frame(Critere = c("R_carré","R_carré_ajusté","Cp_Mallows", "BIC"),
Nombre_de_var_retenues = c(which.max(sumres.back$rsq),
which.max(sumres.back$adjr2),
which.min(sumres.back$cp),
which.min(sumres.back$bic)))
kable(t(Tableau1), align = "cccc") %>% kable_styling(full_width = F)| Critere | R_carré | R_carré_ajusté | Cp_Mallows | BIC |
| Nombre_de_var_retenues | 20 | 19 | 17 | 15 |
CONCLUSION METHODE BACKWARD : Les critères proposent un nombre de variables compris entre 15 et 17. Analysons les données avec d’autres méthodes pour voir si les résultats peuvent nous aider à prendre une décision sur ce nombre de variables explicatives à conserver.
Régression avec la méthode EXHAUSTIVE
Le principe général est le même. Il y a juste la méthode appelée par la fonction qui change. Je ne fais donc pas apparaître le code pour ne pas surcharger la présentation. Cette méthode EXHAUSTIVE, est assez fastidieuse. Elle consiste à considérer toutes les combinaisons de sous-modèles possibles. Soit, tous les modèles à une variable, tous les modèles à deux variables, etc. Ce qui revient dans ce cas à 2^20 -1 modèles, soit 1048576 modèles. R exécute cette régression et donne exactement les mêmes résultats qu’avec la méthode BACKWARD :
| Critere | R_carré | R_carré_ajusté | Cp_Mallows | BIC |
| Nombre_de_var_retenues | 20 | 19 | 17 | 15 |
Ci-dessous, nous pouvons visualiser quelles sont les variables retenues par la méthode EXHAUSTIVE et pour chaque critère. Les carrés noirs représentent les variables que la méthode conseille de conserver dans le modèle.
Régression avec la méthode FORWARD
Le principe général de cette méthode ascendante est le même que les deux méthodes précédentes. Il y a juste la méthode appelée par la fonction qui change (argument “direction”). Je ne fais donc pas apparaître le code pour ne pas surcharger la présentation. Cette méthode FORWARD, reprend le principe de la méthode BACKWARD, mais dans le sens inverse. Elle consiste à ajouter au fur et à mesure des variables explicatives. On commence par des modèles avec une unique variable, puis on ajoute une variable explicatives et on retient celui qui améliore le plus les critères. Et on recommence jusqu’à ce qu’aucune variable ajoutée n’améliore le modèle précédent. R exécute cette régression et donne exactement les mêmes résultats qu’avec la méthode BACKWARD et EXHAUSTIVE :
| nombre_var_explicatives | AIC | BIC | CpMallows | R_carre | R_carre_ajuste |
|---|---|---|---|---|---|
| 17 | 527688.5 | 589177.2 | 18.63014 | 0.7028 | 0.7025 |
| Critere | R_carré | R_carré_ajusté | Cp_Mallows | BIC |
| Nombre_de_var_retenues | 20 | 19 | 17 | 15 |
Régression avec la méthode STEPWISE BOTH
Cette méthode est une combinaison de sélections FORWARD et BACKWARD. Cela permet de vérifier que l’ajout d’une variable ne provoque pas la suppression d’une variable déjà introduite (qui deviendrait non significative). On part d’un modèle sans variables explicatives, puis on ajoute de manière séquentielle les variables explicatives les plus contributives. Après avoir ajouté chaque nouvelle variable, on supprime toutes les variables qui n’améliore pas l’ajustement du modèle. R exécute cette régression et donne pratiquement les mêmes résultats qu’avec la méthode BACKWARD, FORWARD et EXHAUSTIVE.
| nombre_var_explicatives | AIC | BIC | CpMallows | R_carre | R_carre_ajuste |
|---|---|---|---|---|---|
| 17 | 527688.5 | 589177.2 | 18.63014 | 0.7028 | 0.7025 |
| Critere | R_carré | R_carré_ajusté | Cp_Mallows | BIC |
| Nombre_de_var_retenues | 20 | 19 | 18 | 15 |
Voici un tableau récapitulatif du nombre de variables retenues par toutes les méthodes et critères présentés précédemment :
| R carré | R carré ajusté | Cp de Mallows | BIC | |
|---|---|---|---|---|
| Backward | 20 | 19 | 17 | 15 |
| Exhaustive | 20 | 19 | 17 | 15 |
| Forward | 20 | 19 | 17 | 15 |
| Both | 20 | 19 | 18 | 15 |
Régression avec méthodes graphiques
Entre 15 et 18 variables explicatives sont proposées par les méthodes présentées précédemment (cf. tableau au-dessus). Pour affiner ma prise de décision, je décide de tracer graphiquement le R² ajusté , ainsi que le Cp de Mallows. En effet, je vois qu’un modèle avec 15 variables explicatives pourrait être un bon modèle. Sur ces graphiques, on voit qu’à partir de 15 variables, les critères stagnent, il n’y a donc qu’une minime amélioration entre 15 ou plus de variables.
x=data[,2:21];y=data[, 22]
model1= leaps(x, y, method=c("adjr2"), nbest=1,names=NULL, df=NROW(x),
strictly.compatible=TRUE)
GG5 = ggplot(data.frame(model1$size,model1$adjr2)) +
geom_line(aes(x = model1$size, y = model1$adjr2), color = "#569AF3")+
ggtitle("R carré ajusté")+
scale_y_continuous(labels = function(x) format(x, scientific = FALSE))+
ylab("R carré ajusté") +xlab("Nombre de variables explicatives")+
geom_hline(aes(yintercept= model1$adjr2[15]), color = "#F3787A", size=0.5)+
geom_vline(aes(xintercept= 15), color = "#F3787A", size=0.5)
model2= leaps(x, y, method=c("Cp"), nbest=1,names=NULL, df=NROW(x),
strictly.compatible=TRUE)
GG6 = ggplot(data.frame(model2$size,model2$Cp)) +
geom_line(aes(x = model2$size, y = model2$Cp), color = "#569AF3", size =1)+
ggtitle("Cp de Mallows")+
scale_y_continuous(labels = function(x) format(x, scientific = FALSE))+
ylab("Cp de Mallows") +xlab("Nombre de variables explicatives")+
geom_hline(aes(yintercept= min(model2$Cp)), color = "#F3787A", size=0.5)+
geom_vline(aes(xintercept= 15), color = "#F3787A", size=0.5)
grid.arrange(GG5, GG6, ncol=2, nrow = 1)Avec ces graphiques, on voit clairement qu’un modèle constitué de 15 variables peut être un bon modèle. Je lance maintenant les quatres méthodes précédentes pour savoir quelle sont les 15 variables qui sont retenues par chaque modèle. Il n’apparaît qu’un seul code (pour la méthode backward), mais les autres méthodes ont exactement le même code, seul l’argument “method” change. Le code est disponible dans le code source.
reg.back = regsubsets(price~ . - date_achat- date_mois_an,
data = data,
method = "backward",
nvmax = 15)
summary(res.back)
coef(res.back,15)Les quatre méthodes sortent les mêmes 15 variables, et donc, les mêmes coefficients de régression. Voici un tableau résumant les variables retenues, avec leur coefficient respectif.
| x | |
|---|---|
| (Intercept) | -5.169936e+07 |
| annee_achat | 2.970140e+04 |
| chambres | -3.613449e+04 |
| salle_de_bain | 5.322856e+04 |
| m2_salon | 1.933962e+03 |
| m2_piece_a_vivre_voisin | 2.285771e+02 |
| m2_terrain_voisin | -2.773120e+00 |
| vue_mer | 5.906902e+05 |
| note_vue | 5.298002e+04 |
| note_condition | 2.614723e+04 |
| note_globale_construction | 9.728031e+04 |
| m2_sous_sol | -3.475670e+02 |
| annee_construction | -2.676458e+03 |
| code_postal | -5.880576e+02 |
| lat | 6.037555e+05 |
| long | -2.080123e+05 |
À ce stade, je décide de garder un modèle avec les 15 variables que me proposent les méthodes. Plusieurs indicateurs m’ont permis de prendre cette décision. Il est vrai que les critères AIC, R², R² ajusté et Cp de Mallows recommande un peu plus de 15 variables. Mais, en analysant graphiquement ces critères, j’ai pu voir qu’ils atteignent pratiquement leur maximum avec 15 variables, la différence quand on ajoute d’autres vavirables est vraiment subtile. De plus, avec l’analyse linéaire de ce modèle, ci-dessous, donne des résultats très satisfaisants :
summary(lm(price~ annee_achat+chambres+salle_de_bain+m2_salon+
m2_piece_a_vivre_voisin +m2_terrain_voisin+vue_mer+
note_vue+note_condition+note_globale_construction+
m2_sous_sol+annee_construction+code_postal+lat+long,
data = data))##
## Call:
## lm(formula = price ~ annee_achat + chambres + salle_de_bain +
## m2_salon + m2_piece_a_vivre_voisin + m2_terrain_voisin +
## vue_mer + note_vue + note_condition + note_globale_construction +
## m2_sous_sol + annee_construction + code_postal + lat + long,
## data = data)
##
## Residuals:
## Min 1Q Median 3Q Max
## -1261392 -98155 -8855 78168 4309599
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) -5.170e+07 6.555e+06 -7.887 3.24e-15 ***
## annee_achat 2.970e+04 2.920e+03 10.172 < 2e-16 ***
## chambres -3.613e+04 1.863e+03 -19.397 < 2e-16 ***
## salle_de_bain 5.323e+04 2.786e+03 19.104 < 2e-16 ***
## m2_salon 1.934e+03 3.825e+01 50.556 < 2e-16 ***
## m2_piece_a_vivre_voisin 2.286e+02 3.660e+01 6.245 4.33e-10 ***
## m2_terrain_voisin -2.773e+00 5.674e-01 -4.888 1.03e-06 ***
## vue_mer 5.907e+05 1.725e+04 34.251 < 2e-16 ***
## note_vue 5.298e+04 2.127e+03 24.910 < 2e-16 ***
## note_condition 2.615e+04 2.301e+03 11.361 < 2e-16 ***
## note_globale_construction 9.728e+04 2.126e+03 45.765 < 2e-16 ***
## m2_sous_sol -3.476e+02 4.183e+01 -8.309 < 2e-16 ***
## annee_construction -2.676e+03 6.415e+01 -41.721 < 2e-16 ***
## code_postal -5.881e+02 3.268e+01 -17.996 < 2e-16 ***
## lat 6.038e+05 1.063e+04 56.782 < 2e-16 ***
## long -2.080e+05 1.299e+04 -16.016 < 2e-16 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 200300 on 21597 degrees of freedom
## Multiple R-squared: 0.7026, Adjusted R-squared: 0.7024
## F-statistic: 3402 on 15 and 21597 DF, p-value: < 2.2e-16
CONCLUSION : Avec cette sortie, nous pouvons voir que les 15 variables sont toutes très significatives. De plus le R² = 0.7026 qui est un bon score et le R² ajusté est tout aussi bon avec une valeur de 0.7024. La p.value globale du modèle est très faible, ce qui signifie que la confiance que l’on peut apporter au modèle est très grande.
Validation simple
Un autre critère de sélection de modèles est la sélection par rapport à l’erreur de prédiction. Pour cela, il faut fabriquer un échantillon d’apprentissage, ainsi qu’un échantillon test. Le but est de trouver le modèle qui minimise cette erreur de prédiction, et de s’assurer que le modèle saura faire des bonnes prédictions sur de nouvelles données. Je programme un “set.seed” qui permet, d’une simulation à l’autre, de retrouver les mêmes résultats. Cela permet d’avoir des résultats en accord avec les commentaires que je vais faire. La première étape est donc la création de l’échantillon d’apprentissage et l’échantillon test qui sera le complément du premier échantillon. J’effectue une régression sur cet échantillon d’apprentissage pour avoir une idée des variables qui sont retenues avec cet échantillon.
set.seed(4)
ech.apprentissage = sample(c(TRUE,FALSE), nrow(data), rep =TRUE)
ech.test = (!ech.apprentissage)
summary(lm(price~.- date_achat- date_mois_an,data=data[ech.apprentissage,]))##
## Call:
## lm(formula = price ~ . - date_achat - date_mois_an, data = data[ech.apprentissage,
## ])
##
## Residuals:
## Min 1Q Median 3Q Max
## -1136835 -101329 -8823 81129 4237829
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) -5.461e+07 1.421e+07 -3.844 0.000122 ***
## annee_achat 3.263e+04 6.729e+03 4.849 1.26e-06 ***
## mois_achat 5.070e+01 1.011e+03 0.050 0.960000
## chambres -3.997e+04 2.802e+03 -14.267 < 2e-16 ***
## salle_de_bain 5.431e+04 4.712e+03 11.526 < 2e-16 ***
## toilette_hors_sdb -1.295e+03 2.991e+03 -0.433 0.665013
## m2_salon 8.940e+05 6.148e+05 1.454 0.145945
## m2_terrain 1.468e-01 8.496e-01 0.173 0.862827
## m2_piece_a_vivre_voisin 2.523e+02 5.347e+01 4.719 2.40e-06 ***
## m2_terrain_voisin -4.155e+00 1.247e+00 -3.333 0.000864 ***
## nb_etage 7.039e+03 4.593e+03 1.533 0.125415
## vue_mer 6.788e+05 2.682e+04 25.313 < 2e-16 ***
## note_vue 4.948e+04 3.017e+03 16.400 < 2e-16 ***
## note_condition 2.649e+04 3.309e+03 8.006 1.31e-15 ***
## note_globale_construction 9.268e+04 3.099e+03 29.905 < 2e-16 ***
## m2_surface_au_sol -8.920e+05 6.148e+05 -1.451 0.146852
## m2_sous_sol -8.922e+05 6.148e+05 -1.451 0.146735
## annee_construction -2.723e+03 9.519e+01 -28.612 < 2e-16 ***
## code_postal -6.581e+02 4.739e+01 -13.888 < 2e-16 ***
## lat 5.989e+05 1.541e+04 38.866 < 2e-16 ***
## long -2.425e+05 1.884e+04 -12.875 < 2e-16 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 203700 on 10789 degrees of freedom
## Multiple R-squared: 0.6995, Adjusted R-squared: 0.6989
## F-statistic: 1255 on 20 and 10789 DF, p-value: < 2.2e-16
Avec cette régression, on retrouve 13 des variables explicatives précédentes.
Ensuite, j’effectue la sélection de modèles sur l’échantillon d’apprentissage. Les 4 graphiques, comme précédemment sont affichés. Il faut savoir que les graphiques ci-dessous sont pour la méthode EXHAUSTIVE, mais les autres méthodes vues précédemment donnent exactement les mêmes résultats. Je ne les fait donc pas apparaître pour ne pas surcharger la présentation. Le code est disponible dans le code source.
| Critere | Nombre_de_var_retenues |
|---|---|
| R_carré | 20 |
| R_carré_ajusté | 17 |
| Cp_Mallows | 17 |
| BIC | 15 |
Le tableau ci-dessus reprend, comme précédemment, le nombre de variables retenues en fonction de chaque critère. Les résultats sont similaires aux régressions précédentes. Ensuite, on procède à l’évaluation des modèles, en regardant pour lequel l’erreur de prédiction est la moins élevée. Pour cela, on calcule, pour chacun des modèles (modèle à 1 variable, modèle à 2 variables, etc.) l’erreur de prédiction. Une fois toutes les erreurs recensées, on trace un graphique permettant de voir pour quel nombre de variables, inclues dans le modèle, l’erreur est la plus faible.
set.seed(4)
X.test1 = model.matrix(price~.- date_achat- date_mois_an, data= data[ech.test,])
erreur1 = rep(NA, 20)
for (i in 1:20){
coefi = coef(regappr1, id=i)
pred <- X.test1[,names(coefi)]%*%coefi
erreur1[i] = mean((data$price[ech.test]-pred)**2)}Voici un tableau qui reprend les 15 variables retenues par ce modèle avec les coefficients correspondants.
| Coefficient | |
|---|---|
| (Intercept) | -5.495347e+07 |
| annee_achat | 3.226994e+04 |
| chambres | -4.002419e+04 |
| salle_de_bain | 5.670653e+04 |
| m2_salon | 2.018345e+03 |
| m2_piece_a_vivre_voisin | 2.440973e+02 |
| m2_terrain_voisin | -4.049907e+00 |
| vue_mer | 6.800370e+05 |
| note_vue | 4.956039e+04 |
| note_condition | 2.620813e+04 |
| note_globale_construction | 9.293232e+04 |
| m2_sous_sol | -3.045662e+02 |
| annee_construction | -2.712927e+03 |
| code_postal | -6.507826e+02 |
| lat | 6.005111e+05 |
| long | -2.446696e+05 |
CONCLUSION : Avec cette validation simple, nous pouvons confirmer un modèle avec 15 variables. Ces dernières sont représentées dans le tableau ci-dessus, avec leur coefficient respectif.
Validation croisée
La méthode de validation simple a des inconvénients. En effet, qu’une partie du jeu de données a été utilisé pour s’entraîner, et donc qu’une partie pour tester… Cela peut, dans certains cas, biaiser l’estimation de la performance. La validation croisée permet d’éviter ce phénomène. Elle permet d’utiliser l’intégralité du jeu de données à la fois pour l’entraînement et pour la validation.Il n’existe pas de fonction intégrée dans R pour prédire les objets regsubsets. Il faut donc en écrire une. (trouvée sur le site https://github.com/). Comment procéder ?
- Premièrement, on divise le jeu de données en folds. J’en crée 10. Un à un, les groupes sont d’abord utilisés comme jeu d’entraînement et les autres sont utilisés pour le test.
- Ensuite, une recherche de modèle, à l’aide de la méthode FORWARD est lancée sur le jeu d’entraînement Pour chaque nombre de variables explicatives, ici de 1 à 20, on calcule les prédictions sur le jeu de test.
- L’erreur faite par le modèle contenant un nombre de variables i, et pour le jeu de test k, est calculée, puis enregistrée dans un tableau. Une fois le tableau complet, la moyenne des erreurs pour chaque nombre de variables du modèle est calculée.
- Enfin, un graphique qui trace ces erreurs permet de voir pour quel nombre de variables les erreurs sont les plus faibles.
predict.regsubsets=function(object, newdata, id,...){
form=as.formula(object$call[[2]])
mat=model.matrix(form, newdata)
coefi=coef(object, id=id)
mat[, names(coefi)]%*%coefi}data.new = data[2:22]# -date_achat- date_mois_an
folds = sample(rep(1:10, length=nrow(data.new))) #création des folds
erreurs1 = matrix(NA, 10, 20) #création de la table contenant les erreurs
for(k in 1:10){#Boucle pour calculer les erreurs
regfit = regsubsets(price~., data=data.new[folds !=k ,], nvmax=20, method="forward")
for (i in 1:20){
pred = predict(regfit, data.new[folds == k,], id=i)
erreurs1[k,i] = mean((data.new$price[folds==k] - pred)^2)}}
moyenne.erreur1 = sqrt(apply(erreurs1, 2, mean))#Moyenne des erreurs| Nombre_de_variables_retenues |
|---|
| 15 |
Avec la méthode FORWARD, la validation croisée préconise 15 variables dans le modèle. Maintenant, je regarde quelles sont les 15 variables retenues.
reg.best <-regsubsets(price~. -date_achat-date_mois_an, data=data, nvmax = 15)
names(coef(reg.best, 15))## [1] "(Intercept)" "annee_achat"
## [3] "chambres" "salle_de_bain"
## [5] "m2_salon" "m2_piece_a_vivre_voisin"
## [7] "m2_terrain_voisin" "vue_mer"
## [9] "note_vue" "note_condition"
## [11] "note_globale_construction" "m2_sous_sol"
## [13] "annee_construction" "code_postal"
## [15] "lat" "long"
Une fois les 15 variables explicatives identifiées, je lance une régression sur ces dernières.
À savoir : Toutes les méthodes (BACKWARD, EXHAUSTIVE et STEPWISE BOTH) donnent le même résultat pour 15 variables. Le code les concernant se trouve dans le code source.
##
## Call:
## lm(formula = price ~ annee_achat + chambres + salle_de_bain +
## m2_salon + m2_piece_a_vivre_voisin + m2_terrain_voisin +
## vue_mer + note_vue + note_condition + note_globale_construction +
## m2_sous_sol + annee_construction + code_postal + lat + long,
## data = data)
##
## Residuals:
## Min 1Q Median 3Q Max
## -1261392 -98155 -8855 78168 4309599
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) -5.170e+07 6.555e+06 -7.887 3.24e-15 ***
## annee_achat 2.970e+04 2.920e+03 10.172 < 2e-16 ***
## chambres -3.613e+04 1.863e+03 -19.397 < 2e-16 ***
## salle_de_bain 5.323e+04 2.786e+03 19.104 < 2e-16 ***
## m2_salon 1.934e+03 3.825e+01 50.556 < 2e-16 ***
## m2_piece_a_vivre_voisin 2.286e+02 3.660e+01 6.245 4.33e-10 ***
## m2_terrain_voisin -2.773e+00 5.674e-01 -4.888 1.03e-06 ***
## vue_mer 5.907e+05 1.725e+04 34.251 < 2e-16 ***
## note_vue 5.298e+04 2.127e+03 24.910 < 2e-16 ***
## note_condition 2.615e+04 2.301e+03 11.361 < 2e-16 ***
## note_globale_construction 9.728e+04 2.126e+03 45.765 < 2e-16 ***
## m2_sous_sol -3.476e+02 4.183e+01 -8.309 < 2e-16 ***
## annee_construction -2.676e+03 6.415e+01 -41.721 < 2e-16 ***
## code_postal -5.881e+02 3.268e+01 -17.996 < 2e-16 ***
## lat 6.038e+05 1.063e+04 56.782 < 2e-16 ***
## long -2.080e+05 1.299e+04 -16.016 < 2e-16 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 200300 on 21597 degrees of freedom
## Multiple R-squared: 0.7026, Adjusted R-squared: 0.7024
## F-statistic: 3402 on 15 and 21597 DF, p-value: < 2.2e-16
| nombre_var_explicatives | AIC | BIC | CpMallows | R_carre | R_carre_ajuste |
|---|---|---|---|---|---|
| 15 | 527693.6 | 589166.3 | 23.75958 | 0.7026 | 0.7024 |
CONCLUSION : Avec cette validation croisée, nous pouvons confirmer un modèle avec 15 variables. Ces dernières sont représentées dans le tableau ci-dessus, avec leur coefficient respectif. Avec cette sortie, nous pouvons voir que les 15 variables sont toutes très significatives. De plus le R² = 0.7026 qui est un bon score et le R² ajusté est tout aussi bon avec une valeur de 0.7024. La p.value globale du modèle est très faible, ce qui signifie que la confiance que l’on peut apporter au modèle est très grande.
Ridge et Lasso
Ces méthodes sont des méthodes de régression dites « régularisée » ou « pénalisée ». Ces deux méthodes, Ridge et Lasso, consistent toutes les deux à chercher à rétrécir les coefficients de régression, c’est-à-dire réduire le poids des variables. Voyons en détail ces deux méthodes.
Ridge
Cette méthode, comme dit précédemment, cherche à réduire le plus possible les coefficients \(\beta\) (proche de 0). La régression Ridge a pour particularité de conserver toutes les variables dans le modèle final. Il faut savoir que \(\lambda\), paramètre de réglage, est le paramètre qui permet d’affecter un poids aux coefficients. Plus \(\lambda\) est petit, plus les coefficients augmentent jusqu’à ce que \(\lambda\) soit proche de 0, où les coefficients ne sont pas régularisés, c’est-à-dire qu’ils seront les mêmes qu’avec la méthode de moindres carrés. Le but est donc de trouver le \(\lambda\) tel que l’erreur quadratique avec les coefficients régularisés sera inférieure à l’erreur quadratique des estimateurs des moindres carrés.
Voici, l’implémentation de cette méthode sous R : - alpha = 0 : permet de dire que c’est la méthode Ridge. - \(\lambda\) = 100 : nombre de valeurs de \(\lambda\) par défaut.
x = model.matrix(price~., data = data.new)[,-1]
y = data.new$price
ridge = glmnet(x, y, alpha = 0, nlambda = 100)
plot(ridge, xvar = "lambda", label = TRUE)Comme on peut le voir graphiquement, c’es le logarithme de \(\lambda\) qui est représenté. Comme dit précédemment, on peut voir que quand log (\(\lambda\)) > 18, tous les coefficients sont nuls. Plus \(\lambda\) est petit, plus les coefficients augmentent jusqu’à ce que \(\lambda\) soit proche de 0, où les coefficients ne sont pas régularisés, c’est-à-dire les mêmes qu’avec la méthode de moindres carrés.
Pour trouver le meilleur \(\lambda\), on procéde par une validation croisée, directement intégrée dans R avec cette fonction.
| lambda_meilleur | log_lambda_meilleur |
|---|---|
| 26010.49 | 10.16626 |
Le \(\lambda\) retenu est donc log(\(\lambda\)) = 10.16626.
On va calculer l’erreur quadratique associée à ce \(\lambda\). Pour cela, on prédit les valeurs avec l’échantillon test sur le modèle que nous avons retenu avec l’échantillon d’apprentissage. Puis, on compare avec les valeurs réelles de l’échantillon.
ridge.pred=predict(ridge,s=cv$lambda.min,newx=x[ech.test,])
kable(data.frame(MSE= mean((ridge.pred-y[ech.test])^2)),
align = "cc")%>% kable_styling(full_width = F)| MSE |
|---|
| 38706428470 |
Le MSE, qui est donc le plus petit, est représenté dans le tableau ci-dessus. Nous pouvons donc maintenant afficher les 20 coefficients de régression régularisés. Nous pouvons aussi les comparer avec le \(\lambda\) dit de « parcimonie ». Je le récupère graphiquement. On voit que ceux du deuxième modèle sont plus proche de 0, vu que le \(\lambda\) est plus elevé.
ridge.meilleur = glmnet(x,y,alpha=0,lambda = cv$lambda.min)
ridge.parcimonie = glmnet(x,y,alpha=0,lambda= exp(11.9))
coef1 = data.frame(as.matrix(coef(ridge.meilleur)))
coef2 = data.frame(as.matrix(coef(ridge.parcimonie)))
kable(data.frame(coef1, coef2),
col.names = c("Coefslambda meilleur", "Coefs lambda parcimonie"),
align = "cc")%>% kable_styling(full_width = F)| Coefslambda meilleur | Coefs lambda parcimonie | |
|---|---|---|
| (Intercept) | -6.098403e+07 | -5.175953e+07 |
| annee_achat | 2.936465e+04 | 1.613156e+04 |
| mois_achat | 5.338791e+02 | -4.757989e+02 |
| chambres | -2.834967e+04 | -9.273912e+03 |
| salle_de_bain | 4.943563e+04 | 4.513987e+04 |
| toilette_hors_sdb | -1.836370e+03 | -2.240531e+03 |
| m2_salon | 8.939214e+02 | 7.420274e+02 |
| m2_terrain | 1.142569e+00 | 8.848821e-01 |
| m2_piece_a_vivre_voisin | 4.019023e+02 | 6.036538e+02 |
| m2_terrain_voisin | -3.304793e+00 | -1.445544e+00 |
| nb_etage | 8.881049e+03 | 1.691773e+04 |
| vue_mer | 5.631819e+05 | 4.650210e+05 |
| note_vue | 5.310266e+04 | 5.164619e+04 |
| note_condition | 2.768421e+04 | 2.575563e+04 |
| note_globale_construction | 8.648667e+04 | 6.406238e+04 |
| m2_surface_au_sol | 8.951300e+02 | 7.179627e+02 |
| m2_sous_sol | 6.660682e+02 | 6.735763e+02 |
| annee_construction | -2.302598e+03 | -1.433940e+03 |
| code_postal | -4.622654e+02 | -1.810613e+02 |
| lat | 5.712847e+05 | 4.560191e+05 |
| long | -1.954690e+05 | -1.443936e+05 |
Lasso
Passons à la seconde méthode. Contrairement à la précédente, cette méhode permet l’élimination de variables. Comme la régression Ridge, cette régression Lasso permet d’affecter un poids \(\lambda\) aux coefficients de régression, et ainsi d’obtenir des coefficients qui tendent vers 0, et aussi qui peuvent être égaux à 0 pour une valeur de \(\lambda\) assez grande. Comme cette dernière permet la suppression de variables explicatives, elle se rapproche des méthodes de sélection vues juste précédemment en ne retenant qu’un sous-ensemble de variables explicatives.
Je procède de la même manière : - Implémentation de la régression Lasso. - Méthode de validation croisée pour trouver \(\lambda\) graphiquement. - Calcul de \(\lambda\). - Calcul du MSE associé à ce \(\lambda\). - Calcul des coefficients associés à ce \(\lambda\).
À savoir : Le deuxième trait en pointillé représente un choix de parcimonie. En effet, en régression, on a une préférence à la simplicité des modèles et cette deuxième solution témoigne d’une préférence à la régularisation affectée à ce \(\lambda\).
| lambda_meilleur | log_lambda_meilleur |
|---|---|
| 424 | 6.049512 |
| MSE |
|---|
| 38703454824 |
Nous pouvons comparer les coefficients obtenus avec le meilleur \(\lambda\) avec le \(\lambda\) dit de « parcimonie ». Je le récupère graphiquement. On voit que ceux du deuxième modèle sont plus proche de 0, vu que le \(\lambda\) est plus elevé. Nous pouvons voir qu’aucune variables n’est suprimée, mais certaines sont tout de même très proches de 0, par rapport à d’autres.
| Coefs lambda meilleur | Coefs lambda parcimonie | |
|---|---|---|
| (Intercept) | -6.522991e+07 | -5.082094e+07 |
| annee_achat | 3.641747e+04 | 1.528816e+04 |
| mois_achat | 1.296285e+03 | -5.104452e+02 |
| chambres | -3.584393e+04 | -7.847239e+03 |
| salle_de_bain | 5.175777e+04 | 4.481015e+04 |
| toilette_hors_sdb | -7.542373e+02 | -2.146619e+03 |
| m2_salon | 1.529840e+03 | 7.297149e+02 |
| m2_terrain | 1.230307e+00 | 8.701908e-01 |
| m2_piece_a_vivre_voisin | 2.450883e+02 | 6.088451e+02 |
| m2_terrain_voisin | -4.028477e+00 | -1.308571e+00 |
| nb_etage | 4.233917e+03 | 1.734174e+04 |
| vue_mer | 5.904989e+05 | 4.553014e+05 |
| note_vue | 5.277339e+04 | 5.126611e+04 |
| note_condition | 2.655218e+04 | 2.528934e+04 |
| note_globale_construction | 9.691969e+04 | 6.243212e+04 |
| m2_surface_au_sol | 3.882139e+02 | 7.034458e+02 |
| m2_sous_sol | 7.265495e+01 | 6.709023e+02 |
| annee_construction | -2.668402e+03 | -1.368401e+03 |
| code_postal | -5.885451e+02 | -1.630481e+02 |
| lat | 6.030399e+05 | 4.446549e+05 |
| long | -2.084678e+05 | -1.396327e+05 |
Comparaison des deux méthodes
Dans cette partie, j’affiche les coefficients estimés par la méthode Ridge et Lasso. On voit clairement que les coefficients sont très proches entre eux.
| Ridge | Lasso | |
|---|---|---|
| (Intercept) | -6.098403e+07 | -6.522991e+07 |
| annee_achat | 2.936465e+04 | 3.641747e+04 |
| mois_achat | 5.338791e+02 | 1.296285e+03 |
| chambres | -2.834967e+04 | -3.584393e+04 |
| salle_de_bain | 4.943563e+04 | 5.175777e+04 |
| toilette_hors_sdb | -1.836370e+03 | -7.542373e+02 |
| m2_salon | 8.939214e+02 | 1.529840e+03 |
| m2_terrain | 1.142569e+00 | 1.230307e+00 |
| m2_piece_a_vivre_voisin | 4.019023e+02 | 2.450883e+02 |
| m2_terrain_voisin | -3.304793e+00 | -4.028477e+00 |
| nb_etage | 8.881049e+03 | 4.233917e+03 |
| vue_mer | 5.631819e+05 | 5.904989e+05 |
| note_vue | 5.310266e+04 | 5.277339e+04 |
| note_condition | 2.768421e+04 | 2.655218e+04 |
| note_globale_construction | 8.648667e+04 | 9.691969e+04 |
| m2_surface_au_sol | 8.951300e+02 | 3.882139e+02 |
| m2_sous_sol | 6.660682e+02 | 7.265495e+01 |
| annee_construction | -2.302598e+03 | -2.668402e+03 |
| code_postal | -4.622654e+02 | -5.885451e+02 |
| lat | 5.712847e+05 | 6.030399e+05 |
| long | -1.954690e+05 | -2.084678e+05 |
Arbre de régression
Les arbres de décision permettent de prédire une valeur, ici le prix de vente d’un bien immobilier. Cette méthode est assez facile à interpréter, ainsi qu’à implémenter. Comment ça fonctionnement ? - Premièrement, on prend un échantillon d’apprentissage sur lequel l’arbre sera créé et un échantillon test pour tester son efficacité. - Ensuite, sur la totalité des données d’apprentissage, l’algorithme recherche la variable qui sépare le mieux les 2 populations. - L’opération se répète jusqu’à temps que l’arbre ne puisse pas améliorer la prédiction finale. Ici, pour choisir le bon nombre de feuilles finales, j’ai procédé par validation croisée. C’est-à-dire qu’une estimation des performances de l’arbre est faite par validation croisée à 10 folds (option xval), et ceci pour chaque niveau de simplification pertinent. Voici l’arbre de décision créer par le logiciel :
tree <- rpart(price ~. , data=data[ech.apprentissage, ],
method="anova",
control=rpart.control(xval = 10))
rpart.plot(tree, type=1, extra=1, box.palette="GnYlRd",digits=-3)Interprétation :
L’arbre de décision permet de voir qu’il y a au total 12 feuilles. C’est-à-dire que chacun des biens immobiliers appartiendra forcément à l’un de ces groupes. Chaque nœud représente un critère. Le premier est la note globale de construction. Si la note est inférieure à 8.5, alors le prix sera plus faible (en partant à gauche) et sinon il sera plus élevé (à droite). Ensuite, allons vers la droite, si la surface du salon est inférieure à 389 m² le prix diminue et sinon, le prix augmente. Chaque nœud, et chaque feuille, présente le nombre d’observations qu’il contient, ainsi que le prix moyen de chacun (ex: 3651 biens pour la première feuille en bas à gauche, avec un prix moyen de 316 099 euros)). Plus le prix est élevé, plus la couleur approche du rouge et inversement vers le vert. L’interprétation est assez simple et très cohérente avec la réalité du marché immobilier.
Enfin, je regarde l’erreur moyenne que commet l’arbre en comparant les résultats de l’arbre avec les résulats réels. Le tableau, ci-dessous, montre les 5 premières lignes du tableau récapitulant le prix réel, le prix prédit et l’erreur faite par l’arbre. Ensuite, le second tableau présente l’erreur moyenne faite par l’arbre : 133603 euros . Cela signifie qu’en moyenne le prix de vente du bien immobilier est exact à plus ou moins 133 000 euros. Cela peut paraître beaucoup à première vu, mais il faut se souvenir quand moyenne un bien immobilier se vend à 540 088 euros, et le prix médian est de 450 000 euros. Le prix maximum est même jusqu’à 7 700 000 euros, donc environ 100 000 euros d’écart reste une erreur de prédiction assez faible.
test_Predict<-predict(tree,newdata=data[ech.test, ], type= "matrix")
tab = data.frame(prix_reel = data[ech.test, ]$price,
prix_predit = test_Predict,
erreur = round(data[ech.test, ]$price- test_Predict,0))
kable(head(tab,5),align = "ccc")%>% kable_styling(full_width = F)| prix_reel | prix_predit | erreur | |
|---|---|---|---|
| 1 | 221900 | 313122.0 | -91222 |
| 6 | 1225000 | 1186445.8 | 38554 |
| 8 | 291850 | 313122.0 | -21272 |
| 10 | 323000 | 313122.0 | 9878 |
| 12 | 468000 | 462914.5 | 5086 |
| Erreur_moyenne |
|---|
| 133603 |
Conclusion générale
Ce document proposait une analyse d’un jeu de données portant sur les données de vente de biens immobiliers. Ainsi qu’un travail de régression sur les différentes variables grâce au logiciel R Studio.
Le but était de trouver une relation entre les différentes variables du jeu de données et le prix de vente des biens immobiliers.
Plusieurs méthodes d’analyse ont été mises en œuvre : BACKWARD, EXHAUSTIVE, FORWARD, STEPWISE BOTH, validation simple et croisée, RIDGE ET LASSO et un arbre de régression . Les méthodes ont donné des résultats assez similaires, mais il y avait tout de même quelques différences. J’ai analysé les résultats et le modèle que j’ai retenu contient 15 variables explicatives : L’année de l’achat, le nombre de chambres, le nombre de salles de bain, la surface du salon, la sruface de la pièce à vivre des voisins, la surface du terrain des voisins,la vue sur la mer, la note de la vue, la note des conditions, la note globale de construction, la surface du sous sol, l’année de construction, le code postal, la lattitude, et la longitude.
Pour réaliser ce projet, plusieurs ressources m’ont aidé : Le cours Machine Learning 2010-2020 de M.Gouno https://rpubs.com/ https://rmarkdown.rstudio.com/ http://fermin.perso.math.cnrs.fr/Files/Chap3.pdf https://www.kaggle.com
Ce projet, très complet, m’a permis d’apprendre beaucoup sur les différentes méthodes de régressions, mais surtout de les mettre en pratique sur un jeu de données de mon choix. J’ai pu approfondir les différentes connaissances que j’avais des régressions linéaires simples, mais aussi d’apprendre beaucoup de nouvelles méthodes et fonction sur le logiciel R. Il aurait était intéressant de trouver des données permettant d’étofer le jeu de données comme la situation du marché immobilier ou bien le pouvoir d’achat de la population. De plus, un travail de supervision a permit d’apporter une analyse différente sur les différentes méthodes d’analyses et de régressions. Enfin, ce projet m’a permis de découvrir RMarkdown, logiciel pour faire des rapports de qualité. Toutes ces nouvelles compétences me serviront dans la suite de mon parcours professionnel.