TP1 Les K Plus Proches Voisins

Télécharger au format pdf ou txt
Télécharger au format pdf ou txt
Vous êtes sur la page 1sur 10

Master 2 MSS 2017-2018

Apprentissage supervisé

TP1 : les k plus proches voisins

Exercice 1. Les objectifs :


— savoir programmer les kppv.
— découvrir les notions de taux d’erreur d’apprentissage, taux d’erreur test (de surapprentissage).
— comprendre l’importance de la calibration d’un paramètre.
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 la commande read.table. 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. Appliquer la fonction knn du package class avec k = 30 voisins pour prédire les classes des
points de coordonnées (0,0) et (-2,1). Vérifiez sur le graphique que les prédictions sont cohérentes.
Recommencer avec l’argument prob=TRUE. A quoi correspondent ces probabilités ? Programmez
votre propre fonction knn.
4. Appliquer la fonction knn pour prédire les données de l’ensemble d’apprentissage avec k = 30
voisins. Calculer le taux d’erreur d’apprentissage.
5. Charger le jeu de données test dans R. Appliquer la fonction knn voisins pour prédire les données
de l’ensemble test avec k = 30 voisins. Calculer le taux d’erreur test et comparer au taux d’erreur
d’apprentissage. Conclure.
6. On veut maintenant visualiser l’importance du choix du paramètre k dans la qualité de la prédic-
tion. Pour cela, représenter graphiquement la frontière de décision pour k = 30 voisins : commencer
par construire une grille de points (cf. code R ci-dessous), prédire les classes de ces points, puis re-
presenter ces points sur un graphique en les coloriant en fonction de leur prédiction. Recommencer
avec k = 15 voisins puis avec k = 1 voisin. Conclure.
#constuction de la grille de points
a <- seq(from=min(train$x1), to=max(train$x1), length.out=100)
b <- seq(from=min(train$x2), to=max(train$x2), length.out=100)
grille <- NULL
for (i in a){
grille <- rbind(grille, cbind(i,b))
}

Exercice 2. Les objectifs :


— savoir simuler des données à partir d’un mélange de lois Gaussiennes.
— découvrir les notions de taux de VP (vrais positifs), FP (faux positifs), VN (vrais négatifs), FN
(faux négatifs) en classification binaire et les notions de sensibilité et de spécificité.
— savoir introduire une matrice de coûts dans la règle de classification et calculer un risque empirique.

1
1. Executez le code R ci-dessous permettant de simuler des données à partir d’un mélange de distri-
butions Normales. Dans cet exemple, on échantillonne à partir du mélange de densités suivant :
0.3 × N(0, 1) + 0.5 × N(10, 1) + 0.2N(3, 1).
#The number of samples from the mixture distribution
n = 10000
set.seed(30)

#Sample n random uniforms U


U =runif(n)

#Variable to store the samples from the mixture distribution


rand.samples = rep(NA,n)
#Sampling from the mixture
for(i in 1:n){
if(U[i]<.3){
rand.samples[i] = rnorm(1,0,1)
}else if(U[i]<.8){
rand.samples[i] = rnorm(1,10,1)
}else{
rand.samples[i] = rnorm(1,3,1)
}
}

#Density plot of the random samples


plot(density(rand.samples),main="Density Estimate of the Mixture Model")

Density Estimate of the Mixture Model


0.15
0.10
Density

0.05
0.00

−5 0 5 10 15

N = 10000 Bandwidth = 0.66

2. En vous inspirant de ce code, échantilloner n = 1000 points selon le mélange 0.2 × N(µ1 , Σ) + 0.8 ×
N(µ2 , Σ) où µ1 = (0, 0), µ2 = (2, 0) et Σ la matrice identité 2 × 2. Utilisez le package mvtnorm
pour échantilloner selon des loi Normales bibariées. Vous devez obtenir un graphique proche du
graphique ci-dessous.

2
3
classe1
classe2

2
1
X[,2]

0
−1
−2
−3

−2 0 2 4

X[,1]

3. On considère que le coût de mauvaise classification dans la classe 1 et le coût de mauvaise classifi-
cation dans la classe 2 sont égaux.
(a) Comment les kppv appliquent de manière empirique la règle de Bayes ? Quelle est la mesure de
performance minimisée ?
(b) Calculer la proportion de chaque classe dans les données. D’après vous, quel serait le taux
d’erreur d’une règle de classification qui consisterait à toujours prédire la classe la plus “probable
à priori” ?
(c) On souhaite constuire le classifieur des k = 10 plus proches voisins (kppv). Evaluer le taux
d’erreur test de ce classifieur en découpant aléatoirement les données en 80% de données d’ap-
prentissage et 20% de données test.
set.seed(30)
tr <- sample(1:n,800)
Xtrain <- X[tr,]
Ytrain <- Y[tr]
Xtest <- X[-tr,]
Ytest <- Y[-tr]
Comparer au taux d’erreur de la règle qui consiste à toujours prédire la classe la plus probable
à priori.
(d) Calculer le taux d’erreur test de ce classifieur pour B = 100 découpages aléatoire des données.
Représentez ces erreur dans un boxplot. Conclure.
(e) On veut maintenant savoir si on prédit aussi bien les données de la classe 1 que les données de
la classe 2. Pour cela reprendre le découpage de la question (c) et calculer sur les données test le
taux de vrai positifs (TVP), le taux de vrai négatif (TVN) et la F-mesure. Ici "positif"=prédire
la classe 1. Que constatez-vous ?
(f) Pour confirmer ces conclusions, refaire les questions précédentes en simulant des données avec
des probabilités à priori π1 = 0.05 et π2 = 0.95 dans la densité de mélange des données.
4. On considère que le coût de mauvaise classification dans la classe 2 est 5 fois plus important le
coût de mauvaise classification dans la classe 1.
(a) Quelle matrice de coût utiliser ?
(b) Comment modifier les kppv pour appliquer de manière empirique la règle de Bayes avec cette
matrice de coût ? Quelle est la mesure de performance minimisée ?

3
(c) Programmer une fonction knn_cout qui inclut la matrice de coût dans les prédictions des kppv.
(d) Appliquer cette fonction sur les données très désiquilibré de la question 2. et calculer sur les
données test : le taux d’erreur, le risque empirique, le TVP, le TVN, la F-mesure. Conclure.
(e) Estimer le risque empirique par validation croisée 5-fold.
n_folds <- 5
folds_i <- sample(rep(1:n_folds, length.out = n))

Recommencer B = 20 fois et faire un boxplot des résultats.


boxplot(remp,xlab="Risque empirique", main="B=20, 5-fold validation")

B=20, 5−fold validation


0.21
0.20
0.19
0.18
0.17
0.16
0.15

Risque empirique

Exercice 3. Les objectifs :


— Découvrir les procédures de choix du paramètre k.
— Découvrir la notion d’échantillon de validation et d’erreur de validation.
1. Echantilloner n = 1000 données selon la densité de mélange de l’exercice 2 avec des probabilités à
priori π1 = 0.5 et π2 = 0.5.
2. Découpez les données en 80% de données d’apprentissage et 20% de données test.
3. On va d’abord choisir k en redécoupant les données d’apprentissage pour constuire en échantillon
de validation.
(a) Découpez les données d’apprentissage en 80% de données d’apprentissage et 20% de données
de validation.
(b) Calculer le taux d’erreur sur les données de validation pour k variant de 1 à 30. Représenter
la courbe des erreurs de validation en fonction de k. Quelle valeur de k minimise cette erreur ?
Recommencez avec plusieurs découpages. Que constatez-vous ?
plot(err,type="l",xlab="Nombre de voisins", ylim=c(0,max(err)))

4
0.20
0.15
err

0.10
0.05
0.00

0 5 10 15 20 25 30

Nombre de voisins

which.min(err)
## [1] 6
(c) Recommencez le processus pour B = 20 découpages et conservez à chaque fois les erreurs de
validation pour k variant de 1 à kmax = 30. Représentez ces erreurs et l’erreur moyenne de
validation sur un graphique qui devrait ressembler au graphique ci-dessous. Quelle valeur de k
minimise l’erreur moyenne de validation ?
#err : matrice 30 lignes et 20 colonnes
#err[i,j] est l'erreur de validation pour k=i dans le jème découpage.
mean_err_valid <- apply(err,1,mean)
lim <-c(0,max(err))
matplot(err,type="l",lty=2,col=2,ylim=lim,
xlab="nombre de voisins",ylab="taux d'erreur de validation",
main="Apprentissage/Validation, B=20 fois")
matpoints(mean_err_valid,type="l",col=2,lwd=4)
legend("bottomright", legend=c("Erreur moyenne", "Erreurs conditionnelles"),
lty=c(1,3),lwd=c(4,2),col=c(2,2))

Apprentissage/Validation, B=20 fois


0.30
0.25
taux d'erreur de validation

0.20
0.15
0.10
0.05

Erreur moyenne
0.00

Erreurs conditionnelles

0 5 10 15 20 25 30

nombre de voisins

5
kopt <- which.min(mean_err_valid)
kopt
## [1] 18

(d) Prédire les données de l’ensemble test avec la valeur de k ainsi sélectionnée.
4. Choisir maintenant k en utilisant la fonction knn.cv sur les données de d’apprentissage. Prédire
les données de l’ensemble test avec la valeur de k ainsi sélectionnée. Critiquez cette approche.

plot(err,type="l",xlab="nombre de voisins",ylab="taux d'erreur de validation", main="Validat

Validation LOO
0.20
taux d'erreur de validation

0.15
0.10
0.05
0.00

0 5 10 15 20 25 30

nombre de voisins

kopt <- which.min(err)


kopt
## [1] 21

5. Proposez une troisième approche pour choisir k.


6. Que faudrait-il faire en plus pour "mieux" estimer l’erreur test ?

Exercice 4. Les objectifs :


— Constuire un classifieur de kppv sur des données réelles.
— Estimer la performance de ce classifieur.
Récuperer le jeu de données Desbois.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 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 critères économiques et financiers et finalement p = 4
ratios financiers on étés retenus pour construire le score :

— R2 : capitaux propres / capitaux permanents,


— R7 : dette à long et moyen terme / produit brut,
— R17 : frais financiers / dette totale,
— R32 : (excédent brut d’exploitation - frais financiers) / produit brut.

La variable qualitative à expliquer est donc la variable difficulté de paiement (0=sain et 1=défaillant).
Voici les 5 premières lignes du tableau de données.

6
DIFF R2 R14 R17 R32
1 saine 0.622 0.2320 0.0884 0.4313
2 saine 0.617 0.1497 0.0671 0.3989
3 saine 0.819 0.4847 0.0445 0.3187
4 saine 0.733 0.3735 0.0621 0.4313
5 saine 0.650 0.2563 0.0489 0.4313

1. Charger le jeu de données dans R avec la commande load.

load("Desbois.rda")
dim(data)
## [1] 1260 5
table(data$DIFF)/nrow(data)
##
## 0 1
## 0.518254 0.481746

2. Afin d’avoir une première idée de l’influence du choix de k sur le taux d’erreur du classifieur des
kppv pour ces données, reprendre la méthodologie de l’exercice précédent :
— en séparant B = 20 fois les données en 900 données d’apprentissage et 360 données de validation
et en faisant varier k de 1 à 60,
— en utilisant la validation croisée LOO.
0.20
0.15
taux d'erreur de validation

0.10
0.05

Erreur moyenne
Erreurs conditionnelles
0.00

Erreur LOO

0 10 20 30 40 50 60

nombre de voisins

3. Pour des raisons de temps de calcul, on choisit ici la procédure qui consiste à choisir k qui minimise
l’erreur LOO. On veut maintenant estimer la performance du classifieur des kppv avec ce choix
automatique de k. Estimer surB = 20 découpages apprentissage/test (dans les proportions 75% -
25%), la performance de ce classifieur en terme de taux de bon classement, taux de vrais positifs,
taux de vrais négatifs. On prendra comme convention que "prédire 0=positif", "prédire1=négatif".

7
boxplot(cbind(tbc_test,tvp_test,tvn_test),main="B=20 decoupages et choix de k par LOO")

B=20 decoupages et choix de k par LOO

0.90
0.85
0.80

tbc_test tvp_test tvn_test

4. Si finalement, la performance du classifieur des kppv avec choix automatique de k par LOO nous
convient, comment prédire la classe de nouvelles exploitations agricoles ? Prédire ainsi la classe
d’une exploitation agricole ayant les valeurs suivantes :
R2 R14 R17 R32
0.700 0.300 0.100 0.500

Exercice 5. Les objectifs :


— Savoir constuire une score.
— Utiliser le package ROCR pour construire une courbe ROC et calculer le critère AUC.
— Constuire une courbe ROC à la main.
— Calculer le critère AUC sur plusieurs échantillons test.
— Choisir un seuil pour optimiser un critère de performance.
1. Découpez les données Desbois en données d’apprentissage et données test.
load("Desbois.rda")
set.seed(30)
tr <- sample(1:nrow(data),945)
train <- data[tr,]
test <- data[-tr,]

2. On veut maintenant constuire un score qui sera d’autant plus élevé que la probabilité qu’une
exploitation soit saine est grande. Quelle est alors la modalité qui correspondra à la classe d’intéret ?
3. Ecrire une fonction prob_knn qui calcule les probabilités à posteriori d’être une exploitation agricole
saine. Caculer alors le score des exploitations agricoles de l’échantillon test.
4. En utilisant le package ROCR, constuire sur les donnée test la courbe ROC du classifieur des kppv
avec k = 10 voisins. Comment est constuite cette courbe ? Quelle est la valeur du AUC sur les
données test ?
library(ROCR) # 3 fonctions : prediction, performance, plot
pred <- prediction(score, test$DIFF,label.ordering=c("1","0"))
#label.ordering : indiquer le libellé de la classe negative puis positive.

8
pred
pred@cutoffs # object of class S4
perf <- performance(pred, "tpr", "fpr")
perf
plot(perf,colorize=TRUE) #courbe ROC avec couleur selon les seuils
auc <- performance(pred, "auc")@y.values[[1]]
auc
5. Constuire cette courbe ROC sans utiliser le package ROCR.
#seuil s variant entre 0 et 1 par pas de 0.1
s <- seq(0,1,by=0.1)

plot(1-tvn_test,tvp_test,type="l", col=2,xlab="1-TVN",
ylab="TVP", main="Courbe ROC maison")

Courbe ROC maison


1.0
0.8
0.6
TVP

0.4
0.2
0.0

0.0 0.1 0.2 0.3 0.4

1−TVN

6. Calculer le critère AUC sur B = 50 échantillons test pour obtenir le graphique ci-dessous.
boxplot(auc, main="B=50 découpages")

B=50 découpages
0.96
0.95
0.94
0.93
0.92
0.91

9
7. On voudrait maintenant choisir le seuil s pour maximiser le taux de bon classement. En utilisant
le package ROCR constuire la courbe du taux de bon classement des données test (en ordonnée) en
fonction du seuil (en abscisse). Quel seuil maximise le TBC ?

set.seed(30)
tr <- sample(1:nrow(data),945)
train <- data[tr,]
test <- data[-tr,]
score <- prob_knn(train[,-1],test[,-1],train$DIFF,k=10)
pred <- prediction(score, test$DIFF,label.ordering=c("1","0"))
perf <- performance(pred, "acc")
plot(perf)
0.8
Accuracy

0.7
0.6
0.5

0.0 0.2 0.4 0.6 0.8 1.0

Cutoff

8. Recommencez sans utiliser cette fois le package ROCR. Pourquoi choisir des seuils variant par pas
de 0.1 est-il suffisant ici ? Pourquoi trouve-on un seuil de 0.5 et non 0.4 comme avec le package
ROCR. Conclure en critiquant les kppv.

# seuil variant entre 0 et 1 : s <- seq(0,1,by=0.01)


plot(s,tbc_test,type="l", col=2,xlab="seuil",
ylab="TBC",main="Seuils variant par pas de 0.1")

Seuils variant par pas de 0.1


0.8
0.7
TBC

0.6
0.5

0.0 0.2 0.4 0.6 0.8 1.0

seuil

s[which.max(tbc_test)] #seuil qui maximise le tbc


## [1] 0.5

10

Vous aimerez peut-être aussi