« februari 2007 | Main | april 2007 »

mars 11, 2007

Några saker om Weka (databrytning, data mining och machine learning)

Not: Delar i nedanstående förutsätter att man känner till data mining/machine learning-verktyget Weka (Wiki). Tyvärr är det en ganska begränsad skara bland mina läsare.

Tystnaden den senaste tiden har till visst del berott på läsning av andra upplagan av boken Data Mining
Practical Machine Learning Tools and Techniques
(ISBN: 0120884070, ISBN13: 9780120884070) som förutom en mycket trevlig och pedagogisk läsning om data mining/machine learning generellt även beskriver just Weka. Till läsande av sådana böcker kommer naturligtvis lekande och testande av saker.


CVS-versionen
Även om det kommer nya versioner av den publika versionen är CVS-versionen att rekommendera eftersom där kommer nya saker hela tiden, framförallt buggfixar. Via mailinglistan förmedlas (de flesta) av ändringarna.

Numera hämtar jag den senaste versionen dagligen med nedanstående program shell-program (Linux). Apache Ant krävs för att kompilera Java-koden. Lösenordet för cvs login är en vagnretur (Enter-tangenten, alltså)

#!/bin/sh
export CVSROOT=:pserver:cvs_anon@cvs.scms.waikato.ac.nz/usr/local/global-cvs/ml_cvs
cvs login
cvs -q co weka
cvs -q co tests
cd weka
# kompilerar koden
/usr/bin/ant
# skapar java doc
/usr/bin/ant docs > /dev/null

Se även CVS-sidan på Wikin.

Närmare bestämt görs detta som ett cron-jobb. Ett Expect-script skapades med programmet autoexpect så att det går helt utan manuell inblandning.

Just det: i crontab måste man se till så att programmen körs i rätt katalog och har de miljövariabler som krävs, såsom CLASSPATH. Min crontab-entry ser ut så ungefär så här (det ska vara en rad) där weka_co.exp är Expect-programmet:

6,12 * * * . /home/hakank/.zshrc && cd /home/hakank/weka_cvs && /home/hakank/weka_cvs/weka_co.exp


Filter
I Weka Explorer (GUI-versionen) och via kommandoraden kan man använda filter för att filtrera datamängderna på olika sätt. Som jag använder Weka nu är det nästan uteslutande via GUI-versionen.

Här är några användbara filter för initialanalys av datan:

Ett filter som jag nyligen skapade är ExpandFreqField som givet ett frekvensfält duplicerar instanser så att det finns så många som frekvensfältet anger. T.ex. följande synnerligen fiktiva datafil (i ARFF-format) har ett sådant frekvensattribut freq (det sista fältet).

@relation Freq
@attribute a {p,q,r}
@attribute x numeric
@attribute y numeric
@attribute freq numeric
@data
p,1,2,1
q,2,3,2
r,3,4,4

dvs första instansen (dataraden som börjar med "p") ska förekomma 1 gång, andra instansen 2 gånger samt tredje instansen 4 gånger. Filtret skapar en ny datamängd som ser ut så här om man kör från kommandoraden: java weka.filters.unsupervised.instance.ExpandFreqField -i ExpandFreqFieldTest.arff
eller väljer filtret via Weka Explorer.


@relation Freq-weka.filters.unsupervised.instance.ExpandFreqField-Flast
@attribute a {p,q,r}
@attribute x numeric
@attribute y numeric
@attribute freq numeric
@data
p,1,2,1
q,2,3,2
q,2,3,2
r,3,4,4
r,3,4,4
r,3,4,4
r,3,4,4

Installation av filtret kräver att man har Java-koden till Weka-installerat (det har man om man laddar ner CVS-versionen enligt ovan):

Kommentar: Normalt skriver jag Perl-program för sådana filter-saker men sådant går inte alls att integrera i Weka Explorer på samma sätt som ett riktigt Weka-filte.


MultiFilter
Eftersom jag använder Weka Explorer för "explorativ data mining" är det många saker som måste göras om varje gång, t.ex. RemoveUseless eller outliner-kontroll enligt InterquartileRange (se ovan). MultiFilter finns ett bra sätt att kombinera flera olika filter. Så här gör man:

* Öppna filtret MultiFilter
* Lägg till de filter som ska användas. Se till så att de läggs i rätt ordning
* Spara filtret med ett lämpligt namn
* Vid senare tillfälle kan man öppna MultiFiltret och köra det rakt av

Några exempel

Det andra filtret tar alltså först bort instanser som är ExtremeValues (det sista attributet), sedan raderas detta attribut. Ett AllFilter justerar attributpositionerna, varefter samma sak görs med Outlier-attributet (som då är det sista attributet).

I båda dessa MultiFilter har filtret AllFilter lagts till som ett "strömfilter" eftersom föregående filter tar bort ett attribut. Sådana attributförändringar förvirrar uppenbarligen nästkommande filter om det arbetar med attributpositioner (såsom first, last, 2,4).

Några nya favoritklassificerare
Tidigare har trädklassificeraren J48 (tillsammans med baselinemetoden OneR och NaiveBayes) varit förstaklassificerare eftersom den är snabb och ger ett översiktlig bild av datans struktur. Numera är det REPTree som har denna status eftersom den är ännu snabbare (dock inte lika stabil som J48),

Några andra nya som är värda att testa:
* SimpleCart - som är en "enkel" implementation av CART (en av de första trädklassificerarna)
* JRip och - inte så ny i Weka men efter genomläsningen av boken återficks ett intresse för regelbaserade klassificerare. Man hittar i dessa regelbaserade små data-klimpar (nuggets) som kan vara intressanta.

För övrigt kan rekommenderas ett studium av BayesNet med algoritmen ICSSearch som ger riktigt trevliga dependensträd (som man i vissa fall möjligen kan tolka som orsaksgrafer), t.ex. om man sätter maxCardinality till > 2. Man bör inte glömma att högerklicka på entryn i Result list och välja "Visualize graph" för då missar man den fina dependensgrafen. Tyvärr kostar metoden mycket kräm (dvs internminne + tid). Mer om BayesNet-implementationen i Weka kan man läsa i Remco R Bouckaert Bayesian Network Classifiers in Weka (PDF, även gammal HTML-version).


R:s RWeka för att konvertera datafiler
Om man som jag är på jakt efter trevliga datamängder att leka med kan man fördel utnyttja den rikliga mängd av data som finns i R med hjälp av paketet RWeka där funktionen write.arff (och read.arff) kan användas. Notera att vissa konverteringar inte fungerar eftersom write.arff förutsätter en datastruktur som inte alltid uppfylles.

Om man vill (och det vill man nog) konvertera alla data från ett R-paket kan man använda följande. ARFF-filerna läggs i den katalog där man startade R.

write.arff.data.package <- function(pack) {
require(RWeka);
for (x in data(package = pack)$results[,3]) {
print(x);
data(list=as.character(x),package=pack)
try(write.arff(get(x),paste(x,".arff",sep="")))
}
}

Exempel: konvertera data som finns i paketet dprep:

write.arff.data.package("dprep")


Känner man sig riktigt modig och har tid (det gör man ibland och har man ibland) kan man köra detta för att konvertera data i samtliga paket

for (pack in .packages(all = TRUE)) {
print(pack);
write.arff.data.package(pack)
}

Notera återigen att allting blir inte konverterat korrekt. Ett kännetecken på att det inte gick bra är att filerna innehåller strängen structure(list. Dessa filer är alltså inte användbara i Weka.

Datafiler
Apropå datafiler.

Har man inte laddat ned ARFF-datafilerna som finns nedladdningsbara bör man göra det. Där finns framförallt standarddatamängderna från UCI Machine Learning Repository och Statlib.

Just det: Man borde ARFF-iera DASL - The Data and Story Library . [... time passes ... ] Fixat: Arff-versioner av DASL.

YALE (och Weka Knowledge Flow)
YALE Yet Another Learning Environment är ett - egentligen - trevligt GUI för att data mining / machine learning. Det inkluderar mycket av Wekas algoritmer och har använder processflöde snarare än det manuella framochtillbakande som används i Weka Explorer. YALE har framförallt bättre möjligheter än Weka att visualisera data, t.ex. sådant som SOM (Kohonen), Andrews-kurvor och plotter-matriser. Man styr experiment antingen via GUI eller att skriva XML-filer. En mycket stor fördel är att det finns en bra online-tutorial som förklarar komponenterna och hur de ska integreras (med många exempel). Det är bra.

Personligen är jag inte så väldigt förtjust i detta processflödande, vilket mest beror på mitt sätt att arbeta med Weka just nu, nämligen att leka med algoritmer, metoder och datamängder. Just sådant är meckigare i YALE. Ett exempel: I Weka Explorer antas att klassattributet är det sista och vill man ändra det är det enkelt att göra i Preprocess. I YALE måste man däremot alltid manuellt skriva in attributnamnet (såvida man inte sparat ett experiment med ett sådant ifyllt). En annan sak är att det finns ohyggligt många komponenter med olika roller och krav, och i alla fall i början är det förvirrande hur de hänger ihop och hur man ska tolka olika felmeddelande att man inte har rätt komponent. Det finns dock en flera hundra sidors dokumentation som beskriver alla komponenter.

Trots ovanstående kittsligheter är YALE definitivt något att hålla ögonen på och att åtminstone använda som komponent till Weka.

Weka KnowledgeFlow har också ett flödestänkande och jag har samma relation till det som till YALE, nämligen att hellre använda Weka Explorer.

Se även
My Weka Page

Posted by hakank at 10:51 FM Posted to Machine learning/data mining