Run Forest Run!

Hallo wereld,

Vandaag kan ik met trots aankondigen dat mijn Random Forest applicatie af is! Ik moet toegeven, ik begon te twijfelen of deze dag ooit nog zou komen. Maar, de aanhouder wint.

Het was echter niet de bedoeling om alleen een Random Forest te maken. De bedoeling was om hem te vergelijken met die van de scikit-learn library. In het bijzonder de applicatie van de EliteDataScience tutorial. Om dat te kunnen doen moest ik nog wat extra aanpassingen maken. Ten eerste moest de data verdeeld worden in een training- en testset. Vervolgens moest alle data gestandaardiseerd worden. Daarnaast moesten er ook nog wat statistische gegevens berekend worden om de prestatie van het algoritme te peilen.

Dit heb ik dan (onder andere) gedaan voor een random forest met 50 bomen met maximale diepte van 20 en een sample grootte van 100. Dat wil zeggen, er zijn 50 beslissingsbomen gemaakt met maximaal 20 lagen van vertakkingen, die gegroeid zijn op basis van 100 willekeurig geselecteerde gegevensrijen uit de trainingset. Daarnaast werden dan ook nog voor elk van die bomen slechts willekeurig 3 kwart van de kolommen geselecteerd. Dit zorgt voor extra variatie tussen de bomen. Deze bomen doen dan elk hun voorspelling en de voorspelling met de meeste stemmen wint.

Het resultaat is een model dat met succes de data van de rode wijn laadt en modelleert, met een r2-score van 0.31 (vs 0.47) en een mean-squared-error van 0.5 (vs 0.33). Ter herhaling, de r2 score geeft aan hoe goed de fit van het model is. De mean-squared-error geeft aan hoe nauwkeurig het model is. Oftewel, mijn model is een slechtere fit en minder nauwkeurig. Dit was echter te verwachten, aangezien mijn model niet automatisch getuned wordt en ik de hyperparameters willekeurig gekozen heb.

Daarnaast heb ik ook de nauwkeurigheid van het model laten uitrekenen, welke 0.67 was. Niet al te slecht dus, het raadt het 2 van de 3 keer goed. Voor het sk-learn model is dit echter niet direct uit te rekenen aangezien deze in tegenstelling tot mijn model geen categorische maar numerieke voorspellingen maakt. Hierdoor zijn alle voorspellingen automatisch niet exact juist, en moet ik dus de afgeronde waardes gebruiken. Als ik dat doe, krijg ik verrassend genoeg een nauwkeurigheid van slechts 0.69. Slechts 2 procent nauwkeuriger dan mijn eigen model!

Hoe dan ook is mijn missie geslaagd. Ik heb mijn eigen Random Forest algoritme gemaakt, en het vergeleken met het model van de EliteDataScience tutorial. Hiermee heb ik niet alleen veel geleerd over de werking van het Random Forest algoritme, ik heb ook mijn vaardigheid met Python enorm verbeterd!

De code kun je hier vinden. Ook heb ik de winesnobloader aangepast om de nauwkeurigheid uit te rekenen. In de toekomst zal ik misschien wat dieper ingaan op de werking en/of wat tutorials geven voor het maken van deze en mijn andere applicaties. Op het moment heb ik echter een probleem met mijn geluidsopname-kwaliteit, dus hoe ik dat ga doen weet ik nog niet. Maar, dat is alles voor nu.

Tot de volgende keer!

 

Worstelen met bomen

Hallo wereld,

Mijn missie om een random forest te maken met Python bleek een stuk lastiger dan ik aanvankelijk had gedacht. Maar, ik heb het nog niet op gegeven. En, hoewel ik er de afgelopen maand een beetje teveel omheen heb gedraaid ben ik er nog steeds mee bezig geweest. En vooral de afgelopen week heb ik weer wat vooruitgang gemaakt.

Na het maken van mijn eerste versie voor een beslissingsboom algoritme had ik namelijk een video met een link naar de voorbeeldcode gevonden op Youtube. In dit voorbeeld wordt ook een beslissingsboom met Python gemaakt, maar de programmeur pakt het toch allemaal net wat beter aan dan ik zelf deed. Het belangrijkste verschil is dat hij gebruikt maakte van recursie, dus ik besloot opnieuw te beginnen en ook een beslissingsboom met recursie te maken. Ik had hierbij het voornemen om alleen de informatie in de video te gebruiken en de voorbeeldcode te negeren.

En, dit was me redelijk goed gelukt, maar toen ik de beslissingsboom net zoals in mijn vorige applicatie probeerde te tekenen raakte ik in de problemen. De bomen werden succesvol gemaakt, wat ik kon zien door het resultaat in tekst te printen, maar om hem (recursief) te tekenen, dat wilde me maar niet lukken. Ondanks mijn vele pogingen.

Als je zelf ervaring hebt met het werken met grote lappen code dan weet je misschien wel hoe moeilijk het kan zijn om een groot project weer op te pakken nadat je er een tijd niet aan gewerkt hebt. Je bent vergeten wat alles ook alweer precies doet, en wat je precies nog allemaal moest doen. Als je dan niet de tijd neemt om je code weer grondig te bestuderen alsof je hem voor het eerst ziet dan kan je veel tijd verspillen. Niets wil werken, je snapt niet waarom, en je staart met frustratie en wanhoop naar je grote lap met code en vraagt je af of je niet beter opnieuw kan beginnen.

Uiteindelijk heb ik dan toch maar de moeite genomen om mijn code weer opnieuw te bestuderen. Regel voor regel. Functie voor functie. En bij al deze functies erbij gezet wat ze ook alweer precies deden. Hierdoor had ik eindelijk weer een goed begrip van hoe alles precies ook alweer werkte en was de code niet zo intimiderend meer.

En toen heb ik toch ook maar de voorbeeldcode erbij gepakt en kwam ik erachter dat daarbij niet eens de moeite werd gedaan om de boom te tekenen. In plaats daarvan werd de boom wel heel netjes met recursie geprint en gebruikt voor het maken van voorspellingen. Deze methodes heb ik dan maar aangepast en aan mijn programma toegevoegd.

Het resultaat is een efficiënte, overzichtelijke en werkende applicatie voor het maken van classificatie (maar geen regressie) bomen. Mocht je vergeten zijn wat dat betekent, het houdt in dat de boom in staat is om data in categorieën te plaatsen, maar nog niet in staat is om (exacte) numerieke voorspellingen te doen.

Aanvankelijk dacht ik regressie nodig zou hebben voor de wijndata, maar nadat ik de moeite had genomen om de data te onderzoeken kwam ik erachter dat er maar vijf verschillende cijfers voor de wijnkwaliteit waren in de gehele dataset: 3 tot en met 8. Dus, het enige wat nu nog te doen staat is het implementeren van deze beslissingsboom in een random forest algoritme. En de resultaten te vergelijken met die van de Random Forest Wijnproever zoals die op EliteDataScience geïmplementeerd was. Zou moeten lukken.

Hoe dan ook ben ik al ver gekomen tijdens het werken aan deze beslissingsboom. Mijn aanvankelijke doel voor dit project was het leren begrijpen en maken van random forests. Tot mijn eigen verbazing las ik zelf in mijn eerste bericht bij dit project terug dat ik nog niet eens van plan was om een Data Scientist te worden op dit punt. Maar, uiteindelijk verschoof het hoofddoel van dit project naar het leren programmeren met Python voor Data Science.

En, ik heb een hele hoop over Python geleerd tijdens het maken van deze beslissingsboom. Het zelf kunnen maken van een random forest is echter niet meer mijn belangrijkste leerdoel, het is slechts een project voor het oefenen met Python. Uiteindelijk is het belangrijker dat ik leer te werken met de libraries van Python voor het analyseren van data en het trainen van machine learning algoritmes. En daar zal ik dan ook na dit project mee verder gaan.

Maar, dat is alles voor nu.

Tot de volgende keer!

Project update: De eerste boompjes

Hallo wereld

Het is weer hoog tijd voor een project update. Mijn missie om een Random Forest te maken in Python gaat nog steeds door. Na uren van het vergroten van mijn kennis over beslissingsbomen, oefenen met Python en prutsen met Python is het me eindelijk gelukt om een werkende applicatie te maken! Er is nog een hele hoop werk te doen, maar de eerste boompjes hebben hun blaadjes gespreid.

Zoals ik al eerder had gezegd, mijn ervaring met Python was beperkt toen ik aan dit project begon. De helft van de uitdaging in dit project zat hem dan ook in het leren om te programmeren met Python. Echter, ik was ook geen complete beginner. Ik had al ervaring met Java en mezelf eerder al genoeg aangeleerd over Python om mijn eerste applicatie te maken: Conway’s Game of Life.

Deze manier van leren programmeren met het maken van een specifieke applicatie in gedachten is in mijn ogen HEEL BELANGRIJK. Want, als je niet weet WAT je wil programmeren en simpelweg het doel stelt om een programmeertaal te leren dan zul je nooit slagen. Je kunt een programmeertaal immers NOOIT helemaal leren! Zelfs een doel als “de basis principes van Python leren” is in mijn ogen nog steeds te vaag en je zult je daarbij eerst eens goed af moeten vragen:

  • Wat zijn die basis principes?
  • Waarom wil ik ze leren?
  • Wat kan ik ermee maken?

Aldus had ik opnieuw het doel om meer over Python te leren met een specifieke applicatie in gedachten. Om dit doel te behalen moest ik wel eerst mijn kennis van de basis syntax een beetje herhalen en aanvullen. Om dat te doen had ik onder andere deze video gekeken, waarin Python in 40 minuten wordt uitgelegd, op advies van EliteDataScience. Wees gewaarschuwd echter, hoewel het meeste wat in deze video wordt uitgelegd best nuttig is, is de kwaliteit niet overal even goed. Aan het eind van de video kwam ik namelijk in de problemen met niet werkende code vanwege een typefout. Nou, dat was mijn eigen schuld natuurlijk, maar toen ik daar op stackoverflow een vraag over stelde kwam ik erachter dat een significant aantal ervaren Python programmeurs de manier waarop hij een aantal dingen deed vrij slecht vonden. In het bijzonder ging het om zijn onhandige manier van het benoemen van variabelen, en zijn manier van het declareren van classes en het implementeren van inheritance. Als geheel is de video echter nog steeds nuttig als spoedcursus, maar wees dus gewaarschuwd dat het niet allemaal even geweldig is.

Daarna ging ik verder met het volgende advies op EliteDataScience. Ze verwezen naar een leuke puzzelpagina waarbij je puzzels kunt oplossen met Python. Hoewel dit in het begin heel leuk was werkte om de een of andere reden een van mijn oplossingen niet helemaal en kon ik de volgende pagina (derde geloof ik?) niet vinden. Ik kwam wel op een of andere forum pagina die mij informeerde dat ik de oplossing juist had, maar de url voor de volgende pagina werkte echter niet voor mij. Dus opnieuw, wees gewaarschuwd.

Maar ja, genoeg daarover. Terug naar het hoofd onderwerp, het project. Waar begin ik? Nou, ik ga er even van uit dat jullie al up-to-date zijn met hoe beslissingsbomen werken. Is dit niet het geval, lees dan misschien beter eerst even mijn eerdere bericht over de werking van beslissingsbomen. De code is te vinden op Github, maar ik denk dat het het handigst is om uit te leggen hoe het allemaal werkt in een video.

Hieronder staat ook nog een selectie van een aantal van de vele bronnen die ik gebruikt heb gedurende dit project tot dusver. Dat is alles voor nu.

 

Tot de volgende keer!

Bronnen:

Een boom tegelijk

Hallo wereld,

Dit keer ga ik jullie wat uitleggen over decision trees oftewel beslissingsbomen. Want, zonder beslissingsbomen kan je geen random forest maken.

In mijn eerdere bericht over random forests had ik jullie al in grote lijnen uitgelegd hoe deze werken. Zoals ik al zei, decision trees leren data te categoriseren aan de hand van een model met knooppunten en vertakkingen. Bij elk knooppunt word een data punt aan een bepaalde test onderworpen om te beslissen naar welk volgende knooppunt de data gaat voor een volgende test. In het voorbeeld dat ik had gegeven kun je bijvoorbeeld een object hebben met de volgende eigenschappen: snelheid: 9001 km/u, lengte: 2m.

Als we willen weten wat dit is dan kunnen we het testen met onze beslissingsboom. Is de snelheid hoger dan 60 km/u? Ja. Dus is het geen vogel en moeten we de vraag stellen: Is de lengte langer dan 3m? Nee. Dus het is ook geen vliegtuig, het is Superman!

Maar, hoe maak je nou zo’n beslissingsboom? Nou, die in het voorbeeld heb ik gewoon helemaal zelf bedacht. Maar wat als je nou niet zo geweldig slim bent, of de data wat ingewikkelder is? Dan heb je een computer algoritme nodig dat de beslissingsboom voor je maakt op basis van gelabelde data.

Want, het is een supervised learning algoritme, weet je nog? Dat betekent in dit geval dus dat je het moet trainen door het gelabelde data te voeren. We zouden de bovenstaande beslissingsboom dus kunnen genereren door het algoritme een hele hoop datarijen met eigenschappen van vogels, vliegtuigen en superman te voeren. In dit geval data rijen met drie kolommen: snelheid, lengte en een label. Op basis van die data kan het computer algoritme dan een beslissingsboom berekenen die het label kan raden voor nieuwe datapunten.

Hoe goed die beslissingsboom is hangt echter af van de kwaliteit van de data. Zowel de relevantie als de juistheid van de data. Geef je het bijvoorbeeld alleen maar kleuren in plaats van snelheden en lengtes dan zal het het waarschijnlijk een stuk minder goed doen. Ook het verkeerd labelen van de data zal weinig goeds uithalen. En ook geldt vaak: hoe meer data, hoe beter!

Maar hoe werkt dat algoritme dan? Nou, het stappenplan is als volgt:

1. Bereken voor de gegeven dataset voor alle mogelijke criteria (alle mogelijke waardes voor alle variabelen)  de kwaliteit van de resulterende splijting van gegevens uit.

2. Kies het criterium uit dat de beste splijting oplevert.  (De splijting die de data zo goed mogelijk verdeeld in de gewenste categorieën.) Dit is het criterium voor het eerste knooppunt.

3. Herhaal voor de resulterende datasets totdat alle data compleet zuiver gespleten is in de gewenste categorieën. Dan zijn er dus alleen nog bladeren. (Of als de boom de maximum lengte bereikt heeft.)

Hoe wordt de kwaliteit van de splijting bepaalt? Nou hier zijn verschillende manieren voor. Een ervan is de Gini index. De Gini index is een statistische maatstaf voor de ongelijkheid binnen een verdeling. Hij wordt vooral in de economie gebruikt om de inkomensongelijkheid te berekenen, maar kan ook gebruikt worden om de kwaliteit van de splijting van onze dataset te bepalen. De Gini index is een getal dat een waarde heeft tussen 0 en 1. Een waarde van 0 komt overeen met volkomen gelijkheid, een waarde van 1 met volkomen ongelijkheid. In ons geval komt 0 overeen met een perfecte splijting en 1 overeen met een compleet waardeloze. In het geval van 2 categorieën zou een score van 1 betekenen dat we precies de helft van onze datapunten in de juiste en de andere helft in de onjuiste categorie zouden plaatsen. Daar schieten we dus niets mee op. Een score van 0 daarentegen zou betekenen dat we onze datapunten allemaal in aparte categorieën hebben geplaatst.

Met 3 categorieën, zoals in ons voorbeeld, wordt het iets ingewikkelder en hebben we al minimaal 2 knooppunten nodig om alle data te kunnen categoriseren. De eerste splijting kan namelijk nooit perfect zijn aangezien er 3 categorieën zijn en maar 2 mogelijke subsets. Ook is het lang niet altijd het geval dat we meteen een perfecte splijting vinden, ongeacht het aantal categorieën. We zijn dus bij elke splijting op zoek naar de laagst mogelijke gini index mogelijk en gaan gewoon net zo lang door totdat we de perfecte boom hebben (met een gini index van 0 in elk blad), of dat onze boom te groot wordt.

Een andere veelgebruikte is de information gain (informatie toename). De information gain is een maat voor de afname van entropie in een verzameling. De entropie is gelijk aan 0 voor een compleet homogene verzameling en 1 voor een evenredig verdeelde verzameling. Een toename van de information gain staat gelijk tot een afname van entropie. En dat betekent dus dat de verzameling puurder wordt, wat precies is wat we willen. We willen dat er alleen maar vogels in ons eerste blad terechtkomen, en geen vliegtuigen!

Nu zijn er natuurlijk ook formules voor deze getallen, en om die uit te leggen zou ik makkelijk een heel nieuw bericht kunnen schrijven. Ik ga dit echter voorlopig denk ik niet doen. Wil je weten hoe ze worden uitgerekend, Google is je vriend. Maar ik zal er natuurlijk ook een van gebruiken in mijn eigen implementatie van de random forest wijnproever, aangenomen dat dit gaat lukken. Ik ben er van overtuigd dat ik er uiteindelijk wel uit zal komen, maar hoe lang dit nog gaat duren is moeilijk te zeggen.

Het nadeel van deze beslissingsbomen is wel dat ze de neiging hebben om data te overfitten. Dat wil zeggen, ze leren de trainingsdata zo goed te classificeren dat ze het slecht doen voor nieuwe gegevens, die net wat anders is. Ze leren de oefentoetsen perfect uit hun hoofd, maar weten niet hoe ze andere sommen op moeten lossen. Een oplossing hiervoor is snoeien (pruning). Dat houdt in dat we er gewoon een aantal takken afhalen zodat de boom wat minder gefixeerd is op details. Maar een andere en betere oplossing is het bundelen van een aantal variaties van deze bomen in een random forest. Maar, dat is alles voor nu,

Tot de volgende keer.

Door de bomen het bos zien

Hallo wereld,

Wat zijn random forests? Hoe werken ze? Waar worden ze voor gebruikt? Nou, laat ik om dat uit te leggen eerst een stap terug doen en wat uit leggen over machine learning en decision trees. Random forests zijn namelijk machine learning algoritmes die zijn opgebouwd uit decision trees.

Machine learning is het subgebied binnen kunstmatige intelligentie dat zich bezig houdt met het bedenken en trainen van algoritmes die leren van gegevens. Het zijn programma’s met een aantal variabele parameters die zich aan passen aan een dataset om een zo effectief mogelijk eindprogramma te realiseren. Het is te vergelijken met de manier waarop wij leren. Op basis van de gebeurtenissen in ons verleden passen wij ons gedrag aan voor de gebeurtenissen in de toekomst.

Soms krijgen wij hier begeleiding bij, van ouders en leraren, die ons vertellen wat we wel of niet moeten of kunnen doen. Op andere momenten zoeken we het zelf uit, met vallen en opstaan. Zo is het ook met machine learning. Je hebt daarbij supervised (onder toezicht) en unsupervised (zonder toezicht) leren.

Decision trees (beslissingsbomen) vallen onder de supervised categorie. Wat houdt dit in? Nou, je moet het algoritme in principe les geven. Je geeft het een gelabelde dataset, dat wil zeggen een dataset met de gewenste antwoorden bijgevoegd. Bijvoorbeeld een verzameling van plaatjes van honden en katten met de labels hond of kat. Op basis daarvan kan het algoritme leren wat het verschil is tussen honden en katten en nieuwe plaatjes zelf leren categoriseren. Decision trees worden gebruikt voor classificatie en regressie. Bij classificatie wordt de data gecategoriseerd, net zoals bij het voorbeeld met honden en katten. Bij regressie wordt er een continue waarde aan toegedeeld. Bijvoorbeeld een algoritme dat de leeftijd van een mens of dier op basis van een foto bepaalt.

Decision trees leren data te categoriseren aan de hand van een model met knooppunten en vertakkingen. Bij elk knooppunt wordt een datapunt getest op een bepaalde variabele en op basis daarvan wordt bepaald naar welk volgende knooppunt het gaat voor de volgende test. Uiteindelijk komt het dan uit bij een eindknooppunt, een blad (leaf). Hierbij wordt het datapunt dan gelabeld binnen een een bepaalde klasse (of een continue waarde in het geval van regressie). Een voorbeeld?

Hierbij zijn de vierkanten dan dus de knooppunten, de lijntjes de takken en de rondjes de bladeren. Hoe bepaalt het algoritme wat de criteria zijn waar op getest wordt in de knooppunten? Brute kracht in principe. Bij elk knooppunt wordt voor elke variabele voor een groot aantal waarden getest tot wat voor split het zou zorgen in de dataset. Uiteindelijk wordt dan gewoon de split gekozen die de data het beste opsplitst. Dit proces wordt herhaald tot de gekozen eindcriteria bereikt worden (bijvoorbeeld de maximale lengte voor de boom).

Decision trees hebben echter de vervelende gewoonte om data te ‘overfitten’. Ze vormen zichzelf op een manier die heel nauwkeurig de trainingset kan modeleren, maar doen dit zo overdreven dat ze het slecht doen voor nieuwe gegevens. Ze leren de antwoorden in plaats van de patronen. Om dit te voorkomen kun je de decision trees ‘snoeien’. Dit houdt in dat je hem kleiner maakt zodat hij niet te gefocust raakt op de details. Maar er zijn ook andere oplossingen, en een daarvan is het random forest algoritme.

Een random forest is precies dat wat de naam al suggereert: een verzameling van random bomen, beslissingsbomen. Er wordt een verzameling van decision trees gegenereerd met random variaties in de trainingset en input variabelen. Deze decision trees krijgen dan elk een stem. In het geval van classificatie wordt het uiteindelijke antwoord bepaald door de meerderheid van die stemmen. In het geval van regressie wordt het gemiddelde genomen. Op deze manier wordt voorkomen dat het model overfit raakt, iets wat vooral een risico is voor trainingsets met veel variabelen en weinig datapunten. Random forests daarentegen kunnen daar over het algemeen uitstekend mee omgaan.

Dit en het feit dat ze over het algemeen vrij simpel te trainen zijn maakt ze erg populair. Ze doen het vooral goed voor classificatie maar zijn ook geschikt voor regressie. Ze worden gebruikt bij allerlei toepassingen op allerlei gebieden. Ze worden gebruikt door banken om kandidaten voor een lening te beoordelen. Ze worden gebruikt op de beurs om trends te voorspellen. Ze worden gebruikt in computer visie, bijvoorbeeld voor X-box connect. En nog veel meer.

En dat is het. Simpel nietwaar? Natuurlijk komt er wat meer bij kijken als je zo’n decision tree of random forest zelf wilt implementeren en trainen. Maar daarover later meer. Ik wil er namelijk eerst voor zorgen dat je het grote plaatje duidelijk hebt. Door de bomen het bos zien aldus. Bovendien heb ik de details zelf ook nog niet allemaal op een rijtje. Een boom tegelijk planten en zo. Maar, dat is alles voor nu.

Tot de volgende keer!

Project update: Random Forest Wijnproever

Hallo wereld,

Inmiddels ben ik begonnen aan de Random Forest Wijnproever. Ik heb de tutorial succesvol afgerond en een werkend model met behulp van de sklearn library gegenereerd.

Laat ik beginnen met uitleggen wat ik gedaan heb in deze tutorial. Alle code werd in deze tutorial gewoon aangereikt en het was in principe een kwestie van de uitleg lezen en de code gewoon overtypen. Desalniettemin is het toch een leerzame oefening zolang je de uitleg ook echt bestudeert en je best doet om de stappen te begrijpen. Het is echter best ingewikkelde theorie en als ik de Data Science Primer niet eerst bestudeerd had dan had ik er waarschijnlijk niet veel van gevolgd. Snap je dus niet waar ik het over heb, dan is het misschien een idee om daar eerst eens naar te kijken en/of naar de voorkennis die wordt aanbevolen in de tutorial. Mijn versie van de code kun je hier vinden. In tegenstelling tot in de voorbeeldcode heb ik twee afzonderlijke scripts gemaakt, een voor het genereren van het model (winesnob.py) en een voor het laden ervan nadat het is opgeslagen (winesnobloader.py). Hieronder zal ik uitleggen hoe het model gemaakt wordt.

Stap  3 en 4

Na het importeren van alle relevante libraries begint het met het laden van de dataset van een online locatie. Daarna wordt de dataset willekeurig gesplitst in een training set en een test set. Zoals de namen al suggereren, de trainingset is de subset van de data die gebruikt wordt om het model te trainen, en de testset de subset die gebruikt wordt om het model te testen. Het is belangrijk dat deze data gescheiden blijft, want anders leert het model geen patronen te ontdekken, maar gewoon de vaste antwoorden op de gegeven dataset. Het is te vergelijken met studenten laten studeren voor een proefwerk met het antwoordmodel. We willen niet dat het model leert alleen te presteren op de gegeven dataset maar op alle data. Om te kunnen testen hoe goed onze student de theorie heeft begrepen is het van belang dat we hem met vragen presenteren die hij/zij nog niet gezien heeft. Zo ook voor ons model.

Stap 5

Vervolgens is het de zaak om de data voor te bereiden. De data is namelijk nog niet geschikt voor het algoritme. Het moet nog gestandaardiseerd worden. Wat houdt dit in? Nou, dit is een concept binnen de statistiek. De korte versie is echter dat de data voor alle eigenschappen rond 0 wordt gecentreerd door het gemiddelde van die eigenschappen er af te halen. Daarnaast wordt het ook gedeeld door iets wat de standaarddeviatie heet, en dit zorgt ervoor dat de spreiding van de gegevens voor alle eigenschappen ongeveer hetzelfde is. Het resultaat van deze bewerkingen is dat alle eigenschappen even sterk meegenomen worden in het algoritme.

Stap 6, 7 en 8

Vervolgens is het tijd om het model te genereren en het vervolgens te trainen. Maar voordat we het model loslaten op de gehele trainingset is het eerst de zaak om de hyperparameters te bepalen. Dit zijn de parameters die bepalen HOE het model leert, niet WAT het leert. Om deze te kunnen bepalen wordt gebruikt gemaakt van een techniek die cross-validatie heet. Hierbij worden meerdere subsets van de trainingset gemaakt waarop modellen met verschillende hyperparameters worden losgelaten. Bij elk van die subsets wordt een kleine portie van de totale trainingset weggelaten bij het trainen van dit model en gebruikt voor het testen van dit model. Op deze manier blijft de echte testset dus onaangetast. Vervolgens worden de hyperparameters van het model met de beste prestatie uitgekozen. Deze hyperparameters worden dan gebruikt voor het model dat wordt losgelaten op de gehele trainingset. Deze laatste stap geeft slechts een kleine verbetering in prestatie ten opzichte van het model dat al losgelaten was op een iets kleinere portie van de trainingset, maar alle beetjes helpen.

Stap 9

Nu het model getraind is kan het getest worden op de testset. Hiervoor wordt het model gebruikt om de afhankelijke variabele te berekenen uit de onafhankelijke variabelen in de testset. Dit resultaat wordt dan vergeleken met de daadwerkelijke afhankelijke variabele die al gegeven was. De nauwkeurigheid van het model wordt dan weergegeven door de r2-score en mean-squared-error (mse) uit te rekenen.  De mean-squared-error spreekt voor zich, die wil je gewoon zo klein mogelijk hebben. De r2-score, ook wel determinatiecoëfficiënt (coefficient of determination) geeft aan hoe goed de “fit” is van het model. Bij een r2 van 1 is die “perfect”, maar van wat ik begrepen heb wil je tegelijkertijd ook voorkomen dat je model “overfit” is. Voor mijn model was de r2-score 0.46 en de mse 0.35, wat ongeveer overeen kwam met de waardes uit de tutorial. Wat dat precies betekent wordt niet echt uitgelegd, en heb ik ook nog niet uit kunnen vinden.

Stap 10

Nu hoeven we het model alleen nog op te slaan zodat we het met het andere script kunnen laden.

En klaar is Kees! Snap je het allemaal? Geloof het of niet, dat was het makkelijke gedeelte. Nu komt de echte uitdaging nog: mijn eigen Random Forest Algoritme schrijven. Ik ben hier namelijk al aan begonnen en ik zie nu al dat het een flinke uitdaging gaat worden. Al is het alleen maar het uitvogelen van Python. Ook zou het wel interessant zijn om de code aan te passen zodat het scores kan geven voor individuele gevallen. In hoeverre dit alles gaat lukken durf ik niet te zeggen, maar ik zal mijn best gaan doen. Dat is alles voor nu.

Tot de volgende keer!

 

Projectaankondiging: Random Forest Wijnproever

Hallo wereld,

Een tijd geleden gaf ik al aan dat ik een nieuw idee had voor een project.  Ik had het idee om een simulatie te programmeren, data te genereren en een programma te schrijven om die data te analyseren. Echter, dit idee gaat voorlopig niet door. Waarom niet? Nou het was me nog niet echt duidelijk hoe deze programma’s er precies uit zouden komen te zien. En hoe meer ik hierover nadacht, hoe meer ik me realiseerde dat ik me eigenlijk eerst ergens anders op wilde focussen. Namelijk, het bestuderen, toepassen en zelf programmeren van machine learning algoritmes. Aldus koos ik voor het volgende project.

Ik ga een tutorial volgen voor het schrijven van een machine learning applicatie in Python die wijnkwaliteit leert beoordelen. Een tutorial op EliteDataScience, een website die mensen de leermiddelen aanreikt om een data wetenschapper te worden. Nu vindt ik dat reuze interessant, maar het is op het moment niet mijn bedoeling om een data wetenschapper te worden, maar een programmeur van datasystemen. En met deze tutorial leer ik onder andere hoe ik de data science libraries van Python kan gebruiken om data te analyseren. En ik heb al wat geleerd op deze site over wat er allemaal komt kijken bij het uitvoeren van een goede data analyse, maar ik wil een stapje verder gaan. Ik wil ZELF het algoritme programmeren dat de data analyseert, in plaats van alleen de kant en klare versie in de gebruikte Python library te leren toepassen. En dat is dan ook het echte project: mijn eigen algoritme programmeren.

Misschien dat je je afvraagt wat het nut hier van is. Immers, waarom zou ik iets programmeren waar al een library voor is? Nou, het antwoord daarop is natuurlijk dat ik wil leren hoe het het algoritme werkt. Ik wil het zo goed leren begrijpen dat ik het zelf kan programmeren.

Bovendien zal ik hiermee ook mijn programmeervaardigheden over het algemeen verbeteren. En ja, ik ga dat doen met Python. Een taal waar ik tot nu toe slechts een klein beetje ervaring mee heb opgedaan met het maken van Conway’s Game of Life. Dat is het eerste en enige programma dat ik tot nu toe met Python heb gemaakt. Dus ook dat zal leerzaam zijn.

Eerst volg ik de tutorial en voer ik de data analyse uit met de methode uit de library. In de tutorial leer je om een programma te schrijven dat leert om een cijfer voor de wijnkwaliteit te berekenen op basis van een lijst van eigenschappen. Het leert om dit te doen op basis van een set trainingsdata. Het doet dit met een random forest algoritme uit de Scikit-Learn library. Daarna schrijf ik mijn eigen random forest algoritme, voer de analyse daarmee opnieuw uit, en vergelijk de resultaten. Het random forest algoritme is een regressie algoritme: het leert om een variabele te berekenen op basis van een aantal inputvariabelen. En zegt dit je niet niets, bekijk dan eventueel ook mijn post over datamining waarin ik onder andere kort uitleg wat regressie is. En wat het random forest algoritme betreft, daarover en ook over regressie zal ik meer uitleggen in de loop dit project. Wil je nu al meer weten hierover, kijk dan misschien eens naar H5 van de Data Science Primer op EliteDataScience. Daar wordt het heel duidelijk uitgelegd. Dat is alles voor nu.

Tot de volgende keer!

StudentApp klaar voor nu

Hallo wereld!

Ik heb nog een aantal laatste aanpassingen gemaakt aan het studenten datasysteem. Dit zullen waarschijnlijk de laatste aanpassingen zijn die ik voorlopig zal maken. In plaats daarvan ga ik verder met nieuwe projecten, waarvan ik al wat gezegd had in mijn mededeling van vorige week.

Ten eerste heb ik de code een beetje gereorganiseerd. In JavaFX maakt men gebruik van wat men noemt Scenes om de windows te vullen met alle interface componenten. Tot nu toe had ik al deze Scenes in een method gepropt. Het resultaat? Een lange onoverzichtelijke rij van code met allerlei interface componenten die allemaal naamconflicten oproepen die constant moeten worden opgelost. Nu heb ik elke Scene laten genereren in een aparte method per stuk. Het resultaat? Een lange onoverzichtelijke rij van methods die in ieder geval geen naamconflicten meer veroorzaken. Na al het scrollen en programmeren en tijdens het schrijven van dit bericht kwam ik er echter weer achter dat je die lange onoverzichtelijke rijen code in Netbeans ook kon inklappen door op het minteken ernaast te klikken. Zucht…

Bovendien bleek het ook handig te zijn om Scenes te laten genereren in de functionaliteit van andere Scenes, door die methodes op deze plekken in te voeren. Bijvoorbeeld om de naam van de ingelogde student aan te passen tijdens het inloggen zelf. Waarschijnlijk kan het nog steeds allemaal veel beter, maar JavaFX was nog steeds onwennig voor mij en dit is de beste oplossing die ik voor nu kon vinden.

Ook heb ik de mogelijkheid om de save folder te wijzigen toegevoegd. Zoals ik al zei is dat veel professioneler. Niet alleen kun je hem nu wijzigen, het is nu ook niet meer zo dat hij automatisch wordt gemaakt in je C directory. In plaats daarvan wordt automatisch de folder geselecteerd waarin je de jar-file hebt opgeslagen voor opslag. Wees echter gewaarschuwd, als je hem in je IDE runt dan wordt automatisch de build folder geselecteerd, en die is niet geschikt voor permanente opslag. Zorg er dan in dit geval dus voor dat je de folder dan ook wijzigt met de handige functionaliteit die ik heb toegevoegd! Wil je niet dat de informatie direct in je geselecteerde folder wordt opgeslagen maar een nieuwe folder aanmaken? Dat kan ook. Type gewoon de naam van de folder die je wilt maken achter het bestandspad en de folder wordt automatisch aangemaakt.

Daarnaast heb ik ook een simpele zoekfunctie toegevoegd. Niets bijzonders, maar wat heb je aan een database waarin je niet kan zoeken? In mijn database staan dan misschien maar slechts een paar elementen, maar in een echte toepassing zouden er al snel honderden tot duizenden rijen in staan. De droom dat deze database een echte toepassing zou worden heb ik voorlopig echter even uitgesteld. Voor nu is het dan ook alleen maar mogelijk om op ID-nummer te zoeken. Meer als proof-of-concept dan als handige functionaliteit dus.

Tot slot heb ik ook een simpele cirkeldiagram scene toegevoegd die de verdeling van de studenten over de verschillende studiejaren toont. Om deze functioneel te maken heb ik dan de beschikbare jaarkeuzes beperkt tot 1 tot en met 5. Deze scene is mijn poging om een beetje data analyse aan het data opslag systeem toe te voegen. Want data analyse is natuurlijk veel leuker dan data opslag!

En dat is het! De code is te vinden op https://github.com/SamsonCodes/StudentenData/tree/evenmorechanges. Het is tijd voor een nieuw project. Wat voor project? Nou, dat vertel ik jullie volgende week natuurlijk.

Tot de volgende keer!

 

StudentApp ontwikkelt zich verder

Hallo wereld. Opnieuw een vooruitgangsrapport over het studenten data systeem, of StudentApp. Kort voor applicatie, niet te verwarren met de Android variant.

Inmiddels is het programma een stuk gevorderd sinds de vorige post. Een van de belangrijkste aanvullingen is die van een save systeem. Want, wat heb je aan een database die elke keer als je hem sluit alles vergeet wat je hebt gedaan? Vrij weinig. De informatie wordt opgeslagen in een map in C:\StudentenDataManager. Natuurlijk is dit niet de meest professionele oplossing en zou het beter zijn als de gebruiker zelf een map kan aanwijzen, maar voor nu werkt dit prima. De gegevens worden opgeslagen in een zelf bedacht XML-format en kunnen vervolgens door de code weer gebruikt worden om de objecten opnieuw aan te maken.

studenten data in XML-format

Ook wordt er nu bij het inloggen gekeken naar het wachtwoord. Voor nu laat ik dit wachtwoord echter standaard ingevuld zijn bij het opstarten zodat ik het niet steeds opnieuw hoef te typen. Het is voor nu dan ook voor elke gebruiker hetzelfde. Wat is het wachtwoord? Het wachtwoord is “dataridder” natuurlijk, wat anders?

Hoe kun je dit wachtwoord nou niet goed krijgen?

De studenten kunnen nu dan dus ook inloggen op hun persoonlijke account via hun studentennummer en zich in- en uitschrijven voor vakken. Ook kan de administrator nu studenten verwijderen in plaats van alleen toevoegen en zijn er meer gegevens om in te vullen. De studentengegevens en de inschrijfgegevens worden nu ook weergegeven in een TableView. Een JavaFX component dat gegevens presenteert in een tabel. Had je nooit geraden, of wel?

Schrijf je in voor plezier!
Voeg al je vrienden toe aan het systeem!

TableView was iets complexer dan de andere interface componenten van JavaFX om te leren gebruiken. Er is een enorme hoeveelheid aan opties en er is makkelijk een klein boek vol aan uitleg en documentatie over te vinden. Tegelijkertijd is het echter ook niet al te moeilijk om uit te vogelen zo lang je je maar richt op de informatie die je nodig hebt om te beginnen en je niet laat afschrikken of afleiden door de rest. Dat is een algemeen advies, maar wat TableView betreft, zorg eerst dat je een tabel op je interface hebt zonder je druk te maken over functionaliteit en maak dan een ObservableList van de gegevens waar je hem mee wilt vullen. ObservableList klinkt ingewikkeld maar is in principe niets anders dan een ArrayList voor in een tabel. Zorg ervoor dat de kolommen de juiste data presenteren en vergeet niet om alle data daadwerkelijk zowel aan de ObservableList toe te voegen als de list aan de tabel toe te voegen. En klaar is kees!

Dat zijn de belangrijkste aanvullingen tot nu toe. De code is te vinden op https://github.com/SamsonCodes/StudentenData/tree/morechanges. Dat is alles voor nu. Tot de volgende keer.

Vooruitgangsrapport Studenten Datasysteem

Hallo wereld. Ik ben inmiddels begonnen aan het programmeren van mijn studenten datasysteem. En hoewel ik nog niet al te ver ben gekomen is de eerste opzet er al wel. Het was lastiger dan ik van te voren had gedacht om met JavaFX te werken. Ik was veel tijd kwijt aan het zoeken naar een opzet met de interface en een soort game-loop in afzonderlijke threads. Ik had eerst dan ook deze loop in de main thread en wilde de JavaFX applicatie in een afzonderlijke class en thread doen maar dat gaf een hoop foutmeldingen die ik niet wist op te lossen. Dus heb ik het uiteindelijk maar omgedraaid en heb ik de JavaFX applicatie als main class genomen en ben ik van plan geen game-loop meer te gebruiken, maar alle achtergrond activiteit te laten activeren als respons op de user input.

Tot nu toe heb ik een simpel inlogscherm, een invoerscherm voor het invoeren van studenten en een titelscherm voor het aanmelden voor vakken voor studenten. Voor nu wordt bij het inlogscherm alleen de naam als input gecontroleerd. De naam Admin laat je inloggen in het invoerscherm, en een ‘s’ gevolgd door het id nummer, bijvoorbeeld s10000 (het eerste nummer dat gebruikt wordt), laat je als student inloggen mits je in het systeem staat. In beide schermen kun je ook uitloggen en terug naar het inlogscherm gaan. Hieronder zijn wat screenshots van de applicatie zoals hij er nu uitziet. Zie https://github.com/SamsonCodes/StudentenData voor de code. Dat is alles voor nu. Tot de volgende keer!

Inlogscherm
Log in als admin
Ingelogd als admin
Student toegevoegd
Log in als student s10000
Ingelogd als student