Devoir #3

4 nov. 2017 - set.seed(1204876) folds = createFolds(c(1:300), k = 5) e3 = data.frame() knn.kfolds = data.frame(). # Boucle de k for(j in seq(1, 20, 2)){ error.fold ...
183KB taille 27 téléchargements 553 vues
Devoir #3 Philippe St-Aubin 4 novembre 2017

Question no.1 a) Prenons la décomposition de Cholesky de la matrice des covariances puisque celle-ci est symétrique et définie positive, ainsi: C = DDT Alors C −1 = D−1 (D−1 )T Posons A = DT Ainsi C = AT A Multiplions le système par A Ay = AXβ + Aϵ On obtient donc une régression linéaire dans l’espace de la base de A: y ′ = X ′ β + ϵ′ On reprend donc la solution pour β :

β = (X ′T X ′ )−1 X ′T y ′ β = ((AX)T AX)−1 (AX)T Ay β = (X T AT AX)−1 X T AT Ay

On obtient donc finalement:

β = (X T CX)−1 X T Cy

b) La loi asymptotique de βˆ est donc :

βˆ ∼ N (β, σ 2 (X T CX)−1 )

Question no.2 \subsection{a) KNN \subsubsection{1. LOOCV library(class) # On normalise les données pour appliquer KNN default.norm = data.frame(apply(default[,c(1,2)], 2, function(x) x/max(x))) default.norm$default = default$default D’après le graphique on peut garder trois nombres de voisins qui donnent la même erreur. Gardons le plus petit (k = 11) Estimons l’erreur sur la classification en utilisant la méthode de validation croisée LOOCV 1

e3 = data.frame() knn.loocv = data.frame() # Boucle k for(j in seq(from = 1, to = 20, by = 2)){ e2 = data.frame() # Boucle LOOCV for(i in c(1:nrow(default.norm))){ # On entraîne le modèle sur toutes les observations sauf une default.knn = knn(default.norm[-i,c(1:2)], default.norm[i,c(1:2)], cl = default.norm[-i, 3], k = j) # On calcul l'erreur de classifiation pour un k donné e = data.frame(pred = default.knn, reel = default.norm[i,3]) e2 = rbind(e2, e) } # On calcul le taux d'erreur pour un k donné e3 = data.frame(k = j, error = mean(e2$pred != e2$reel)) knn.loocv = rbind(knn.loocv, e3) }

0.19 0.17 0.15

taux d'error

0.21

# Graphique du nombre optimal de voisins (k) plot(knn.loocv$k, knn.loocv$error, type = "l", xlab = "k", ylab = "taux d'error")

5

10

15

k D’après le graphique 3 ou 17 voisins seraient le nombre de voisins qui minimise l’erreur estimée par LOOCV avec un taux de 15% d’erreur. \subsubsection*{2. 5-Fold CV On doit construire au hasard 5 échantillons tests library(caret)

2

## Loading required package: lattice ## Loading required package: ggplot2 set.seed(1204876) folds = createFolds(c(1:300), k = 5) e3 = data.frame() knn.kfolds = data.frame() # Boucle de k for(j in seq(1, 20, 2)){ error.fold = data.frame() # Boucle de CV for(i in c(1:5)){ # On entraîne le modèle sur tous les folds sauf un default.knn = knn(default.norm[-folds[[i]],c(1:2)], default.norm[folds[[i]],c(1:2)], cl = default.norm[-folds[[i]], 3], k = j) # On calcul l'erreur de classification e = data.frame(fold = i, error = mean(default.knn != default.norm[folds[[i]],3])) error.fold = rbind(error.fold, e) } # On calcul le taux d'erreur moyen pour les 5 folds e3 = data.frame(k = j, error = mean(error.fold$error)) knn.kfolds = rbind(knn.kfolds, e3) }

0.17 0.15 0.13

taux d'error

plot(knn.kfolds$k, knn.kfolds$error, type = "l", xlab = "k", ylab = "taux d'error")

5

10

15

k En utilisant la méthode des k-folds avec k=5, on trouve que le nombre optimal de voisins est de 19 avec une estimation du taux d’erreur à 13%. \subsubsection*{3. Choix du k La méthode LOOCV permet d’obtenir le biais le plus faible sur l’erreur puisqu’on entraîne le modèle avec n-1 observations. Par contre la variance sur le résultat est plus élevée. Comme on cherche à trouver le k optimal minimisant l’erreur, il serait judicieux de se baser sur le résultat 3

du LOOCV. Donc on conserve k = 17.

b) Régression Logistique 1. LOOCV default$default = as.character(levels(default$default))[default$default] default$default[default$default == "Yes"] = 1 default$default[default$default == "No"] = 0 default$default = as.numeric(default$default) library(boot) ## ## Attaching package: 'boot' ## The following object is masked from 'package:lattice': ## ## melanoma # Modèle 1 d.glm1 = glm(default ~ income + balance, data = default) # LOOCV glm1.loocv = cv.glm(default, d.glm1) glm1.loocv$delta[1] ## [1] 0.1044673 # Modèle 2 d.glm2 = glm(default ~ income + balance + income:balance, data=default) # LOOCV glm2.loocv = cv.glm(default, d.glm2) glm2.loocv$delta[1] ## [1] 0.1043897 ## methode modèle erreur ## 1 LOOCV 1 0.1044673 ## 2 LOOCV 2 0.1043897 On remarque que l’estimation de l’erreur sur les deux modèles est très proche l’une de l’autre. Par contre, le modèle 2 donne une erreur plus basse. 2. K-Folds CV # K-folds glm1.kfolds = cv.glm(default, d.glm1, K = 5) glm1.kfolds$delta[1] ## [1] 0.1041416 # K-folds glm2.kfolds = cv.glm(default, d.glm2, K = 5) glm2.kfolds$delta[1] ## [1] 0.106043 4

## methode modèle erreur ## 1 K-folds 1 0.1041416 ## 2 K-folds 2 0.1060430 Le modèle 1 obtient cette fois un résultat légèrement meilleur. 3. Choix du modèle summary(d.glm1) ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ##

Call: glm(formula = default ~ income + balance, data = default) Deviance Residuals: Min 1Q -0.87551 -0.20109

Median 0.03664

3Q 0.22483

Max 0.85042

Coefficients: Estimate Std. Error t value Pr(>|t|) (Intercept) -3.069e-01 6.083e-02 -5.045 7.92e-07 *** income 1.466e-06 1.413e-06 1.037 0.3 balance 5.960e-04 2.892e-05 20.610 < 2e-16 *** --Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1 (Dispersion parameter for gaussian family taken to be 0.1038968) Null deviance: 75.000 Residual deviance: 30.857 AIC: 177.04

on 299 on 297

degrees of freedom degrees of freedom

Number of Fisher Scoring iterations: 2

On remarque que la variable income n’est pas significative dans le modèle, car sa p-value est très grande. summary(d.glm2) ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ##

Call: glm(formula = default ~ income + balance + income:balance, data = default) Deviance Residuals: Min 1Q -0.86069 -0.21023

Median 0.04809

3Q 0.21411

Max 0.82670

Coefficients: Estimate Std. Error t value Pr(>|t|) (Intercept) -4.025e-01 1.149e-01 -3.505 0.000528 *** income 4.533e-06 3.429e-06 1.322 0.187201 balance 6.655e-04 7.650e-05 8.700 2.35e-16 *** income:balance -2.243e-09 2.285e-09 -0.982 0.327041 --Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1

5

## ## ## ## ## ## ##

(Dispersion parameter for gaussian family taken to be 0.1039095) Null deviance: 75.000 Residual deviance: 30.757 AIC: 178.07

on 299 on 296

degrees of freedom degrees of freedom

Number of Fisher Scoring iterations: 2

On remarque que le terme d’interaction n’est pas non plus significatif. Son ajout ne contribue donc pas au modèle. Au final choisir un modèle ou l’autre ne devrait pas modifier grandement le résultat. Toutefois comme le modèle 2 semble donner une erreur légèrement inférieure avec la méthode LOOCV, on va poursuivre avec celui-ci.

c) LDA, QDA 1. LOOCV default$default[default$default == 1] = "Yes" default$default[default$default == 0] = "No" default$default = as.factor(default$default) library(MASS) #LDA e2 = data.frame() for(i in c(1:nrow(default))){ d.lda = lda(default[-i,c(1,2)], default$default[-i]) # On calcul l'erreur de classifiation pred.lda = predict(d.lda, default[i,c(1,2)]) e = data.frame(pred = pred.lda$class, reel = default.norm$default[i]) e2 = rbind(e2, e) } lda.loocv = mean(e2$pred != e2$reel) #QDA e2 = data.frame() for(i in c(1:nrow(default))){ d.qda = qda(default[-i,c(1,2)], default$default[-i]) # On calcul l'erreur de classifiation pred.qda = predict(d.qda, default[i,c(1,2)]) e = data.frame(pred = pred.qda$class, reel = default.norm$default[i]) e2 = rbind(e2, e) } qda.loocv = mean(e2$pred != e2$reel) data.frame(méthode = c("LOOCV","LOOCV"), modèle = c("LDA", "QDA"), erreur = c(lda.loocv, qda.loocv)) ## méthode modèle erreur ## 1 LOOCV LDA 0.1300000 ## 2 LOOCV QDA 0.1333333 On remarque que les deux taux d’erreurs sont très similaires avec 0,13 pour lda et 0,133333 pour qda.

6

2. K-Folds CV set.seed(1204876) folds = createFolds(c(1:300), k = 5) # LDA lda.kfolds = data.frame() # Boucle de CV for(i in c(1:5)){ # On entraîne le modèle sur tous les folds sauf un d.lda = lda(default[-folds[[i]],c(1:2)], default$default[-folds[[i]]]) pred.lda = predict(d.lda, default[folds[[i]], c(1,2)]) # On calcul l'erreur de classifiation e = data.frame(fold = i, erreur_moy = mean(pred.lda$class != default$default[folds[[i]]])) lda.kfolds = rbind(lda.kfolds, e) } # QDA qda.kfolds = data.frame() # Boucle de CV for(i in c(1:5)){ # On entraîne le modèle sur tous les folds sauf un d.qda = qda(default[-folds[[i]],c(1:2)], default$default[-folds[[i]]]) pred.qda = predict(d.qda, default[folds[[i]], c(1,2)]) # On calcul l'erreur de classifiation e = data.frame(fold = i, erreur_moy = mean(pred.qda$class != default$default[folds[[i]]])) qda.kfolds = rbind(qda.kfolds, e) }

# On calcul le taux d'erreur moyen pour les 5 folds data.frame(méthode = c("K-folds", "K-folds"), modèle = c("LDA", "QDA"), erreur = c(mean(lda.kfolds$err ## méthode modèle erreur ## 1 K-folds LDA 0.1266667 ## 2 K-folds QDA 0.1266667 En utilisant la méthode de validation croisée, on trouve encore une fois que les erreurs sont très similaires entre les deux méthodes. 3. Choix de la méthode ## ## ## ## ##

méthode modèle erreur 1 LOOCV LDA 0.1300000 3 K-folds LDA 0.1266667 2 LOOCV QDA 0.1333333 4 K-folds QDA 0.1266667

On remarque que les deux méthodes donnent à peu près les mêmes résultats pour les deux méthodes de validation croisée. Toutefois, on remarque que les résultats de LDA donnent une erreure très légèrement

7

inférieur que QDA avec la méthode LOOCV. Comme c’est la méthode de validation croisée avec le biais le plus faible, on prendre ce résultat pour appuyer notre choix de modèle. On choisit donc le modèle LDA

D. Choix du modèle 1. Comparaison graphique ## Grille normalisée r.norm = sapply(default.norm[,c(1:2)], range) # On construit les points en x xs.n = seq(r.norm[1,1], r.norm[2,1], length.out = 100) # On construit les points en y ys.n = seq(r.norm[1,2], r.norm[2,2], length.out = 100) ## # On construit la structure pour la prédiction des points de la grille g.n = expand.grid(income = xs.n, balance = ys.n) ## Grille r = sapply(default[,c(1:2)], range) # On construit les points en x xs = seq(r[1,1], r[2,1], length.out = 100) # On construit les points en y ys = seq(r[1,2], r[2,2], length.out = 100) ## # On construit la structure pour la prédiction des points de la grille g = expand.grid(income = xs, balance = ys) # KNN comp.knn = knn(default.norm[,c(1,2)], g.n, cl = default.norm$default, k = 17) # Regression Logistique comp.glm = predict(d.glm2, g) comp.glm = ifelse(comp.glm > 0.5, 1, 0) # LDA comp.lda = predict(d.lda, g) # On affiche la frontière du KNN z.knn = matrix(as.numeric(comp.knn), nrow = 100, byrow = TRUE) # On affiche la frontière de la Régression logistique z.glm = matrix(as.numeric(comp.glm), nrow = 100, byrow = TRUE) # On affiche la frontière de LDA z.lda = matrix(as.numeric(comp.lda$class), nrow = 100, byrow = TRUE) # On affiche les données plot(default$income, default$balance, col = default$default, pch = as.integer(default$default), xlab = "income", ylab = "balance", main = "Frontière du défaut de paiement") legend("topright", c("KNN", "GLM", "LDA"), lwd = 2, col = c("orange", "blue", "red")) # Contour KNN

8

contour(xs, ys, t(z.knn), add = TRUE, drawlabels = FALSE, lwd = 2, levels = (1:2), col = "orange") # Contour GLM contour(xs, ys, t(z.glm), add = TRUE, drawlabels = FALSE, lwd = 2, levels = (1:2), col = "blue") # Contour LDA contour(xs, ys, t(z.lda), add = TRUE, drawlabels = FALSE, lwd = 2, levels = (1:2), col = "red")

Frontière du défaut de paiement

500 1000 0

balance

2000

KNN GLM LDA

10000

20000

30000

40000

50000

60000

income L’équation de la frontière de décision de la courbe LDA est donnée par l’expression suivante : δy − δn = 0 où 1 δy = xt Σ−1 µy − µty Σ−1 µy + ln(πy ) 2 et 1 δn = xt Σ−1 µn − µtn Σ−1 µn + ln(πn ) 2 avec Σ−1 = d.lda$scaling^-1 ## LD1 ## income 1212599.4023 ## balance 407.5182 et µtn (première ligne de la matrice) et µty (deuxième ligne de la matrice) : d.lda$means ## ## No

income 31351.59

balance 781.8979 9

## Yes 31030.88 1760.5056 Finalement les probabilité à priori (πn , πy ) sont données par : d.lda$prior ## No Yes ## 0.5125 0.4875 La courbe tracée est donc celle où les x annulent la différence δy − δn . 2. K-folds CV set.seed(1204876) folds = createFolds(c(1:300), k = 10) # KNN for(i in c(1:10)){ # On entraîne le modèle sur tous les folds sauf un default.knn = knn(default.norm[-folds[[i]],c(1:2)], default.norm[folds[[i]],c(1:2)], cl = default.norm[-folds[[i]], 3], k = 17) # On calcul l'erreur de classification e = data.frame(fold = i, error = mean(default.knn != default.norm[folds[[i]],3])) error.fold = rbind(error.fold, e) } # On calcul le taux d'erreur moyen pour les 10 folds knn.test = data.frame(modèle = "KNN", erreur = mean(error.fold$error))

# Régression Logistique default.num = default default.num$default = ifelse(default$default == "Yes", 1, 0) glm2.kfolds = cv.glm(default.num, d.glm2, K = 10) glm.test = data.frame(modèle = "RegLog", erreur = glm2.kfolds$delta[1]) # LDA error.fold = data.frame() for(i in c(1:10)){ # On entraîne le modèle sur tous les folds sauf un d.lda = lda(default[-folds[[i]],c(1:2)], default$default[-folds[[i]]]) pred.lda = predict(d.lda, default[folds[[i]], c(1,2)]) # On calcul l'erreur de classifiation e = data.frame(fold = i, error = mean(pred.lda$class != default$default[folds[[i]]])) error.fold = rbind(error.fold, e) } lda.test = data.frame(modèle = "LDA", erreur = mean(error.fold$error)) # Tableau de comparaison rbind(knn.test, glm.test, lda.test) ## modèle erreur ## 1 KNN 0.1457975 ## 2 RegLog 0.1047641 10

## 3

LDA 0.1340913

Avec la validation croisée sur les trois modèles, on constate que l’erreur moyenne est plus faible pour la régression logistique. On choisit donc de conserver le modèle de régression logistique 2.

Question no.3 A. Expression d’un estimateur On doit donner une estimation du paramètre θ donné par l’expression suivante: θ = E(min(|X1 X3 |, X1 2 ln X2 + X3 , X2 X3 )) On dispose de n observations pour estimer θ. On peut donc l’estimer par l’expression suivante : 1∑ θˆ = min(|Xi1 − Xi3 |, Xi1 − 2 ln Xi2 + Xi3 , Xi2 − Xi3 ) n i=1 n

B. Bootstrap 1. Estimation ponctuelle, biais et écart-type :

library(boot) # Statistique set.seed(192348) thet = function(x, ind){ y = data.frame(X1 = abs(x$Girth[ind] - x$Volume[ind]), X2 = x$Girth[ind] - 2*log(x$Height[ind]) + x$Vo mean(apply(y,1,min)) } # Bootstrap b_t = boot(trees, thet, R = 1500) b_t ## ## ## ## ## ## ## ## ## ## ##

ORDINARY NONPARAMETRIC BOOTSTRAP

Call: boot(data = trees, statistic = thet, R = 1500)

Bootstrap Statistics : original bias t1* 13.74516 -0.004582796

std. error 1.420574

2. Intervalle de confiance:

11

plot(b_t)

16 12

t*

14

0.20 0.00

10

0.10

Density

0.30

18

Histogram of t

8

10 12 14 16 18

−3

t*

−1 0

2

3

Quantiles of Standard Normal

constate une distribution normale des résultats de l’estimateur. confiance en considérant une distribution normale des résultats.

On On peut donc estimer l’intervalle de

boot.ci(b_t, conf = 0.95, type = c("norm")) ## ## ## ## ## ## ## ## ## ##

1

BOOTSTRAP CONFIDENCE INTERVAL CALCULATIONS Based on 1500 bootstrap replicates CALL : boot.ci(boot.out = b_t, conf = 0.95, type = c("norm")) Intervals : Level Normal 95% (10.97, 16.53 ) Calculations and Intervals on Original Scale

ˆ On obtient donc un intervalle de confiance de (10.93, 16.63) pour l’estimateur θ.

12