Vous êtes sur la page 1sur 8

Data Mining

TP : Knn, Arbres de décision et mesure de


performance

1. Échantillonnage

Afin de découper aléatoirement nos données initiales en un échantillon d’apprentissage et un échantillon de


test, nous avons besoin de savoir générer aléatoirement des entiers qui seront considérés comme indices des
individus choisis. Pour cela on peut utiliser la fonction sample.

set.seed(1)
Npop<-1000
taille.test<-200
test.ind<-sample(1:Npop,taille.test)
appr.ind<-setdiff(1:Npop,test.ind)

Pour effectuer des tirages avec remise (utiles pour le bootstrap), il faut ajouter l’argument replace=TRUE.

sort(sample(1:10,10))
sort(sample(1:10,10,replace=TRUE))

2. Méthode de k plus proches voisins et estimation de l'erreur de


prédiction

On va travailler sur les données iris présentes dans R. La méthode des k plus proches voisins est réalisée
par la fonction knn du package class.

Première réalisation de la méthode k plus proches voisins

library(class)
#données
data<-iris
#on fixe les paramètres
Npop<-nrow(iris)
taille.test<-Npop/3
K<-3
#création du découpage apprentissage-test
test.ind<-sample(1:Npop,taille.test)
appr.ind<-setdiff(1:Npop,test.ind)
#réalisation de la prédiction
knn.pred<-knn(iris[appr.ind,-5],iris[test.ind,-5],iris[appr.ind,5],k=K)
#matrice de confusion
table(iris[test.ind,5],knn.pred)
#taux d'erreur
mean(iris[test.ind,5]!=knn.pred)

MÉCEN - 1 E ANNÉE Université de Tours - 2018-2019


Répétition du découpage apprentissage-test

On répète grâce à une boucle for le découpage des données et l’estimation de l’erreur de prédiction. Puis on
représente les estimations obtenues avec un diagramme en boîte.

err.at<-NULL
for (i in 1:100){
test.ind<-sample(1:Npop,taille.test)
appr.ind<-setdiff(1:Npop,test.ind)
knn.pred<-knn(iris[appr.ind,-5],iris[test.ind,-5],iris[appr.ind,5],k=K)
err.at[i]<-mean(iris[test.ind,5]!=knn.pred)
}
boxplot(err.at)

Méthode bootstrap

On peut également estimer l’erreur de prédiction par la méthode bootstrap.

K<-3
err.boot<-NULL
for (i in 1:100){
boot.ind<-sample(1:Npop,Npop,replace=TRUE)
test.ind<-setdiff(1:Npop,boot.ind)
knn.pred<-knn(iris[boot.ind,-5],iris[test.ind,-5],iris[boot.ind,5],k=K)
err.boot[i]<-mean(iris[test.ind,5]!=knn.pred)
}
boxplot(err.boot)

Validation croisée

Une autre méthode d’estimation est la validation croisée. On va réaliser une validation croisée en 5 groupes.

groupes<- sample(rep(1:5,each=30))
k<-3
err.cv<-NULL
for (g in 1:5){
sample1 <- iris[which(groupes!=g),-5] #pour l'apprentissage
sample2 <- iris[which(groupes==g),-5] #pour les prédictions
class1 <- iris[which(groupes!=g),5]
pred <- knn(sample1,sample2,class1,k=k)
err.cv[g]<-mean(iris$Species[which(groupes==g)]!=pred)
}
err.cv
mean(err.cv)

Répétez cela pour différentes valeurs du paramètre k afin de choisir celui fournissant le meilleur modèle.

La fonction tune
La fonction tune du package e1071 permet de sélectionner les paramètres des modèles fournissant la
plus petite estimation de l’erreur de prédiction que ce soit par validation croisée, bootstrap ou découpage
apprentissage-test.
Répetez les estimations faites précédemment en utilisant tune. Pour cela vous pouvez consulter l’aide des
commandes tune et tune.control.

MÉCEN - 1 E ANNÉE Université de Tours - 2018-2019


Application sur d'autres données

Choisissez une autre base de données (autre cours, semestre 1, etc.). Découpez les données en un échantillon
de test et un échantillon d’apprentissage.
Choisissez à l’aide des données d’apprentissage le meilleur modèle de la famille des k plus proches voisins.
Estimez l’erreur de prédiction de ce modèle sur l’ensemble de test et gardez cette valeur en mémoire.

3. Arbre de décision

Nous allons utilisé le package rpart et découvrir comment il fonctionne en travaillant sur les données iris.
Puis vous appliquerez cela pour la détection de spams.

Première réalisation

Consultez l’aide afin de comprendre les commandes et de connaître les arguments.

Npop<-nrow(iris)
taille.test<-Npop/3
#création du découpage apprentissage-test
test.ind<-sample(1:Npop,taille.test)
appr.ind<-setdiff(1:Npop,test.ind)
##
library(rpart)
control.max<-rpart.control(cp=0,max.depth=0,minbucket=1,minsplit=1)
tree<-rpart(Species~. ,data=iris[appr.ind,],control=control.max,
parms=list(split="information"))
plot(tree)
text(tree)
tree

À quoi servent les différents arguments dans rpart.control ? Que signifie split="information" ?

Estimation et élagage

Les informations sur le paramètre de complexité s’obtient avec les commandes suivantes.

plotcp(tree)
tree$cp

Une fois la valeur optimale du paramètre de complexité choisie, il faut construire le nouvel arbre.

treebis<-rpart(Species~. ,data=iris[appr.ind,],
control=rpart.control(cp=0.12),parms=list(split="information"))
plot(treebis)
text(treebis)

On peut améliorer la représentation graphique avec le package rpart.plot et la fonction prp.

library(rpart.plot)
prp(treebis,type=0,extra=0,split.box.col="lightblue",cex=0.6)
prp(treebis,type=1,extra=1,split.box.col="lightblue",cex=0.6)

MÉCEN - 1 E ANNÉE Université de Tours - 2018-2019


Prévision et estimation de l'erreur sur l'ensemble de test

pred.tree<-predict(treebis, newdata=iris[test.ind,-5],type="class")
table(pred.tree,iris[test.ind,5])
mean(pred.tree!=iris[test.ind,5])

Application sur d'autres données

Construisez un bon arbre de décision sur les données d’apprentissage.


Estimez l’erreur de prédiction de ce modèle sur l’ensemble de test et comparez cette valeur à celle obtenue
avec le modèle précédent.

N’hésitez pas à essayer à construire et tester d’autres modèles sur ces données (analyse discriminante linéaire,
quadratique, etc.) pour comparer les méthodes.

MÉCEN - 1 E ANNÉE Université de Tours - 2018-2019


Data Mining

TP : Bagging, forêts aléatoires, boosting


et arbres de régression

1. Arbres de classification

On va travailler sur les données OJ, contenues dans le package ISLR, concernant les ventes de jus d’orange.

1.1. Préparation de l'échantillon

Découper aléatoirement le jeu de données en un échantillon d’apprentissage et un échantillon de test en


proportion 1/3-2/3.
Pour que le script soit reproductible à l’identique, fixer une graine d’aléa avec la commande set.seed.
Cependant choisir des valeurs différentes entre vous afin de comparer les résultats.

1.2. Arbre de décision

Construire à partir de l’échantillon d’apprentissage un bon arbre aléatoire et le représenter.

1.3. Bagging et forêt aléatoire

Le package permettant de réaliser une forêt aléatoire ou un bagging d’arbres CART est le package
randomForest. La synthaxe est la même que pour la commande de construction des arbres de décision.
Voici la commande de base pour la réalisation d’une forêt aléatoire.

rf<-randomForest(Purchase~.,data=data.train,method="class",parms=list(split="gini"))

Pour réaliser un bagging d’arbres, il suffit de spécifier que l’on garde toutes les variables via l’argument mtry.

nvar<-ncol(OJ)-1
bag<-randomForest(Purchase~.,data=data.train,method="class",parms=list(split="gini"),
mtry=nvar)

Étudions maintenant plus en détails les sorties de ces commandes et tentons d’améliorer ces modèles.
1. Observer les différentes sorties notamment : oob.times, err.rate, votes.
2. Représenter sur le même graphique les erreurs OOB des forêts aléatoires et des bagging construits.
3. Faire varier le nombre de variables choisies à chaque cission et visualiser les erreurs OOB.
4. Faire varier la profondeur des arbres construits (avec maxnodes) dans le modèle de bagging et visualiser
les erreurs OOB.
5. Faire la même chose pour les modèles de forêts aléatoires et visualiser les erreurs OOB.
6. Récupérer la taille de forêt minimisant l’erreur OOB.
7. On s’intéresse maintenant aux variables les plus importantes dans la construction des arbres. Pour
obtenir cela effectuer les commandes suivantes.

MÉCEN - 1 E ANNÉE Université de Tours - 2018-2019


#importance des variables
rf<-randomForest(Purchase~.,data=data.train,method="class",
parms=list(split="gini"),keep.forest=TRUE,importance=TRUE)
#il faut avoir précisé importance=TRUE lors de la construction de la forêt
importance(rf)
varImpPlot(rf,main="Random Forest",cex=0.8)

1.4. Boosting

On peut réaliser du boosting d’arbres de classification avec l’algorithme AdaBoost en utilisant le package
ada.

library(ada)
boost<-ada(Purchase~.,data=data.train,type="discrete",loss="exponential",
control=rpart.control(cp=0),iter=200,nu=1,
test.y=data.test[,1],test.x=data.test[,-1])

Les arguments type="discrete" et loss="exponential" permettent de réaliser la méthode vu en cours.


À titre éducatif, regardons ce qui se passe sur les données de test avec les commandes suivantes.

plot(boost,test=T)
mean(predict(boost, newdata=data.test[,-1])!=data.test[,1])

En jouant sur l’argument control de ada, réaliser un boosting sur des stumps, c’est-à-dire des arbes à 2
feuilles.
Puis essayer d’améliorer vos modèles en intégrant une pénalisation.

Afin de trouver les meilleures valeurs pour les paramètres dont le paramètre de pénalisation, on va faire
appel au package caret. Vous pouvez trouver beaucoup d’informations sur l’utilisation du package caret
sur ce lien : https://topepo.github.io/caret/index.html.
Il est utilisable avec de très nombreux modèles et on peut contrôler beaucoup de choses. De plus, il permet
d’effectuer assez aisément les calculs en parallèle afin de diminuer les temps de calculs.

Exemple d’utilisation :

Afin de paralléliser le calcul, il suffit de créer un cluster de cœurs.

library(parallel)
#detection du nombre de coeurs
detectCores(logical=FALSE)
detectCores(logical=TRUE)
#enregistrement d'un cluster avec le package doParallel
library(doParallel)
registerDoParallel(cores=3)
#lancement de la commande à l'identique
system.time(caretada<-train(Purchase~.,data=data.train,method="ada",
trControl=ctrlCv,tuneGrid=adaGrid))
#fermeture du cluster
stopImplicitCluster()

ou

MÉCEN - 1 E ANNÉE Université de Tours - 2018-2019


#enregistrement d'un cluster avec le package doParallel
library(doParallel)
cl<-makePSOCKcluster(3)
registerDoParallel(cl)
#lancement de la commande à l'identique
system.time(caretada<-train(Purchase~.,data=data.train,method="ada",
trControl=ctrlCv,tuneGrid=adaGrid))
#fermeture du cluster
stopCluster(cl)

1.5. Choix du meilleur des modèles construits

À l’aide des données de test laissées de côté en début de procédure, estimer les erreurs de prédiction des
différents modèles sélectionnés.
On pourrait également représenter les courbes ROC des différents modèles.

2. Arbres de régression

On va travailler avec les données Boston concernant les valeurs des maisons à Boston contenu dans le package
MASS.

2.1. Préparation de l'échantillon

Commencer par découper vos données en une partie apprentissage et une partie test/validation.

2.2. Un simple arbre de régression

1. Construire un premier arbre de régression élagué dans le but de prévoir la variable medv représentant la
valeur d’une maison.
2. Utiliser le package e1071 ou le package caret pour obtenir les meilleurs paramètres. Par exemple, avec
les commandes suivantes :

library("e1071")
system.time(treetune<-tune.rpart(medv~. ,data=data.train,cp=seq(0.001,0.1,0.001)))
treetune$best.performance
treetune$best.parameter
plot(treetune)

Par défaut, la méthode d’estimation de l’erreur est une validation croisée en 10 groupes. On peut modifier
cela de la façon suivante.

tctrlboot<-tune.control(sampling="bootstrap",nboot=50)
system.time(treetune<-tune.rpart(medv~. ,data=data.train,tunecontrol=tctrlboot,
cp=seq(0.001,0.1,0.001)))
treetune$best.performance
treetune$best.parameter
plot(treetune)

2.3. Forêt aléatoire

1. Tenter d’améliorer le modèle via la construction d’une forêt aléatoire.


2. Automatiser la procédure d’optimisation des différents paramètres avec la fonction tune.

MÉCEN - 1 E ANNÉE Université de Tours - 2018-2019


2.4. Boosting

On va maintenant essayer de voir si le boosting nous permet d’obtenir un meilleur modèle. Pour cela on va
utiliser la fonction gbm du package gbm. Voici un exemple d’utilisation.

library(gbm)
system.time(boost<-gbm(medv~.,data=data.train,distribution="gaussian",
n.trees=1000,interaction.depth=4,shrinkage=1,cv.folds=5))
ntree.opt<-gbm.perf(boost,plot.it=TRUE,method="cv")

Le modèle obtenu n’est pas très bon pour un modèle de boosting. Il faut sûrement utiliser la pénalisation.
Afin de trouver les meilleures valeurs pour les paramètres dont le paramètre de pénalisation, on va faire
appel au package caret.

library(caret)
gbmGrid<-expand.grid(interaction.depth=(1:5)*2, n.trees=(1:10)*25,
shrinkage=c(0.01,0.05,0.1),n.minobsinnode=(1:3)*2)
ctrlCv<-trainControl(method="repeatedcv",repeats=3)
system.time(gbmcaret<-train(medv~.,data=data.train,method="gbm",distribution="gaussian",
trControl=ctrlCv,tuneGrid=gbmGrid))
gbmcaret
gbmcaret$bestTune
gbmcaret$finalModel
pred.gbmopt<-predict(gbmcaret$finalModel,newdata=data.test,
n.trees=gbmcaret$bestTune$n.trees)

2.5. Choix du meilleur des modèles construits

À l’aide des données de test laissées de côté en début de procédure, estimer les erreurs de prédiction des
différents modèles sélectionnés.

MÉCEN - 1 E ANNÉE Université de Tours - 2018-2019

Vous aimerez peut-être aussi