1 Données synthétiques

publicité
Master 2 MIMSE
Apprentissage automatique
2015-2016
TP2 : analyse discriminante et régression logistique
1
Données synthétiques
Récupérer les jeux de données synth_train.txt et synth_test.txt. On a Y ∈ {1, 2} et X ∈ R2 . On
dispose de 100 données d’apprentissage et 200 données test.
1. Charger le jeu de données d’apprentissage dans R (soit avec la commande read.table, soit avec
l’outil d’importation de Rstudio : Tools > Import Dataset). Afficher les données d’apprentissage.
2. Représenter graphiquement les observations à l’aide de la fonction plot. On pourra colorier les
points en fonction de leur classe à l’aide du paramètre col et modifier le symbole avec le paramètre
pch (=point character) et rajouter une légende à l’aide de la fonction legend.
3. On s’intéresse d’abord au classifieur QDA (quadratic discriminant analysis)
(a) Constuire le classifieur QDA à partir des données d’apprentissage et de la fonction qda du
package MASS .
(b) Prédire les classes et les probabilités à posteriori des deux points de coordonnées (0,0) et (-2,2).
newdata <- data.frame(x1=c(0,-2),x2=c(0,2))
(c) Représenter graphiquement la frontière de décision : commencer par construire une grille de
points, prédire ces points, puis ajouter ces points sur le graphique en les coloriant en fonction
de leur prédiction.
(d) Charger le jeu de données test dans R. Prédire les données de l’ensemble test avec ce classifieur
et comparer avec les vraies classes. Calculer le taux d’erreur empirique (nombre de fausses
prédictions sur l’échantillon d’apprentissage divisé par taille de cet échantillon).
4. On s’intéresse maintenant au classifieur LDA (linear discriminant analysis).
(a) Reprendre les questions précédentes (contruction du classifieur, prédiction des deux points,
frontière de décision et taux d’erreur test) avec la fonction lda du package MASS.
(b) Dans le cas particulier de la classification binaire, on peut écrire que la probabilité à posteriori
P(Y = 2|X = x) est une fonction logistique d’un score linéaire :
P(Y = 2|X = x) =
exp(α0 + xT α)
1 + exp(α0 + xT α)
et que ce score linéaire est une fonction logit de la probabilité à posteriori :
log
P(Y = 2|X = x)
= α0 + xT α.
P(Y = 1|X = x)
Le score linéaire α0 + xT α est le logarithme de l’odd ratio
P(Y = 2|X = x)
, aussi appelé logP(Y = 1|X = x)
odds ou encore la probabilité à posteriori sur l’échelle logit.
— Trouver l’expression de α0 et α dans le cours (p. 40 des diapos du chapitre 2).
1
— A quelle valeur se compare α0 + xT α pour classer x ?
— Calculer les log-odds (probabilités à posteriori sur l’échelle logit) des deux points de coordonnées (0,0) et (-2,2).
5. On s’intéresse maintenant à la régression logistique qui fournit un fonction de classification binaire
et estime directement les probabilités à posteriori.
(a) Reprendre les questions précédentes (contruction du classifieur, prédiction des deux points,
frontière de décision et taux d’erreur test) avec la fonction glm et en vous aidant du code
suivant :
#regression logistique sur donnees d'apprentissage
?glm
g <- glm(as.factor(y)~x1+x2,data=train,family=binomial)
#proba a posteriori P(Y=2|X=x) pour x=(0,0),x=(-2,2)
predict(g, newdata, type="response")
##
1
2
## 9.999998e-01 1.061813e-06
#P(Y=2|X=(0,0))=0.99
#P(Y=2|X=(-2,2))=0.00000106
#fontieres de decision
prob_grille <- predict(g,data.frame(grille),type="response")
pred_grille <- 2*I(prob_grille>0.5)+1*I(prob_grille<=0.5)
(b) En régression logistique, on définit le modèle suivant :
P(Y = 2|X = x) =
exp(β0 + xT β)
1 + exp(β0 + xT β)
et les paramètres β0 et β sont estimés par maximum de vraisemblance sur les données d’apprentissage. On a donc comme en LDA un score linéaire qui est une fonction logit de la probabilité
à posteriori :
P(Y = 2|X = x)
log
= β0 + xT β,
P(Y = 1|X = x)
aussi appellé log-odds ou encore la probabilité à posteriori sur l’échelle logit.
— Quelles sont les valeurs des paramètres β0 et β estimés sur les données d’apprentissage ?
— Quel test est utilisé pour tester la nullité de ces coefficients ?
— Calculer le log-odd (probabilités à posteriori sur l’échelle logit) du points de coordonnées
(-2,2) de 3 manières différents.
6. Pour les trois méthodes considérées ici, un seuil a été fixé pour constuire les fonctions de classification g. Ce seuil vaut 0.5 si on regarde les probabilités à posteriori p = P(Y = 2|X = x) et 0 si
p
on regarde les log-odds
. On va faire varier ce seuil en LDA et regarder comment le taux de
1−p
bons classements varie.
(a) Faire varier le seuil de 0 à 1 par pas de 0.1 et représenter sur un graphique le taux de bons
classement en fonction du seuil.
(b) Recommencer mais en faisant varier cette fois le seuil des log-odds par pas de 0.1.
(c) Calculer les taux de vrais positis (T V P ) et de vrais négatifs (T V N ) lorsque le seuil varie sur
l’échelle des log-odds par pas de 0.1. Ici positif = 2. Tracer ensuite la courbes ROC des points
(1 − T V N (s); T V P (s)).
7. On peut retrouver ces graphiques avec le package ROCR et le code suivant :
library(ROCR) # 3 fonctions : prediction, performance, plot
#label.ordering pour le label de la classe negative puis positive
pred <- prediction(prob_test, Ytest,label.ordering=c("1","2"))
perf <- performance(pred, "acc")
plot(perf)
2
0.9
0.8
0.7
0.6
0.3
0.4
0.5
Accuracy
0.0
0.2
0.4
0.6
0.8
1.0
Cutoff
0.6
0.3
0.4
0.5
Accuracy
0.7
0.8
0.9
pred <- prediction(odds_test, Ytest,label.ordering=c("1","2"))
perf <- performance(pred, "acc")
plot(perf)
−10
−5
0
5
Cutoff
pred <- prediction(prob_test, Ytest,label.ordering=c("1","2"))
perf <- performance(pred, "tpr", "fpr")
plot(perf,colorize=TRUE) #courbe ROC avec couleur selon les seuils
3
10
1.01
0.2
0.4
0.6
0.8
1.0
0.8
0.6
0.4
0
0.0
0.2
True positive rate
0.0
0.2
0.4
0.6
0.8
1.0
0.8
1.0
False positive rate
auc <- performance(pred, "auc")@y.values[[1]]
auc
## [1] 0.9893642
3.87
−0.61
0.6
−5.08
0.4
0.0
−9.56
0.2
True positive rate
0.8
8.35
1.0
12.83
pred <- prediction(odds_test, Ytest,label.ordering=c("1","2"))
perf <- performance(pred, "tpr", "fpr")
plot(perf,colorize=TRUE) #courbe ROC avec couleur selon les seuils
0.0
0.2
0.4
0.6
False positive rate
8. On souhaite maintenant associer un coût 3 fois plus important aux faux positifs.
4
Le coût moyen est mesuré par la fonction average_cost.
average_cost <- function(Y_pred, Y_test)
{
FP = (Y_pred == "2") & (Y_test == "1")
FN = (Y_pred == "1") & (Y_test == "2")
return(sum(3*FP+1*FN)/length(Y_test))
}
Proposez un seuil pour le classifieur LDA qui minimise ce coût moyen sur les données d’apprentissage. Calculer alors le T V P et le T V N sur les données tests.
g <- lda(y~x1+x2,data=train)
prob_test <- predict(g,Xtest)$posterior[,2]
odds_test <- log(prob_test/(1-prob_test))
s <- seq(min(odds_test),max(odds_test),by=0.1)
cout_moy <- rep(NA,length(s))
for (i in 1:length(s))
{
pred_test <- 2*I(odds_test>s[i])+1*I(odds_test<=s[i])
cout_moy[i] <- average_cost(pred_test,Ytest)
}
plot(s,cout_moy,type="l", col=2,xlab="seuil",
ylab="Cout moyen", main="Seuil sur les log-odds")
0.2
0.4
Cout moyen
0.6
0.8
Seuil sur les log−odds
−10
−5
0
5
seuil
#seuil optimal
s[which.min(cout_moy)]
## [1] 2.04147
s <- seq(0,1,by=0.01)
cout_moy <- rep(NA,length(s))
for (i in 1:length(s))
{
pred_test <- 2*I(prob_test>s[i])+1*I(prob_test<=s[i])
cout_moy[i] <- average_cost(pred_test,Ytest)
}
5
10
plot(s,cout_moy,type="l", col=2,xlab="seuil",
ylab="Cout moyen", main="Seuil sur les proba")
0.6
0.2
0.4
Cout moyen
0.8
Seuil sur les proba
0.0
0.2
0.4
0.6
seuil
#seuil optimal
s[which.min(cout_moy)]
## [1] 0.88
log(0.885/(1-0.885))
## [1] 2.040656
hist(prob_test)
6
0.8
1.0
60
0
20
40
Frequency
80
100
120
Histogram of prob_test
0.0
0.2
0.4
0.6
0.8
1.0
prob_test
hist(odds_test)
20
15
0
5
10
Frequency
25
30
35
Histogram of odds_test
−10
−5
0
5
10
odds_test
2
Données réelles
Récuperer le jeu de données Desbois_complet.rda. Les données concernent n = 1260 exploitations
agricoles réparties en K = 2 groupes : le groupe des exploitations saines et le groupe des exploitations
7
défaillantes. On veut construire un score de détection du risque financier applicable aux exploitations
agricoles. Pour chaque exploitation agricole on a mesuré une batterie de p = 30 crières économiques et
financiers pour construire le score. La variable qualitative à expliquer est donc la variable difficulté de
paiement (0=sain et 1=défaillant). Une étude de cas de ces données est disponible à l’adresse suivante :
http://publications-sfds.fr/index.php/csbigs/article/view/351/331
1. Charger le jeu de données complet dans R.
2. On veut dans un premier temps comparer les performances de différents classifieur.
(a) Quelles stratégies peuvent être envisagées pour comparer correctement les taux d’erreur des
classifieurs obtenus avec les méthodes knn, lda, qda et régression logistique ?
(b) Retrouver le graphique ci-dessous obtenue avec B = 50 découpages aléatoire des données en
945 observations d’apprentissage/validation et 315 observations test.
0.08
0.10
0.12
0.14
0.16
0.18
0.20
0.22
Erreurs test pour 50 decoupages
knn
lda
qda
glm
3. On veut maintenant définir une fonction de classification (un classifieur) avec moins de variables
explicatives et donc effectuer une sélection de variables. Une première approche consiste à choisir
un critère de choix de modèle et un algorithme de sélection de variables.
(a) Créer un jeu de données de données d’apprentissage de taille 945 (75% des données) et un jeu
de données test de taille 315 (25% des données) avec le code suivant.
set.seed(30)
tr <- sample(1:nrow(data),945)
train <- data[tr,]
test <- data[-tr,]
(b) Quels sont les taux d’erreurs sur les données tests des fonctions de classification obtenues avec
toutes les variables en lda et regression logistique.
error_rate <function(y_pred, y_test) {
return(sum(y_pred!=y_test)/length(y_test))
}
8
(c) La fonction greedy.wilks du package klaR effectue une sélection de variable pas à pas ascendante en lda. Testez cette méthode avec le code ci-dessous. Combien de variables sont
sélectionnées, quel est le taux d’erreur de ce classifieur sur les données test ?
library(klaR)
?greedy.wilks
# lda avec selection de variables pas à pas ascendante
g <- greedy.wilks(DIFF~.,data=train,niveau=0.1)
g$formula
## DIFF ~ R1 + R32 + R14 + R17 + R2 + R3 + R36 + R21 + R4
## <environment: 0x3b5e728>
#prediction des donnees test
pred_wilks <- predict(lda(g$formula,data=train),test)$class
(d) La fonction step effectue une sélection de variable pas à pas ascendante, descendante ou ascendante/descendante en régression logistique. Testez cette méthode avec le code ci-dessous.
Combien de variables sont sélectionnées, quel est le taux d’erreur sur les données test de ce
classifieur ?
?step
library(MASS)
?stepAIC
# logistique avec selection de variables pas a pas ascendante et descendante
modelenul <- glm(DIFF~1,data=train)
modelecomplet <- glm(DIFF~.,data=train)
g <- step(modelenul, scope=list(upper=modelecomplet),
direction="both",trace=FALSE)
g$formula
## DIFF ~ R1 + R32 + R14 + R17 + R2 + R3 + R36 + R21 + R4 + R19 +
##
R37
# logistique + selection pas à pas descendante
# g <- step(modelecomplet,direction="backward",trace=FALSE)
# logistique + selection pas à pas ascendante
# g <- step(modelenul, scope=list(lower=modelenul,upper=modelecomplet),
#
direction="forward",trace=FALSE)
# g$formula
#prediction des donnees test
prob <- predict(g,newdata=test,type="response")
pred_step <- 1*I(prob>0.5)+0*I(prob<=0.5)
4. Pour sélectionner des variables, il est également possible d’utiliser des approches de type regression pénalisée (régularisée). Les deux méthodes classiques de régression pénalisées sont la
régression ridge et la regression LASSO. La régression ridge est utilisée pour gérer la question de
la multicolinéarité, et la régression LASSO est utilisée pour gérer la question de la sélection de
variable.
De manière très simplifiée, on écrit le modèle de régression sous la forme Y = Xβ + ε et on peut
dire qu’en régression ridge l’estimateur de β est défini par :
β̂ = arg minp ||Y − Xβ||2 + λ||β||22
β∈R
et qu’en régression LASSO il est défini par :
β̂ = arg minp ||Y − Xβ||2 + λ||β||1
β∈R
où dans les deux cas λ est un paramètre positif à choisir.
La régression ridge correspond à la minimisation d’un critère des moindres carrés avec une pénalité
de type `2 et la régression LASSO à la minimisation d’un critère des moindres carrés avec une
9
pénalité de type `1 .
Pour la méthode LASSO, on voit bien que :
- si λ = 0 on retrouve l’estimateur des moindres carrés de la régression linéaire multiple.
- si λ tend vers l’infini, on annulle tous les β̂j pour j = 1, . . . , p.
En pratique, le paramètre λ est souvent fixé par validation croisée.
Des méthodes de type LASSO peuvent également être utilisées en classification :
- la fonction PenalizedLDA effectue une lda régularisée avec pénalité de type `1 .
- la fonction glmnet effectue une régression logistique régularisée avec pénalité de type `1 ..
Pour effectuer une régression logistique régulariséee de type LASSO, appliquez le R code ci-dessous
et en dédruie :
- la stratégie du choix du paramètre λ implémentée par défaut,
— la liste des variables sélectionnées,
— le taux d’erreur test.
library(glmnet)
?glmnet
#choix de lambda par validation croisée 10 fold
?cv.glmnet
g <- cv.glmnet(as.matrix(train[,-1]),train$DIFF,family="binomial",
type.measure="class") #quel autre type de mesure est possible ?
plot(g)
8
7
6
5
4
4
4
4
0.3
0.1
0.2
Misclassification Error
0.4
0.5
20 19 18 15 15 12 11 11 12
−8
−6
−4
log(Lambda)
g$lambda.min
# a bien comprendre
## [1] 0.003399611
g$lambda.1se # a bien comprendre
## [1] 0.0554052
coef(g)
## 23 x 1 sparse Matrix of class "dgCMatrix"
##
1
10
−2
3
0
##
##
##
##
##
##
##
##
##
##
##
##
##
##
##
##
##
##
##
##
##
##
##
(Intercept) -1.825295
R1
2.431740
R2
.
R3
.
R4
.
R5
.
R6
.
R7
.
R8
.
R11
.
R12
.
R14
1.204252
R17
.
R18
6.138417
R19
.
R21
.
R22
.
R24
.
R28
.
R30
.
R32
-3.237207
R36
.
R37
.
#prediction avec les variables selectionnées
prob <- predict(g,as.matrix(test[,-1]),type="response")
pred_glmnet <- 1*I(prob>0.5)+0*I(prob<=0.5)
5. Proposez une stratégie pour évaluer le taux d’erreur du classifieur obtenu avec la fonction glmnet.
6. Constuire le classifieur qui sera finalement utilisé pour prédire si de nouvelles exploitations sont
saines ou défaillantes.
11
Téléchargement