TP1 Les K Plus Proches Voisins
TP1 Les K Plus Proches Voisins
TP1 Les K Plus Proches Voisins
Apprentissage supervisé
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)
0.05
0.00
−5 0 5 10 15
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))
Risque empirique
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))
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.
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
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
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")
0.90
0.85
0.80
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
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")
0.4
0.2
0.0
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
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.
0.6
0.5
seuil
10