machine-learning
En introduktion till klassificering: Generera flera modeller med Weka
Sök…
Introduktion
Denna handledning visar hur du använder Weka i JAVA-kod, laddar datafil, utbildar klassificerare och förklarar några viktiga begrepp bakom maskininlärning.
Weka är en verktygssats för maskininlärning. Det innehåller ett bibliotek med maskininlärning och visualiseringstekniker och har ett användarvänligt GUI.
Denna handledning innehåller exempel skrivna i JAVA och inkluderar bilder genererade med GUI. Jag föreslår att du använder GUI för att undersöka data och JAVA-kod för strukturerade experiment.
Komma igång: Laddar ett datasæt från fil
Datauppsättningen för blommor Iris är en allmänt använd datauppsättning för demonstrationsändamål. Vi laddar den, inspekterar den och ändrar den något för senare användning.
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();
}
}
Träna den första klassificeringen: Ställa in en baslinje med ZeroR
ZeroR är en enkel klassificering. Den fungerar inte per instans istället för den på allmän distribution av klasserna. Den väljer klassen med den största sannolikheten i förväg. Det är inte en bra klassificerare i den meningen att den inte använder någon information i kandidaten, men den används ofta som en baslinje. Obs: Andra baslinjer kan användas som handduk, till exempel: industristandardklassificerare eller handgjorda regler
// 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());
Den största klassen i uppsättningen ger dig en 34% korrekt ränta. (50 av 149)
Obs: ZeroR har cirka 30%. Det beror på att vi delade slumpmässigt i ett tåg- och testuppsättning. Den största uppsättningen i tåguppsättningen blir således den minsta i testuppsättningen. Att skapa ett bra test / tåguppsättning kan vara värt ditt tag
Få en känsla för data. Träning av Naive Bayes och kNN
För att bygga en bra klassificering behöver vi ofta få en uppfattning om hur informationen är strukturerad i funktionsutrymme. Weka erbjuder en visualiseringsmodul som kan hjälpa till.
Vissa dimensioner separerar redan klasserna ganska bra. Kronbladbredd ordnar konceptet ganska snyggt, jämfört med exempelvis kronbladbredd.
Träning av enkla klassificerare kan också avslöja en hel del om strukturen för uppgifterna. Jag brukar gärna använda närmaste granne och Naive Bayes för det ändamålet. Naive Bayes antar självständighet, det fungerar bra är en indikation på att dimensioner på sig själv innehar information. k-Närmaste granne fungerar genom att tilldela klassen för k närmaste (kända) instanser i funktionsutrymme. Det används ofta för att undersöka lokalt geografiskt beroende, vi kommer att använda det för att undersöka om vårt koncept definieras lokalt i funktionsutrymme.
//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 klarar sig mycket bättre än vår nyligen etablerade baslinje, vilket anger att oberoende funktioner har information (kom ihåg kronbladets bredd?).
1NN klarar sig också bra (i själva verket lite bättre i detta fall), vilket indikerar att en del av vår information är lokal. Den bättre prestandan kan indikera att vissa andra ordningseffekter också innehåller information (Om x och y än klass z) .
Sätta ihop det: Träna ett träd
Träd kan bygga modeller som arbetar med oberoende funktioner och på andra ordningseffekter. Så de kan vara bra kandidater för den här domänen. Träd är regler som är klyvda ihop, en regel delar upp instanser som kommer till en regel i undergrupper, som övergår till reglerna under regeln.
Trädelever genererar regler, kedjer dem och slutar bygga träd när de känner att reglerna blir för specifika för att undvika övermontering. Överpassning innebär att konstruera en modell som är för komplex för det koncept vi letar efter. Övermonterade modeller presterar bra på tågdata, men dåligt på nya data
Vi använder J48, en JAVA-implementering av C4.5, en populär algoritm.
//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());
Trädelever som tränas med högsta självförtroende genererar de mest specifika reglerna och har bästa prestanda på testuppsättningen, till synes är specificiteten berättigad.
Obs: Båda eleverna börjar med en regel om kronbladets bredd. Kommer du ihåg hur vi märkte denna dimension i visualiseringen?