Zoeken…


Invoering

Deze tutorial laat je zien hoe je Weka in JAVA-code kunt gebruiken, een gegevensbestand kunt laden, classificaties kunt trainen en legt enkele belangrijke concepten achter machine learning uit.

Weka is een toolkit voor machine learning. Het bevat een bibliotheek met machine learning- en visualisatietechnieken en beschikt over een gebruikersvriendelijke GUI.

Deze zelfstudie bevat voorbeelden die zijn geschreven in JAVA en bevat visuals die zijn gegenereerd met de GUI. Ik stel voor de GUI te gebruiken om gegevens en JAVA-code voor gestructureerde experimenten te onderzoeken.

Aan de slag: een gegevensset uit een bestand laden

De gegevensset Irisbloem is een veelgebruikte gegevensset voor demonstratiedoeleinden. We zullen het laden, inspecteren en enigszins aanpassen voor later gebruik.

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();
  }
}

Train de eerste classificator: een basislijn instellen met ZeroR

ZeroR is een eenvoudige classificator. Het werkt niet per instantie, maar het werkt op algemene verdeling van de klassen. Het selecteert de klasse met de grootste a priori waarschijnlijkheid. Het is geen goede classificator in die zin dat het geen informatie in de kandidaat gebruikt, maar het wordt vaak gebruikt als basislijn. Opmerking: Andere basislijnen kunnen ook worden gebruikt, zoals: classificatienormen volgens de industrie of handgemaakte regels

 // 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());

De grootste klasse in de set geeft u een 34% correct tarief. (50 van 149)

De daadwerkelijke verdeling van de klassen in de set

Opmerking: de ZeroR presteert ongeveer 30%. Dit komt omdat we willekeurig zijn opgesplitst in een trein en testset. De grootste set in de treinset is dus de kleinste in de testset. Een goede test / treinset maken kan de moeite waard zijn

Een idee krijgen van de gegevens. Training Naive Bayes en kNN

Om een goede classificator te bouwen, moeten we vaak een idee krijgen van hoe de gegevens in functieruimte zijn gestructureerd. Weka biedt een visualisatiemodule die kan helpen.

plots van 2 dimensies, klassen zijn ingekleurd

Sommige dimensies scheiden de klassen al redelijk goed. Kroonbladbreedte ordent het concept heel netjes, bijvoorbeeld in vergelijking met bloembladbreedte.

Het trainen van eenvoudige classificaties kan ook behoorlijk wat over de structuur van de gegevens onthullen. Meestal gebruik ik daar graag Neighbour Neighbor en Naive Bayes voor. Naive Bayes neemt onafhankelijkheid aan, het presteert goed als een indicatie dat dimensies op zichzelf informatie bevatten. k-Dichtstbijzijnde-buur werkt door de klasse toe te kennen van de k dichtstbijzijnde (bekende) instanties in de objectruimte. Het wordt vaak gebruikt om de lokale geografische afhankelijkheid te onderzoeken, we zullen het gebruiken om te onderzoeken of ons concept lokaal wordt gedefinieerd in de kenmerkruimte.

 //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());

Naïeve Bayes presteert veel beter dan onze pas vastgestelde basislijn en suggereert dat onafhankelijke functies informatie bevatten (denk aan bloembladbreedte?).

1NN presteert ook goed (in dit geval zelfs iets beter), wat aangeeft dat sommige van onze informatie lokaal is. De betere prestaties kunnen erop wijzen dat sommige effecten van de tweede orde ook informatie bevatten (als x en y dan klasse z) .

Samenstellen: een boom trainen

Trees kunnen modellen bouwen die werken op onafhankelijke functies en op effecten van tweede orde. Dus ze zijn misschien goede kandidaten voor dit domein. Bomen zijn regels die samen chaind zijn, een regel splitst instanties die tot een regel in subgroepen komen, die doorgaan naar de regels onder de regel.

Tree Learners genereren regels, koppelen ze aan elkaar en stoppen met het bouwen van bomen wanneer ze vinden dat de regels te specifiek worden om overfitting te voorkomen. Overfitting betekent een model bouwen dat te complex is voor het concept waarnaar we op zoek zijn. Overvolle modellen presteren goed op de treingegevens, maar slecht op nieuwe gegevens

We gebruiken J48, een JAVA-implementatie van C4.5, een populair algoritme.

//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());

De boomleer die met het grootste vertrouwen is getraind, genereert de meest specifieke regels en levert de beste prestaties op de testset, blijkbaar is de specificiteit gerechtvaardigd.

voer hier de afbeeldingsbeschrijving in voer hier de afbeeldingsbeschrijving in

Opmerking: beide leerlingen beginnen met een regel op bloembladbreedte. Weet je nog hoe we deze dimensie in de visualisatie hebben opgemerkt?



Modified text is an extract of the original Stack Overflow Documentation
Licentie onder CC BY-SA 3.0
Niet aangesloten bij Stack Overflow