machine-learning
Une introduction à la classification: générer plusieurs modèles avec Weka
Recherche…
Introduction
Ce tutoriel vous montrera comment utiliser Weka en code JAVA, charger un fichier de données, former des classificateurs et expliquer certains concepts importants de l’apprentissage automatique.
Weka est une boîte à outils pour l'apprentissage automatique. Il comprend une bibliothèque de techniques d'apprentissage et de visualisation et comprend une interface utilisateur conviviale.
Ce tutoriel comprend des exemples écrits en JAVA et inclut des éléments visuels générés avec l'interface graphique. Je suggère d'utiliser l'interface graphique pour examiner les données et le code JAVA pour des expériences structurées.
Mise en route: Chargement d'un jeu de données à partir d'un fichier
Le jeu de données de fleurs Iris est un ensemble de données largement utilisé à des fins de démonstration. Nous allons le charger, l'inspecter et le modifier légèrement pour une utilisation ultérieure.
import java.io.File;
import java.net.URL;
import weka.core.Instances;
import weka.core.converters.ArffSaver;
import weka.core.converters.CSVLoader;
import weka.filters.Filter;
import weka.filters.unsupervised.attribute.RenameAttribute;
import weka.classifiers.evaluation.Evaluation;
import weka.classifiers.rules.ZeroR;
import weka.classifiers.bayes.NaiveBayes;
import weka.classifiers.lazy.IBk;
import weka.classifiers.trees.J48;
import weka.classifiers.meta.AdaBoostM1;
public class IrisExperiments {
public static void main(String args[]) throws Exception
{
//First we open stream to a data set as provided on http://archive.ics.uci.edu
CSVLoader loader = new CSVLoader();
loader.setSource(new URL("http://archive.ics.uci.edu/ml/machine-learning-databases/iris/iris.data").openStream());
Instances data = loader.getDataSet();
//This file has 149 examples with 5 attributes
//In order:
// sepal length in cm
// sepal width in cm
// petal length in cm
// petal width in cm
// class ( Iris Setosa , Iris Versicolour, Iris Virginica)
//Let's briefly inspect the data
System.out.println("This file has " + data.numInstances()+" examples.");
System.out.println("The first example looks like this: ");
for(int i = 0; i < data.instance(0).numAttributes();i++ ){
System.out.println(data.instance(0).attribute(i));
}
// NOTE that the last attribute is Nominal
// It is convention to have a nominal variable at the last index as target variable
// Let's tidy up the data a little bit
// Nothing too serious just to show how we can manipulate the data with filters
RenameAttribute renamer = new RenameAttribute();
renamer.setOptions(weka.core.Utils.splitOptions("-R last -replace Iris-type"));
renamer.setInputFormat(data);
data = Filter.useFilter(data, renamer);
System.out.println("We changed the name of the target class.");
System.out.println("And now it looks like this:");
System.out.println(data.instance(0).attribute(4));
//Now we do this for all the attributes
renamer.setOptions(weka.core.Utils.splitOptions("-R 1 -replace sepal-length"));
renamer.setInputFormat(data);
data = Filter.useFilter(data, renamer);
renamer.setOptions(weka.core.Utils.splitOptions("-R 2 -replace sepal-width"));
renamer.setInputFormat(data);
data = Filter.useFilter(data, renamer);
renamer.setOptions(weka.core.Utils.splitOptions("-R 3 -replace petal-length"));
renamer.setInputFormat(data);
data = Filter.useFilter(data, renamer);
renamer.setOptions(weka.core.Utils.splitOptions("-R 4 -replace petal-width"));
renamer.setInputFormat(data);
data = Filter.useFilter(data, renamer);
//Lastly we save our newly created file to disk
ArffSaver saver = new ArffSaver();
saver.setInstances(data);
saver.setFile(new File("IrisSet.arff"));
saver.writeBatch();
}
}
Former le premier classificateur: définir une référence avec ZeroR
ZeroR est un classificateur simple. Il ne fonctionne pas par instance mais opère sur la distribution générale des classes. Il sélectionne la classe avec la plus grande probabilité a priori. Ce n'est pas un bon classificateur dans le sens où il n'utilise aucune information dans le candidat, mais il est souvent utilisé comme base. Remarque: d'autres lignes de base peuvent être utilisées, telles que: Classificateurs standard ou règles artisanales
// First we tell our data that it's class is hidden in the last attribute
data.setClassIndex(data.numAttributes() -1);
// Then we split the data in to two sets
// randomize first because we don't want unequal distributions
data.randomize(new java.util.Random(0));
Instances testset = new Instances(data, 0, 50);
Instances trainset = new Instances(data, 50, 99);
// Now we build a classifier
// Train it with the trainset
ZeroR classifier1 = new ZeroR();
classifier1.buildClassifier(trainset);
// Next we test it against the testset
Evaluation Test = new Evaluation(trainset);
Test.evaluateModel(classifier1, testset);
System.out.println(Test.toSummaryString());
La plus grande classe de l'ensemble vous donne un taux correct de 34%. (50 sur 149)
Remarque: le ZeroR effectue environ 30%. C'est parce que nous avons divisé au hasard dans un train et un ensemble de test. Le plus grand ensemble de la rame sera donc le plus petit de l'ensemble de test. Fabriquer un bon ensemble test / train peut valoir la peine
Avoir une idée des données. Entraînement Naive Bayes et kNN
Afin de construire un bon classificateur, nous devrons souvent avoir une idée de la structure des données dans l'espace des objets. Weka propose un module de visualisation pouvant aider.
Certaines dimensions séparent déjà assez bien les classes. La largeur des pétales ordonne le concept de manière très nette, par exemple par rapport à la largeur des pétales.
La formation de classificateurs simples peut en révéler beaucoup sur la structure des données. J'aime généralement utiliser Nearest Neighbor et Naive Bayes à cette fin. Naive Bayes assume son indépendance, elle fonctionne bien, ce qui indique que les dimensions sur elles-mêmes détiennent des informations. k-Nearest-Neighbor fonctionne en attribuant la classe des k instances les plus proches (connues) dans l'espace des objets. Il est souvent utilisé pour examiner la dépendance géographique locale, nous l'utiliserons pour examiner si notre concept est défini localement dans l'espace des entités.
//Now we build a Naive Bayes classifier
NaiveBayes classifier2 = new NaiveBayes();
classifier2.buildClassifier(trainset);
// Next we test it against the testset
Test = new Evaluation(trainset);
Test.evaluateModel(classifier2, testset);
System.out.println(Test.toSummaryString());
//Now we build a kNN classifier
IBk classifier3 = new IBk();
// We tell the classifier to use the first nearest neighbor as example
classifier3.setOptions(weka.core.Utils.splitOptions("-K 1"));
classifier3.buildClassifier(trainset);
// Next we test it against the testset
Test = new Evaluation(trainset);
Test.evaluateModel(classifier3, testset);
System.out.println(Test.toSummaryString());
Naive Bayes fonctionne beaucoup mieux que notre base de référence fraîchement établie, indiquant que des fonctionnalités indépendantes contiennent des informations (souvenez-vous de la largeur des pétales?).
1NN fonctionne bien aussi (en fait un peu mieux dans ce cas), indiquant que certaines de nos informations sont locales. La meilleure performance pourrait indiquer que certains effets de second ordre contiennent également des informations (If x et y que la classe z) .
Rassembler: Former un arbre
Les arbres peuvent créer des modèles qui fonctionnent sur des fonctions indépendantes et sur des effets de second ordre. Ils pourraient donc être de bons candidats pour ce domaine. Les arbres sont des règles qui sont regroupées, une règle divise les instances qui parviennent à une règle dans des sous-groupes, qui passent aux règles de la règle.
Les apprenants arborescents génèrent des règles, les enchaînent et arrêtent de construire des arborescences lorsqu'ils estiment que les règles deviennent trop spécifiques, pour éviter de les dépasser. Overfitting signifie construire un modèle trop complexe pour le concept que nous recherchons. Les modèles surdimensionnés fonctionnent bien sur les données du train, mais mal sur les nouvelles données
Nous utilisons J48, une implémentation JAVA de C4.5 un algorithme populaire.
//We train a tree using J48
//J48 is a JAVA implementation of the C4.5 algorithm
J48 classifier4 = new J48();
//We set it's confidence level to 0.1
//The confidence level tell J48 how specific a rule can be before it gets pruned
classifier4.setOptions(weka.core.Utils.splitOptions("-C 0.1"));
classifier4.buildClassifier(trainset);
// Next we test it against the testset
Test = new Evaluation(trainset);
Test.evaluateModel(classifier4, testset);
System.out.println(Test.toSummaryString());
System.out.print(classifier4.toString());
//We set it's confidence level to 0.5
//Allowing the tree to maintain more complex rules
classifier4.setOptions(weka.core.Utils.splitOptions("-C 0.5"));
classifier4.buildClassifier(trainset);
// Next we test it against the testset
Test = new Evaluation(trainset);
Test.evaluateModel(classifier4, testset);
System.out.println(Test.toSummaryString());
System.out.print(classifier4.toString());
L'apprenant en formation formé avec la plus grande confiance génère les règles les plus spécifiques et offre les meilleures performances sur l'ensemble de test, apparemment la spécificité est justifiée.
Remarque: les deux apprenants commencent par une règle sur la largeur des pétales. Rappelez-vous comment nous avons remarqué cette dimension dans la visualisation?