silico.biotoul.fr
 

M1 MABS BBS Data Mining TD Classification

From silico.biotoul.fr

Revision as of 18:07, 25 November 2014 by Barriot (Talk | contribs)
Jump to: navigation, search

Contents

Introduction

Afin de mettre en pratique les concepts vus en cours, nous allons nous appuyer sur des jeux de données publiques hébergées par le UC Irvine Machine Learning Repository.

Pour le premier jeu de données intitulé "mushrooms", il s'agit de classer un champignon comme comestible ou non en fonction d'attributs de type catégoriel. Pour le second - italian wines -, il s'agit de prédire le cultivar du cépage en fonction de mesures quantitatives.

Pour cela, nous utiliserons différents environnements :

  • KNIME : un logiciel d'analyse qui est en fait un environnement dérivé de la plateforme de développement intégré Eclipse
  • R : environnement orienté calcul numérique & statistiques
  • python : un langage de programmation afin de voir l'utilisation de bibliothèque de fouille de données ainsi que pour réaliser son propre programme de classification

Mushrooms

Les données

Le premier jeu de données concerne des champignons. Il est publié à l'adresse : http://archive.ics.uci.edu/ml/datasets/Mushroom

La description du jeu de données est aussi accessible ici.

Le jeu de données modifié pour inclure une première ligne contenant les noms des colonnes est disponible ici.

Analyses préliminaires avec R

Charger le jeu de données et utiliser la commande summary pour vous faire une idée du nombre d'instances de chaque classe, et du nombre de modalité de chaque facteur (attribut/dimension/variable).

Etudiez ensuite la liaison entre chaque variable et la classe. Pour cela, vous pourrez utiliser le test du χ2 d'indépendance. Utilisez également la fonction table (pour générer une table de contingence) pour la combiner avec la fonction plot afin d'explorer visuellement les biais entre chaque attribut et la classe.

Exemple de visualisation :

Image:mushrooms.gill.attachment.png

Ces analyses devrait vous permettre de vous faire une idée sur la pertinence d'un attribut en ce qui concerne l'objectif : classer un champignon comme comestible ou pas.

Quels attributs vous semblent les plus pertinents ?

A partir de là, il semble qu'aucun attribut peut permettre à lui seul de classer un échantillon. Nous allons donc utiliser des méthodes d'apprentissage proposées dans le logiciel KNIME.

Analyses avec KNIME

Pour cette partie, nous allons utiliser l'environnement pour la fouille de données KNIME. C'est un logiciel en Java développé à l'origine par l'université de Constance (Allemagne).

Construction du modèle

La première étape consiste à charger les données. Dans KNIME, ajoutez un noeud File Reader (section IO pour Input/Output) et configurez-le afin de charger le fichier de données.

Comme premier exercice, ajoutez un noeud Decision Tree Learner (induction d'arbre de décision) et connectez la sortie du File Reader à l'entrée du Decision Tree Learner. Configurez ce dernier pour qu'il cherche à prédire la classe du champignon. Lancez l'éxécution de ces noeuds et visualisez l'arbre de décision inféré. Quelles sont les variables les plus importantes ?

Remarque : A la configuration du noeud Decision Tree Learner, observez les autres paramètres disponibles (mesure de pertinence d'un attribut, élagage).

Effectuez la même chose avec un classificateur bayésien naïf et visualisez le modèle obtenu.

Evaluation des performances

Afin de décider quelle méthode fonctionne le mieux (arbre de décision ou bayésien naïf) pour ce jeu de données et avec quels paramètres (gain ratio ou gini index par exemple), vous allez effectuer des validation croisées.

Pour cela, ajoutez et en configurez un noeud Cross validation (section Meta). Une leave-one-out cross validation (ou LOOCV) sera pour ce TP trop couteuse en temps (> 8000 modèles inférés par méthode). Essayez par exemple avec les valeurs 3 et 10 pour le noeud X-partitioner (3-fold ou 10-fold cross validation). Ceci aura pour effet de diviser le jeu de données en entrées en jeux de données d'apprentissage (pour le learner) et jeux de données tests (pour le modèle produit par le learner). Configurez enfin le noeud X-agregator qui confrontera la classe prédite à la classe connue.

Examinez ensuite le taux d'erreurs à l'aide d'un noeud Statistics view.

Faites varier la méthode et ces paramètres et notez à chaque fois les performances obtenues (taux d'erreurs) :

  • arbre de décision
    • gain ratio ou gini index
    • no pruning ou MDL
  • bayésien naïf

Qu'observez vous lorsque vous augmentez le nombre de validations croisées (3-fold vs. 10-fold) ?

Italian wines

Les données

Le second jeu de données concerne des cépage de vins italiens. Il est publié à l'adresse : http://archive.ics.uci.edu/ml/datasets/Wine

La description du jeu de données est aussi accessible ici.

Le jeu de données modifié pour inclure une première ligne contenant les noms des colonnes est disponible ici.

Analyses avec KNIME

Chargez le jeu de données et faites construire le modèle de classificateur bayésien naïf. Observez le modèle obtenu. Quelle(s) différence(s) au niveau du modèle observez-vous par rapport à celui appris sur les champignons ?


Pour finir avec KNIME et choisir entre la méhotde bayésienne et celle des k plus proches voisins, effectuez des validations croisées (10-fold CV). Pour la méthode k-NN, faites varier le nombre de voisins considérés (1, 3 et 10 par exemple). Observez-vous une différence notable de performances ? par rapport à k ? par rapport à la méthode bayésienne ?

La distance calculée par k-NN est en fait sensible aux unités (et plages de valeurs) de chacune des dimensions. Refaites la validation en ayant au préalable normalisé les dimensions avec la méthode z-score.

Pour décider la méthode et ses paramètres, effectuez des validations croisées (10-fold et LOOCV) avec comme normalisation (z-score, min-max, decimal scaling) et notez les taux d'erreurs obtenus.

Analyses avec R

Analyse descriptive

Commencez par charger le jeu de données et faire un summary.

Pour la suite, il vous est conseillé de stocker la classe dans un vecteur (par exemple y) et les données sous forme de matrice.

Tracez un camembert pour l'effectif de chaque classe.

Etudiez ensuite la distribution des valeurs de chaque dimension par rapport à la classe. Vous pourrez par exemple tracer des boites à moustache :

Image:Italian.wine.alcohol.boxplot.png

Notez les attributs qui vous semblent le mieux séparer les classes.

Comme vue en cours de Traitement de données biologiques, il est possible de faire une ANOVA à plusieurs facteurs afin d'estimer si les moyennes des différentes mesures sont égales et s'il y a interaction entre ces facteurs. Même si ce n'est pas le sujet d'aujourd'hui, ici, il y a clairement un effet du cultivar sur plusieurs des mesures effectuées et certaines sont sûrement corrélées. On remarquera tout de même que lorsqu'il y a plus de 2 mesures, l'analyse se complexifie.

Sur la base des distributions par classe (boxplots précédents), il semble qu'aucune des mesures n'est capable de discriminer à elle seule les différents cultivars. Par contre, il est peut-être possible de séparer les classes en combinant plusieurs variables.

Essayez de combiner quelques paires de variables parmi celles relevées précédemment. Par exemple, avec alcohol et flavonoids on obtient :

Image:Italian.wine.alcohol-flavonoids.png

On observe que la séparation entre les classes (différentes couleurs) bien que pas mauvaise n'est pas complète pour ce couple de mesures.

Remarque : pour visualiser toutes les pairs de variables, utilisez la fonction pairs.

Analyse discriminante linéaire

L'analyse discriminante linéaire permet de trouver la combinaison linéaire des variables qui permet de séparer le mieux les classes. Pour cela, nous allons utiliser la librairie MASS :

# lecture des données dans une data.frame puis vecteur y et matrice
DF=read.table('wine.data.txt',header=T,sep=',')
y=as.factor(DF[,1])
wine=DF[,-1]
# analyse discriminante
library(MASS)
sol = lda(x=wine, grouping=y)

Commentez le contenu de sol.

Comme il y a 3 classes, on peut projeter le résultat sur 2 axes (un de moins que le nombre de classes). Faire plot(sol) et commenter.

LD1 et L2 sont les vecteurs portant les axes de la projections (vecteurs propres associées aux plus grandes valeurs propres de V-1B avec V et B les matrices de variance-covariance totale et inter-classes respectivement, cf. cours).

Pour s'en assurer, on peut tracer la projection des individus d'origines :

par(mfrow=c(1,2))
plot(sol)
plot(as.matrix(wine) %*% sol$scaling, col=y, pch=19)

Image:Italian.wine.sol-projection.png


Est-ce qu'il est possible d'obtenir a priori de bonnes performances sur ce jeu de données avec une analyse discriminante ?

Pour l'analyse des performances, vous allez faire le schéma 2/3 training et 1/3 test set :

n = nrow(wine)
training = sample(n, round(2*n/3)) # tirage aléatoire de 2/3 pour le jeu d'apprentissage
train = wine[training,]
train_y = y[training]
test = wine[-training,] # le reste pour le jeu de test
test_y = y[-training]

Effectuer l'analyse discriminante avec le jeu de données d'apprentissage ainsi obtenu et la prédiction sur le jeu de données test à l'aide de la fonction predict(sol, test). Commentez la sortie de la fonction predict.

Tracez le résultat avec plot et text :

Image:Italian.wine.lda.cross-validation.png

Selon l'échantillon test tiré, il y aura ou non des individus mal classés : par exemple, un 2 apparaissant en vert sur le plot ci-dessus.

Remarque : la projection est sensiblement différente de la précédente puisque le jeu de données d'apprentissage est différent.

Calculer le taux d'erreurs pour votre tirage.

Pour visualiser l'espace de décision, on peut utiliser la librairie klaR (à installer).

library(klaR)
partimat(as.matrix(train) %*% sol$scaling, train_y)

Image:Italian.wine.lda.decision-map.png

Et pour tracer la projection avec les mêmes axes (LD1 en ordonnées) :

train.proj = as.matrix(train) %*% sol$scaling
plot(train.proj[,2], train.proj[,1], pch=16, col=train_y, xlab='LD2', ylab='LD1')
test.proj = as.matrix(test) %*% sol$scaling
text(test.proj[,2], test.proj[,1], col=as.character(test_y), labels=test_y)

Image:Italian.wine.lda-LD2vsLD1.png

Analyse discriminante "manuelle"

A compléter

Analyses avec python

A compléter