V. Multi-layer Perceptron & Backpropagation
A. Inleiding
Perceptrons zijn netwerkjes met twee lagen, een
inputlaag en een outputlaag, die in staat zijn zo ongeveer elke 'mapping' van
inputs op outputs te leren. 'Ongeveer', want zoals je ongetwijfeld al
etterlijke malen gehoord hebt toonden Minsky & Papert in 1969 aan dat
bepaalde mappings, bijv. XOR, niet te leren zijn door Perceptrons.
De meerlagige perceptron of MLP was een antwoord op
hun boek. De MLP kan, in combinatie met het krachtige error-backpropagation
leeralgoritme, wel die problematische 'mappings' leren. 'Backprop'-netwerken,
zoals MLP's met backpropagation meestal worden aangeduid, werden meteen na hun
ontstaan dan ook uiterst populair. Ze bleken in staat te zijn de meest
verschillende taken te leren uitvoeren, zoals het vinden van de juiste
uitspraak gegeven de spelling, of het produceren van de verleden tijd van Engelse
werkwoorden, het herkennen van onderzeemijnen of het afhandelen van
bagagestromen op vliegvelden. De laatste tijd is deze populariteit overigens
aan het afkalven: er zijn krachtige statistische methoden die net zo goed maar
efficiënter de typische backprop-taken aankunnen. Bovendien zijn de
statistische methoden inzichtelijker dan backprop netwerken, die vaak als black
box gebruikt worden: je stopt er iets in en er komt iets uit, zonder dat je
hoeft te begrijpen wat er precies gebeurt. Als model voor het functioneren van
de hersenen is de populariteit van het backprop netwerk ook tanende. Steeds
meer mensen binnen de connectionistische gemeenschap vinden het problematisch
dat backpropagation biologisch gezien weinig plausibel is.
In deze opdracht introduceren we backprop, en laten
we je een dataset met een backprop netwerk aanpakken.
B. Het trainen van een 'backprop' netwerk
Stap 1: de dataset
Voor dit practicum hebben we vier datasets
voorbereid, met heel uiteenlopende onderwerpen. Een dataset kan van alles zijn,
het kunnen klanten aantallen per kassa zijn of schoenmaten of misdaadcijfers of
taalconstructies. Al deze informatie moet worden omgezet in iets waar een
neuraal netwerk iets mee kan; meestal houdt dit een proces in van schonen en
schalen en voorbewerken in dat bij werkelijke toepassingen, zoals het
voorspellen van aardbevingen of beurskoersen, een enorme klus kan zijn. De
dataset moet bestaan uit een aantal inputvariabelen en één of meer
outputvariabelen, waarbij de inputvariabelen gebruikt kunnen worden voor het
voorspellen van de output. Bij één van onze datasets kan je bijvoorbeeld
demografische variabelen (leeftijd, geslacht, opleiding) gebruiken om salaris
te berekenen. De inputvariabelen vormen het inputpatroon, de outputvariabelen
het outputpatroon, en de combinatie een van input- en outputpatroon wordt aan
het netwerk aangeboden.
Stap 2: leren
Het leren in een backprop-simulatie is meestal het
heel vaak -duizenden keren- aanbieden van de input- en outputcombinaties uit de
dataset. Het netwerk past tijdens het leren zijn gewichten aan tot het de set
kan voorspellen.
Het backpropagation-algoritme bestaat uit twee delen
(lees ook de uitleg in B. & A., hfdst. 3):
1. Een voorwaartse berekening waarbij de
activatiewaarden van de elke laag uit de activatie van de vorige laag wordt
berekend (in het Nutshell-backpropparadigma heet dit 'Upsweep').
2. Een terugwaartse berekening waarin verschil
tussen het gewenste outputpatroon en de werkelijke patroon in de uitvoerlaag
wordt berekend (de 'fout'), en vervolgens naar de vorige lagen terug wordt
berekend (in het paradigma heet dit 'Downsweep').
Vervolgens worden de gewichten in het hele netwerk
veranderd m.b.v. de delta-leerregel op basis van dit verschil: het netwerk
wordt zo aangepast dat het bij een volgende iteratie een kleinere fout zou
opleveren. Het netwerk leert ze de gewenste output voorspellen op basis van de
ingekomen input. Statistisch is dit overigens equivalent aan niet-lineaire
regressie (perceptrons doen lineaire regressie).
Leren in Backprop gaat meestal langzaam, met heel
kleine stapjes. Dit is omdat bij grotere veranderingen het netwerk vaak
instabiel wordt: in plaats van dat de gewichten naar een stabiele toestand
convergeren schieten ze wild heen en weer en leert het netwerk nooit goed voorspellen.
De leersnelheid wordt bepaald door de leerparameter eta (vaak wordt als symbool de griekse letter mu gebruikt
voor de leerparameter).
Stap 3: testen
In de testfase wordt het inputpatroon aangeboden, en
wordt er enkel gekeken in hoeverre de door het netwerk gegenereerde output
overeen komt met de bedoelde output. Meestal worden niet alleen al geleerde
patronen getest, maar wordt er ook een deel van de dataset achter gehouden voor
verificatiedoeleinden: met deze, niet geleerde patronen test je of het netwerk
goed kan generaliseren.
C. Opdracht 3: backprop
In zowel opdracht 3.1 als 3.2 is het de bedoeling om
een dataset aan te leren. Om te zorgen dat niet iedereen hetzelfde hoeft te
doen hebben we 4 datasets van het Net gehaald - echte data, overigens.
Open het bestand "opdr3 datasets"; op elke sheet
staat een andere dataset. Dataset 1 bestaat uit hier verzamelde data over een
steekproef ouderen waarvan wordt vermoed dat er risico voor dementie bestaat;
voor elke oudere zijn er uitslagen op een aantal geheugentests, samen met
demografische variabelen en de scores op een dementietest en een
depressievragenlijst. Dataset 2 geeft voor een aantal personen een stel
demografische gegevens (geslacht, opleiding, functiesoort…) en hun salaris.
Voor de hardcore determinist: dataset 3 geeft informatie over IQ en
breingrootte van 12 tweelingen=24 tweelinghelften. Dataset 4 geeft voor een
aantal Nederlandse gemeenten de score van de belangrijkste partijen bij de
verkiezingen van 1998. De eerste set komt van Paulien Spaan (waarvoor dank), de
volgende twee zijn gedownload van de site: http://www.stat.cmu.edu/datasets/,
en de laatste is een bewerking van data van het Centraal Bureau voor de
Statistiek [2].
Kies een dataset. Bepaal in deze dataset welke
variabelen de inputvariabelen worden, en welke de outputvariabelen. Als je
bijvoorbeeld dataset 4 kiest, kan je bijvoorbeeld proberen de score van de
grote partijen (PvdA, VVD, CDA) te voorspellen uit de score van de kleine
partijen. Kies minstens 4 inputvariabele en minstens 1, maar liever meer,
outputvariabelen. Denk eraan: zowel input- als outputvariabelen moeten cijfers
zijn, dus kies bij set 4 bijvoorbeeld niet de gemeentenaam als variabele. Regel
3 van de sheets is de regel waarin je moet aangeven wat de input- en wat de
outputvariabelen zijn. Zet boven elke inputvariabele een kleine "i", boven elke
outputvariabele een kleine "o" (o, niet O of 0).
Open bestand "Backpropscripts". Open de Visual
Basic-code. Er zijn drie modules, oftewel codewindows. De code voor het inlezen
van de dataset en het wegschrijven van de data staat in een aparte module voor
de overzichtelijkheid. Open deze module en kijk even of je kunt snappen wat de
code hierin allemaal gaat doen.
Klik terug naar Excel. Open weer het bestand "opdr3
datasets", en zorg dat de dataset die
jullie willen gebruiken degene is die 'actief' is (d.w.z., degene die
geheel zichtbaar is). Als je dat niet doet krijg je een foutmelding bij de regel:
ReDim learnPats(nrLearnPats - 1, nrInputs + nrOutputs - 1)
Sla, na het actief maken van je datasheet, tegelijk de toetsen
"Alt" en "F8" aan; dit zorgt ervoor dat je een lijstje te zien krijgt met
scripten die je kunt runnen. Selecteer "datavoorbereiden", en klik op 'run'.
Dit zorgt ervoor dat er verschillende gegevens op je datasheet terecht komen.
op de bovenste regel komen achtereenvolgens: het aantal variabelen (cel D1),
het aantal 'cases' - oftewel het aantal patronen (cel E1), het aantal
inputvariabelen dat jullie hebben aangegeven (cel F1) en het aantal
outputvariabelen (cel G1).Op de derde regel komt een schalingsfactor te staan.
Deze is gelijk aan de maximum waarde op de variabele. Alle waarden worden
gedeeld door deze schalingsfactor, zodat geen enkele boven de 1 uit komt. Dit
versnelt het leren: anders is het netwerk eerst eindeloos bezig met het schalen
van de gewichten zo dat elke variabele ongeveer evenveel invloed heeft.
Het databestand is nu klaar voor de opdracht. In
beide opdrachten zal het databestand ingelezen worden, en automatisch opgedeeld
worden in een leerset van ¾ van alle 'cases' ('leerpatronen') en een testset
van ¼ van de cases, waarmee generalisatie wordt getest ('testpatronen'). De
leerset wordt geleerd met door jou aangegeven parameters, en vervolgens wordt
het netwerk getest.
3.1 Perceptron.
Open de module "Perceptron" in het bestand
"Backpropscripts". In deze module staat het raamwerk van een simulatie waarin
een tweelagig netwerk je dataset aan gaat leren. Het is overigens niet echt een
perceptron waar je in deze opdracht mee werkt. Een tweelagig backprop-netwerk
-wat je in feite hier bouwt- is niet gelijk aan een perceptron, maar werkt in
essentie hetzelfde.
Het meeste werk aan de simulatie is gedaan -de
procedures zijn geschreven die de data inlezen, het leren uitvoeren, het
netwerk testen. Wat ontbreekt is het netwerk zelf.
a) schrijf een stukje code op de aangewezen
plaats (zie commentaar in de macro) dat een netwerk aanmaakt met twee lagen. De
ene laag (de inputlaag) moet een aantal knopen hebben dat overeenkomt met het
aantal dat je in je dataset hebt gemarkeerd als inputvariabelen. De andere laag
(outputlaag) moet een aantal knopen hebben gelijk aan het aantal
outputvariabelen. Zorg dat de eerste laag, die met nummer '0', de inputlaag is,
en de tweede laag, die met nummer '1', de outputlaag. Kijk naar appendix 1 en
de bestanden uit opdracht 2 om te zien hoe alles moet.
b) Stel de twee belangrijkste variabelen bij
het leren in: het aantal leerepisodes (LearnEpochs) en de leersnelheid
('learning rate'). Begin met een kleine waarde voor de leersnelheid en een
grote voor het aantal episodes. Er is een derde constante, het aantal tests dat
het model doet - geef deze constante de waarde 4. De simulatie doet een test om
de zoveel leerepisodes; als je 200 leerepisodes opgeeft en 4 testen zal hij een
test uitvoeren elke 200 / 4 = 50 leerepisodes (overigens doet hij automatisch
een test aan het begin, voor er sprake is van leren, zodat je een vergelijking
hebt). Zo kan je de voortgang van het leren zien, en hoef je niet voor elk
aantal leerepisodes een nieuwe test te doen. De resultaten van elke test worden
in een excel-workbook op steeds een nieuwe worksheet gezet. Zorg wel dat het
aantal leerepisodes deelbaar is door het aantal testen (als je niets aan het
aantal testen verandert: deelbaar door 4).
Run het script "Perceptron". Hiervoor moet je wel
het bestand "opdr3 datasets" open hebben, en de sheet met jouw dataset als de
actieve 'bovenaan' hebben. Als het goed is wordt er nu een workbook aangemaakt
met daarop de uitvoer van de simulatie. Bekijk hoe goed het model het heeft
gedaan. Zie je vooruitgang van de ene test naar de volgende? Gaan de
testpatronen (zie boven) even veel vooruit als de geleerde patronen?
c) Varieer de leersnelheid en het aantal
leerepisodes net zo lang tot je het volgende kunt beantwoorden:
- Welke combinatie is optimaal?
- Wat is de invloed van de leersnelheid?
- Wat is de invloed van het aantal leerepisodes?
Wat is de procedure die je gevolgd hebt om dit uit
te zoeken?
d) Als je netwerk een staat heeft bereikt
waarin de output goed wordt voorspeld, kijk naar de gewichten tussen de
input-en de outputknopen. Beantwoord voor elke outputvariabele de volgende
vraag: welke inputvariabele voorspelt de outputvariabele het best? (Hint: de
knopen in de inputlaag hebben dezelfde volgorde als de inputvariabelen in je
datafile).
Als je netwerk zo'n staat nooit bereikt en de output
knudde blijft voorspellen, beantwoord de bovenstaande vraag niet maar probeer
te bedenken waarom het voorspellen niet wil lukken.
e) Sommige patronen blijven het een stuk
slechter doen dan anderen. Probeer dit te verklaren.
3.2. Backprop
In deze opdracht moet je een drielagig netwerk
loslaten op je data. Gebruik precies dezelfde dataset als in 3.1, met precies
dezelfde mapping. Open de module "Backprop"
a) Maak, zoals je dat in opdracht 3.1 deed met
twee lagen, een drielagig netwerk aan. Zorg dat dezelfde variabelen naar de
input- en outputlagen verwijzen als in opdracht 3.1. Zorg ervoor dat de
variabele "hiddenlayer" verwijst naar de "hidden layer". Het aantal knopen in
de "hidden layer" moet je straks gaan variëren. Maak ook de juiste verbindingen
("Tracts") aan. Je kunt degene kopiëren uit opdracht 3.1, maar i.p.v. een tract
van de input- naar de outputlaag heb je tracts nodig van de input- naar de
verborgen laag, en van de verborgen laag naar de outputlaag (let op: in
overeenstemming met connectionistische conventies komt de doellaag van de tract
eerst in het commando, en dan pas de bronlaag). Controleer of het netwerk goed
wordt aangemaakt met behulp van een 'breakpoint'.
Een "breakpoint" onderbreekt een programma zodat je kunt zien wat er tot dan
toe allemaal gebeurd is. Een manier om een breakpoint te zetten is door de cursor
te plaatsen op de regel waar je je programma wilt onderbreken, en dan onder het
menu "Debug" "Toggle breakpoint" te klikken (zet hem hier bijv. net na de code
voor het aanmaken van je netwerk). Je kunt een break point niet zetten op een lege
regel of eentje die begin met "Dim" of "ReDim", of enkel commentaar bevat. Zet de
breakpoint in de eerstvolgende regel waar het wel kan, en run je code op de normale
manier. Het programma zal nu stoppen bij de "break point". Je kunt nu naar Nutshell
klikken en kijken hoe het netwerk eruit ziet. Om weer verder te kunnen met programmeren
moet je in "Visual Basic" op de "reset"-knop drukken (blauw vierkant), of de 'reset'-optie
aanklikken onder het "run"-menu. Breakpoints zijn een handig middel om te kijken of je
programma doet wat het moet doen.
b) Je hebt nu drie variabelen om mee te
variëren: de leersnelheid, het aantal leerepisodes, en het aantal "hidden
units" - het aantal knopen in de verborgen laag. Stel de leersnelheid laag in
en het aantal leerepisodes hoog, en vergelijk in ieder geval de volgende drie
simulaties: met 1 "hidden unit", met een aantal "hidden units" dat twee keer zo
groot is als het aantal outputknopen, en 100 "hidden units". Wat is het effect
van het aantal "hidden units"?
c) Zoek weer naar een optimale instelling van
de drie variabelen. Kan het netwerk goed voorspellen? Is het drielagig netwerk
beter, sneller en/of efficienter dan het tweelagig netwerk? Vergelijk de twee
netwerken; welke bevalt je beter en waarom?
!!!!! DENK AAN DE DEADLINE !!!!!
[2]
Mocht je overigens met een andere dataset aan de slag willen,
dan mag dat. Maak binnen "opdr3 datasets" een nieuwe sheet aan,
en zet je dataset erop in hetzelfde formaat als de andere sets:
met de verschillende variabelen in verschillende kolommen, de
data vanaf cel B5 naar rechts en onder, etc. Je kunt de
opdrachten verder gewoon afwerken.
|