silico.biotoul.fr
 

M1 MABS BBS Data Mining TD KNIME

From silico.biotoul.fr

Jump to: navigation, search

Contents

Contexte

Afin de mettre en pratique les concepts vus en cours, nous allons nous appuyer sur un jeu de données publiques hébergées par le UC Irvine Machine Learning Repository. Il s'agit d'une petite base de données sur des données cliniques de patients (âge, sexe, ...) associées à la présence ou l'absence d'une maladie cardiaque.

Pour chaque personne (270 en tout), vous disposez de 13 variables :

  • âge (age) : continue
  • sexe (sex) : discrète M/F
  • type de douleur à la poitrine (chest_pain_type) : discrète, 4 valeurs 1/2/3/4
  • pression sanguine au repos (resting_blood_pressure) : continue
  • taux de cholestérol en mg/dl (serum_cholesterol) : continue
  • glycémie à jeun > 120 mg/dl (fasting_blood_sugar) : discrète FALSE/TRUE
  • électrocardiogramme au repos (resting_ecg_results) : discrète 0/1/2
  • fréquence cardiaque maximale (max_heart_rate) : continue
  • angine induite par l'exercice (excerise_induced_angina) : discrète FALSE/TRUE
  • "oldpeak = ST depression induced by exercise relative to rest" (depression_induced) : continue
  • pente de la crête du segment ST (slope) : ordinale 1/2/3
  • nombre de vaisseaux (major_vessels) : continue
  • thal (thal) : discrète normal/fixed_defect/reversable_defect

ainsi que de la présence ou l'absence d'une maladie cardiaque. Il va donc s'agir à partir des variables de construire un modèle (arbre de décision, bayésien, ...) afin de prédire la présence d'une maladie cardiaque chez une personne.



Classification

Utilisation d'un environnement de fouille de données

Pour cette partie, nous allons principalement 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).

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 Media:Data_Mining_heart.txt.

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 si un individu est malade. Lancez l'éxécution de ces noeuds et visualisez l'arbre de décision induit. Quels sont les variables les plus importantes ? Comparez les résultats avec ou sans élagage.

Ensuite, évaluez les performance de ce type de classificateur en ajoutant et en configurant un noeud Cross validation (section Meta). Vous lui ferez effectuer une leave-one-out cross validation. Examiner ensuite le taux d'erreurs à l'aide d'un noeud Statistics view.

Effectuer le même travail avec les types de classificateur suivants :

  • Bayésien naïf,
  • k plus proches voisins (essayez différentes valeurs de k),
  • Réseau de neurones.

Quel est le classificateur le plus performant sur ce jeu de données ?

Utilisation d'une bibliothèque de programmation

Afin d'automatiser la réalisation de certaines tâches, il est possible d'utiliser une librairie/module/bibliothèque proposant des fonctionnalités de fouilles de données. Il en existe pour différents langages de programmation, certaines proposant également une interface utilisateur graphique et/ou des passerelles pour d'autres langages de programmation (ex: RWeka) :

Pour aujourd'hui, nous utiliserons Orange.

Import de la librairie

Si la librairie n'est pas installée, elle peut l'être en téléchargeant la version appropriée (Windows, Mac ou linux). Pour linux, il faut récupérer les sources et en effectuer une installation standard :

python setup.py build
python setup.py install

Si vous ne disposez pas des droits administrateurs sur le poste de travail, il est possible de l'installer comme une librairie utilisateur :

python setup.py install --user


Une fois correctement installée, l'import de la librairie se fait très simplement :

#!/usr/bin/python
 
import orange

Chargement des données

Orange propose différentes facilités pour charger un jeu de données, notamment un format CSV (les colonnes sont en fait séparées par des tabulations) amélioré qui permet de décrire le nom des colonnes, leur type, ainsi que la colonne correspondant à la classe :

  • la première ligne contient les noms des colonnes
  • la deuxième contient les types des colonnes : discrete, continuous, string, ignore
  • la troisième peut contenir le mot class dans la colonne correspondant à la classe
  • les lignes suivantes correspondent aux données

Inspection des données

Avant de charger le jeu de données dans votre script python, adaptez le fichier de données en conséquence puis :

# LOAD DATASET
data = orange.ExampleTable("Data_Mining_heart.orange.tab")

Avant toute utilisation du jeu de données pour faire de la fouille ou autre technique d'apprentissage, il est bon d'étudier les données dont on dispose.

Inspection des types des données

# report on number of classes and attributes
print "Classes:", len(data.domain.classVar.values)
print "Attributes:", len(data.domain.attributes), ",",
# count number of continuous and discrete attributes
ncont=0; ndisc=0
for a in data.domain.attributes:
    if a.varType == orange.VarTypes.Discrete:
        ndisc = ndisc + 1
    else:
        ncont = ncont + 1
print ncont, "continuous,", ndisc, "discrete"

Distribution des données

# obtain class distribution
c = [0] * len(data.domain.classVar.values)
for e in data:
    c[int(e.getclass())] += 1
print "Instances: ", len(data), "total",
for i in range(len(data.domain.classVar.values)):
    print ",", c[i], "with class", data.domain.classVar.values[i],
print
print 
 
dist = orange.DomainDistributions(data)
 
print "Average values and mean square errors:"
for i in range(len(data.domain.attributes)):
    if data.domain.attributes[i].varType == orange.VarTypes.Continuous:
        print "%s, mean=%5.2f +- %5.2f" % \
            (data.domain.attributes[i].name, dist[i].average(), dist[i].error())
 
print "\nFrequencies for values of discrete attributes:"
for i in range(len(data.domain.attributes)):
    a = data.domain.attributes[i]
    if a.varType == orange.VarTypes.Discrete:
        print "%s:" % a.name
        for j in range(len(a.values)):
            print "  %s: %d" % (a.values[j], int(dist[i][j]))

Valeurs manquantes

print "\nNumber of items where attribute is not defined:"
for i in range(len(data.domain.attributes)):
    a = data.domain.attributes[i]
    print "  %2d %s" % (dist[i].unknowns, a.name)
 
# missing values manually in %
natt = len(data.domain.attributes)
missing = [0.] * natt
for i in data:
    for j in range(natt):
        if i[j].isSpecial():
            missing[j] += 1
missing = map(lambda x, l=len(data):x/l*100., missing)
 
print "Missing values per attribute:"
atts = data.domain.attributes
for i in range(natt):
    print "  %5.1f%s %s" % (missing[i], '%', atts[i].name)

Remarque: L'inspection des données peut-être réalisée avec n'importe quelle suite logicielle ou langage de programmation. Par exemple, il aurait été judicieux d'utiliser R pour ce travail, et notamment afficher différents graphiques tels que des histogrammes, boites à moustache, courbes de densité, graphes d'éparpillement pour chaque paire de variables continues, ... mais ce n'est pas l'objet de la séance d'aujourd'hui. Il s'agissait ici plutôt de se familiariser avec les structures de données de la librairie Orange.

Classification

# BUILD CLASSIFIER
classifier = orange.BayesLearner(data)
 
# OUTPUT MODEL (ONLY CLASS PROBABILITIES WHEN continuous VALUES)
import orngBayes
model = orngBayes.BayesLearner(data)
orngBayes.printModel(model)
 
# BUILD TEST SAMPLE
test = orange.Example(data.domain, [61, 'M', 4, 138, 166, 'FALSE', 2, 125, 'TRUE', 3.6, 2, 1, 'normal', 'TRUE'])
print "Test object ",test
 
c = classifier(test)
print "original", test.getclass(), "classified as", c
# same with probabilities
p = classifier(test, orange.GetProbabilities)
for i in range(len(data.domain.classVar.values)):
	print "%s : %5.3f" % (data.domain.classVar.values[i], p[i])

Evaluation

Orange permet également d'effectuer des validations croisées. Nous allons ainsi comparer les performances de différentes méthodes.

# Validation with various classifiers
bayes = orngBayes.BayesLearner()
import orngTree
tree = orngTree.TreeLearner(mForPruning=2)
knn = orange.kNNLearner(k=5)
bayes.name = "bayes"
tree.name = "tree"
knn.name="knn"
learners = [bayes, tree, knn]
 
import orngTest
# 10 fold cross validation
print "Performing 10-fold X validation..."
cv10 = orngTest.crossValidation(learners, data, folds=10)
# LOOCV
print "Performing LOOCV..."
loocv = orngTest.leaveOneOut(learners, data)
 
# results
import orngStat
print "Learner  10-CV     LOOCV"
for i in range(len(learners)):
    print "%-8s %5.3f     %5.3f" % (learners[i].name, orngStat.CA(cv10)[i], orngStat.CA(loocv)[i])

Jeu de données : Media:Data_Mining_heart.txt Media:Data_Mining_heart.orange.txt