Courses  

III.     Werken met Nutshell

Tot voor kort schreven alle connectionisten hun eigen simulatieprogramma's, met eigen algorithmes, eigen opties, eigen leerregels, outputmodules, patrooninlezers, etc. Iedereen kon zo zijn code aan de eigen wensen aanpassen, maar het resultaat was wel dat het wiel telkens opnieuw uitgevonden werd. Sinds enige jaren komen er standaardsimuleeromgevingen beschikbaar. Idealiter maken die het mogelijk om zonder eerst maanden te programmeren meteen simulaties te kunnen doen, zonder de flexibiliteit aan te tasten die de gevorderde gebruiker nodig heeft. Nutshell is zo'n simuleeromgeving. Er is één buitenkant waarmee je veel verschillende connectionistische paradigma's (=soorten netwerken) kunt simuleren. Aangezien Nutshell toevallig ontwikkeld werd aan de UvA [1] (en ook nog eens heel goed is) zullen we dit programma gebruiken in het practicum.

A. Werken met de omgeving

Om je te laten wennen aan Nutshell zullen we eerst een aantal simpele stappen doen. We gebruiken hierbij het Hopfield paradigma dat ook in de eerstvolgende opdracht zal worden gebruikt. Je start Nutshell op door in je startknop Nutshell aan te klikken (staat onder 'Programs' en dan 'Nutshell 1.0'). De nutshell-applicatie start nu op. Je kan uit verschillende paradigma's kiezen. Een paradigma is in connectionisme een bepaalde manier waarop netwerken werken - een definitie van hoe leren gaat, hoe knopen ge-update worden, wat je allemaal met lagen kunt doen, etc. Hopfield is zo'n paradigma. Kies "Hopfield.np".

Opmaak van de nutshell-omgeving

Je ziet nu een lege 'workspace' (een groot leeg venster waarin je een model kunt bouwen), en verschillende werkbalken met tal van functies. Onder de Help-functie (in de menu's bovenin) staat de op het moment nog vrij beperkte, helpinformatie van nutshell, en verder een Hopfield tutorial. Hierin staan een wat uitgebreidere beschrijving van een aantal functies. Belangrijk is ook het 'Edit'-menu, te herkennen aan de muispointer met daarnaast een loep waar je mee in en uit kan zoomen. Als 'default' is de muispointer geselecteerd. Verder belangrijk: het "General"-menu links waarin allefuncties staan opgesomd. Als je een klein venster hebt dan kan je de onderkant van het "General"-menu niet zien. Dat is niet problematisch: alles in het "General"-menu staat ook onder "Parameter" in de menubalk boven. Mocht je dus dingen niet kunnen zien in het "General"-menu omdat het niet op je scherm past, kijk dan onder "Parameter".

Links onderin nutshell zit het 'console'-venster, en rechts onderin het outputvenster. Je kunt de console gebruiken om scripting-commando's (zie sectie B) één voor één in te voeren en het outputvenster om variabelen of andere informatie te zetten, maar beide vensters gaan we niet veel gebruiken in deze cursus.

Een Hopfieldnetwerk bestaat uit knopen die zich in een 'laag' (layer) bevinden. Maak een laag aan door simpelweg op "insert layer" te klikken. Je mag aangeven welke dimensies de laag gaat krijgen; standaard is 10 bij 10. Klik op "OK". Je ziet nu vierkant van knopen (de laag) met willekeurig geïnitialiseerde activaties.

Variabelen bekijken

Je kunt de waarde van de activatie -en van andere parameters- bekijken door een knoop te selecteren (1 keer erop klikken met de linkermuisknop) en dan op de rechtermuisknop te drukken. Er verschijnt nu een menu. Zet de muis op het veldje met 'Node' en het knoopnummer, en klik op het verschijnende veldje met 'parameters'. Kijk wat het verschil is tussen rode en zwarte knopen. Je kunt nu ook een knoop van rood naar zwart veranderen, door de waarde van de goede parameter te veranderen en op "OK" te drukken.

Er zijn algemene parameters, parameters die bij knopen horen, parameters die bij lagen horen, bij verbindingen, en bij 'tracts' (bundels verbindingen van 1 laag naar zichzelf of een andere laag). Links in het 'General'-menu is een optie 'Parameters'. Als je daarop klikt kan je de algemene parameters bekijken. 'Laag'-parameters kan je inkijken door een laag aan te wijzen door er op te klikken, dan weer de rechtermuisknop in te drukken, en onder de "Layer"-optie te kijken. Daar zal je weinig aantreffen: 'Hopfield' is een paradigma met weinig parameters (er is bijvoorbeeld geen enkele 'tract'-parameter). Andere paradigma's hebben hele lijsten parameters.

De laag verbinden, patronen tekenen

De knopen zijn nog niet met elkaar verbonden. Dit doe je door op het bovenste deel van de laag (het witte) te klikken om hem te selecteren, en dan links in het menu op "Insert Tract" te klikken. Er verschijnt een ronde pijl rechtsboven de laag. Dit is de 'tract' met de verbindingen van de laag naar zichzelf. Het netwerk is nu intern volledig verbonden.

De waarden van de knopen kun je instellen door de functie van de muispointer in het editmenu in "set value" te veranderen. Deze functie staat meest rechts (half gevuld vierkantje). Nu kun je met je linker muisknop de ene uiterste waarde selecteren en met je rechter muisknop de andere. Deze waarden stel je in door op het pijltje rechts van het half gevulde vierkantje te klikken. Kies "custom value". Zorg dat de waardes gelijk zijn aan de twee mogelijke activatiewaardes in het Hopfield-paradigma: "set" moet +1 zijn, en "clear" -1.

Als je nu op een rode knoop klikt zal hij zwart worden ('set'-waarde). Je kunt de hele laag of een deel van de laag tegelijk de 'set'-waarde geven door het 'vlakje trekken'. Zet de muispunt buiten de laag (maar in de buurt), houd de linkermuisknop ingedrukt en schuif de muispunt over een deel van de laag. In het getrokken vierkantje krijgen nu alle knopen de 'set'-waarde. Je kunt de 'clear'-waarde aan knopen geven door de shift knop ingedrukt te houden en of op een knoop te klikken, of weer een vlak te trekken om een te veranderen deel van de laag.

Als het je gelukt is de activatie-waarden onder controle te krijgen dan kun je proberen een patroon in de laag te tekenen.

Leren in het netwerk, bekijken van gewichten

Door middel van "Learn" in het linker menu wordt dit patroon geleerd. Druk op "Learn".

Je kunt op twee manieren controleren of de connecties ook daadwerkelijk veranderd zijn. Je kunt de connecties bekijken. Dat doe je door boven in het scherm bij View naar de optie connection te gaan. De eerste keer dat je dit doet zie je misschien alleen maar grijze vierkantjes met kruisjes erin. Dan moet je even de functie van de muispointer veranderen in het simpele pijltje. Als je nu op een neuron in de laag klikt zie je de waarde van de verbindingen met andere neurons als kleuring van deze neurons. Een nader onderzoek is mogelijk als volgt. Klik op een neuron naar keuze. Klik op een ander neuron naar keuze maar houd daarbij de shift toets ingedrukt. Als je nu de rechtermuisknop indrukt krijg je in het menu de optie "weight(nodenummer, nodenummer)" erbij. Als je deze optie aanklikt zie je de waarde die de verbinding heeft aangenomen.

Activatie updaten, iteraties

In het simpele geval van een geleerd patroon is het makkelijk aan te tonen dat het netwerk het patroon heeft onthouden. Hiervoor ga je terug naar de "node"-mode (bovenaan: view>node). Nu reset je de layer met random waarden (hiervoor eerst de laag selecteren door klikken op de juiste plaats of het "vlakje trekken". Klik links op "reset layer" Met de linker optie "Act Step" voer je een enkele berekening uit. In het geval van een Hopfield-netwerk verandert dan maar de activatie van een enkele knoop. Druk een aantal malen op "Act Step" tot je een knoop van activatie ziet veranderen.

Met "Act Cycle" voer je er een aantal iteraties achter elkaar uit ('default' 100 in Hopfield). Druk een keer op "Act Cycle", en constateer dat er dan een heel stel knopen van activatie veranderen. Na een aantal keren op 'Act Cycle" te hebben geklikt krijg je je originele patroon terug. Als je het aantal iteraties wilt instellen moet je onder "Parameters" kijken in het "General"-menu links. Daar zal je de parameter "Cycle Step" vinden (in oudere versies van Nutshell heet die "Iteration Length").

Clampen en deactiveren

Soms is het nodig een deel van een netwerk te laten itereren, terwijl een ander deel constant dezelfde activatie houdt (bijvoorbeeld als dit gedeelte de input van het netwerk weergeeft en je de rest van het netwerk zich wilt laten aanpassen aan de input). Hiervoor bestaat in Nutshell het 'clampen' van knopen. Een 'geclampte' knoop verandert niet van waarde als je op "Act Cycle" drukt, ook als hij het normaal wel zou doen. Knopen 'clampen' kan je door een kruisje te zetten achter "Clamped" in het parametermenu van de knoop (zie onder 'Variabelen bekijken'). Veel handiger is weer "vlakje trekken".

Om dit te testen moet je eerst de laag weer 'resetten' (laag selecteren, functie aanklikken in linkermenu). Klik nu in het "Edit" menu op het tekeningetje met een wit vierkant met een zwart kruis erdoor, en een klein wit pijltje. Je muispunt is nu een 'clamper' geworden. Druk in de buurt van je netwerk op de muisknop, en trek de muispunt over een deel van de laag. Als je nu loslaat zie je een witte en zwarte kruizen verschijnen door alle knopen in het door jou getrokken vlak. Deze knopen zijn nu geclampt. Als je nu op "Act Cycle" drukt zal je zien dat een aantal van de niet-geclampte knopen van activatie verandert, maar de geclampte knopen niet. Door de shift-knop ingedrukt te houden terwijl je een vlakje trekt kan je knopen weer ontclampen.

Druk op het pijltje in het "Edit" menu om de muispointer terug te krijgen.

Je kunt knopen ook deactiveren (dood maken). Druk hiervoor in het "Edit" menu op het tekeningetje met een grijs vierkant met een wit kruis erdoor, en een witte pijltje. Je muispunt is nu een 'deactivator'. Trek weer een vlak over een deel van de laag. Je zult zien dat de knopen in je vlak grijs worden met een wit kruis erdoor. Deze knopen zijn gedeactiveerd: ze doen niets meer. Je kunt deactiveren, je raadt het al, weer opheffen door de shift-knop ingedrukt te houden en weer een vlak te trekken.

B. Scripting

Je kunt met de functies die in het linker menu staan verschillende soorten netwerken maken. Let wel, zolang je een Hopfield-workspace hebt opgestart blijven dit altijd Hopfield netwerken met Hopfield eigenschappen. Voor de rest kunnen deze netwerken zo complex worden gemaakt als de gebruiker wil. Je kunt ook allerlei patronen in een netwerk stoppen door ze na elkaar te tekenen en vervolgens te leren.

Voor onderzoek is het vaak nodig om je resultaten te repliceren om te laten zien dat je resultaat geen toevalstreffer is maar een robuust fenomeen. Om dan niet telkens het netwerk te hoeven maken en je patronen te leren, kun je alle informatie over het netwerk en patronen in een script zetten, een file met achter elkaar een serie commando's die nutshell kan uitvoeren. Ook kun je via script je resultaten handig weg laten schrijven naar bijvoorbeeld een excel sheet. Scripts zijn eigenlijk kleine programmaatjes. Ze zijn vergelijkbaar met macro's in word processors, of syntax-files die je misschien in SPSS hebt gebruikt.

Hoe je in een script met Nutshell werkt wordt uit de doeken gedaan in Appendix 1. Daarin staan een aantal commando's waarmee je dingen gedaan krijgt in Nutshell, met uitleg over hun werking. De uitleg gaat er overigens wel van uit dat je iets van visual basic begrijpt, dus bijv. de hieronder genoemde hoofdstukken van de Microsoft webmanual gelezen hebt.

In de volgende sectie zullen we uitleggen hoe een standaardscript in Visual Basic er uit ziet. Als je nog geen kaas gegeten hebt van programmeren kan je dit gebruiken om de scripts die je in opdracht 2.2 moet maken te begrijpen.

C. Het lezen van een Visual Basic-script.

In een net programma is er een scheiding tussen datastructuren en algoritmen. In de datastructuren wordt de data die je wilt gaan bewerken gezet. Algoritmen zijn de bewerkingen op de datastructuren. Stel dat je je een rij van tien getallen wilt opslaan binnen Visual Basic (VB). Dit definieer je zo:

Dim MaxSize as Integer
MaxSize = 9 ' 10 - 1
Dim GetalArray(MaxSize) as Integer

We beginnen met de onderste regel van de drie regels code. Dim staat voor Dimension; dit is in VB de aankondiging dat er een datastructuur gedefinieerd gaat worden. GetalArray is je datastructuur, in dit geval een rij (array) van getallen. MaxSize geeft de maximale hoeveelheid van getallen aan die je in de array kunt stoppen. En 'as Integer' geeft aan wat voor soort getallen je in de array wilt stoppen. Integers zijn de gehele getallen , de verzameling Z (zowel negatieve als positieve getallen). Op de tweede regel code krijgt Maxsize een waarde toegekend, namelijk de waarde 9. Het deel na het accent ' is commentaar (zie verderop). Arrays beginnen in VB altijd bij element 0, dus als je tien getallen op wilt slaan dan moet je een 'array' hebben van grootte 9: doordat je het element 0 mee moet rekenen zitten er dan eigenlijk 10 elementen in de Array. Op de bovenste regel wordt Maxsize gedefinieerd als een Integer.

Om nu daadwerkelijk getallen in de array te stoppen kan het volgende algoritme worden geschreven:

For index = 0 to MaxSize
GetalArray(index) = index
Next

Op de eerste regel wordt een 'for' loop gedefineerd. In een 'for'-loop wordt een stukje code een aantal malen herhaald; hier wordt steeds 1 element van de array 'GetalArray' gelijk gezet aan de index. . Dit wordt gedaan d.m.v. een index die de waarde 0 tot en met MaxSize kan aannemen. Doordat steeds 1 element van GetalArray ingevuld wordt, wordt zo de hele GetalArray doorlopen.

De eerste actie die de for loop doet is de GetalArray op plaats 0 de waarde 0 toe te kennen. Dus:

GetalArray(0) = 0

Het Next statement zorgt ervoor dat er naar de volgende index in de For loop wordt gegaan (We springen dus weer naar de eerste regel). Na 0 komt 1, dus het volgende wat de for loop gaat doen is de GetalArray op plaats 1 de waarde 1 te geven. Dus:

GetalArray(1) = 1

Dit gaat door totdat de 'For' loop bij MaxSize is aanbeland. De index heeft dan de waarde van MaxSize, in dit geval 9. Het laatste wat de for loop doet is GetalArray op plaats 9 de waarde 9 te geven, daarna is de loop klaar en gaat het programma verder.

GetalArray(9) = 9

Een programmeertaal heeft net als elke taal een syntax. Wat je doet is communiceren met een 'compiler', die je programmeerconstructies vertaalt in voor de hardware van de computer begrijpelijke code om jouw instructies uit te voeren (ik heb voor het gemak allerlei tussenstappen overgeslagen). De compiler kan alleen dingen begrijpen als jij je aan de syntax houdt. Elke programmeertaal heeft zijn eigen syntax, maar in hun essentie zien ze er allemaal vrijwel hetzelfde uit. Een taal heeft regels om datastructuren te maken/definiëren, en regels om algoritmen te schrijven die deze datastructuren bewerken.

We zijn al een syntaxconventie van Visual Basic voor datastructuren tegengekomen, namelijk dat na het woord Dim altijd een definitie volgt van een datastructuur. 'Dim' is een zogenaamd gereserveerd woord, een woord waarvan de betekenis is vastgelegd in de taal (zoals ook 'For' en 'Next' gereserveerde woorden zijn). Een tweede datastructuur-conventie was dat als een woord meteen wordt gevolgd door haakjes, (), het de naam van een array moet zijn. Die arraynaam, en ook namen van andere typen variabelen, mag je geheel zelf verzinnen mits het geen gereserveerd woord is. Dus sflj() is een array. Let wel dat er tussen haakjes maar één getal (die de grootte aangeeft) mag staan wil het een array zijn, dus sflj(10) is een array. Wat je vaak in de script zal tegenkomen is een matrix(aantalrijen, aantalkolommen). Iets wat twee getallen tussen de twee haken heeft staan, zoals sflj(10, 3), is een matrix volgens de Visual basic syntax.

Om algoritmen te schrijven heeft Visual Basic ook allerlei vaste taalconstructies. De 'for…next' loop is hier een voorbeeld van. In de visual basic 'help' kun je allerlei syntax-conventies voor datastructuren en algoritmen opzoeken. Je kan dit doen door met je cursor het woord te selecteren en dan op F1 te drukken. Of gewoon vanuit het helpmenu de help op te starten en dan het woord in te typen. Bovendien is er op de website van microsoft een heel boekwerk met informatie over Visual Basic te verkijgen. Voor beginners is het goed om dit boekwerk (gratis) te downloaden en de eerste twee-drie hoofdstukken door te lezen. Webadres: http://www.microsoft.com/officedev/articles/Opg/default.htm.

In een net programma zijn datastructuren en algoritmen netjes gescheiden. Dit is niet het geval in de visual basic scripts: hier staan de datastructuren binnen de algoritmen. Maar een datastructuur is makkelijk te herkennen omdat er Dim voor staat. Het algoritme zelf heeft een duidelijke structuur. Er is sprake van een hoofdalgoritme of hoofdprocedure waarin allerlei subprocedures staan. Subprocedures lossen vaak een deelprobleem van het hoofdprobleem op. Deze subprocedures staan elders in het programma gedefinieerd, en alleen de 'header' van de subprocedure staat in hoofdprocedure. De header bevat de naam van een subprocedure en een aantal parameters. Parameters zijn vaak datastructuren die in het hoofdprogramma zijn gedefinieerd en die je wilt gaan gebruiken in de subprocedure. Schematisch kan een programma er ongeveer zo uit zien (gereserveerde woorden zijn schuin gedrukt):

Sub Hoofdprocedure

Dim Datastructuur1
Dim Datastructuur2
Subprocedure1 datastructuur1 datastructuur2

Dim datastructuur3
Subprocedure2 datastructuur2 datastructuur3

End Sub

 

SubSubprocedure1( Dim datastructuur1, Dim datastructuur2)

Doe iets met datastructuur1en datastructuur2

End Sub

 

Sub Subprocedure2( Dim datastructuur2, Dim datastructuur3)

Doe iets met datastructuur2 en datastructuur3

End Sub

In elk van de subprocedures kan ook weer van alles worden gedaan. Er kan bijvoorbeeld een 'for…next' loop in staan, maar er kunnen ook weer allerlei andere procedures worden aangeroepen. Die je dan weer elders moet definiëren.

In een Visual basic script kun je nog drie andere soorten van taalconstructies tegenkomen, namelijk script-aanroepen, globale constanten en commentaar.

Scriptaanroepen zijn functie-aanroepen vanuit een script-taal naar een ander programma, vaak een zgn. 'applicatieprogramma' zoals Word of Excel, of ook Nutshell. Dit programma kan in een andere taal zijn geschreven en bevat allerlei eigen datastructuren en algoritmen. In dit geval worden er functies van de Nutshell-simulator aangeroepen vanuit Visual Basic. Nutshell is in C++ geschreven en bevat tienduizenden regels code, maar scripting maakt het mogelijk je daar niets van aan te trekken en er met Visual Basic mee te werken.

Globale constanten zijn constanten die je overal in je programma gebruikt. Als je bijvoorbeeld 5 patronen wilt leren, kan het slimmer zijn een globale constante "NrOfPatterns"en maken en die gelijk te zetten aan 5, dan om overal waar je het aantal patronen nodig hebt '5' te schrijven.

Commentaar staat achter een accent: ' ('dit is commentaar), en dient er meestal voor om aan te geven wat een bepaald algoritme doet of een datastructuur representeert.

Schematisch kan een script er zo uit zien:

'Globale constanten
Const GlobalConstant1 = waarde
Const GlobalConstant2 = waarde

 

Sub Hoofprocedure

Scriptcommando1
Scriptcommando2

Dim Datastructuur1 ' Commentaar over wat deze datastructuur doet
Dim Datastructuur2 ' Commentaar over wat deze datastructuur doet
Subprocedure1 datastructuur1 datastructuur2

Dim datastructuur3
Subprocedure2 datastructuur2 data

End Sub

 

Sub Subprocedure1( Dim datastructuur1, Dim datastructuur2)

Doe iets met datastructuur1 en datastructuur2

End Sub

 

Sub Subprocedure2( Dim datastructuur2, Dim datastructuur3)

Doe iets met datastructuur2 en datastructuur3
Subprocedure3 datastructuur3

End Sub

 

Sub Subprocedure3( Dim datastructuur3)

Doe iets met datastructuur3

End Sub

 


[1]        Door Robert Berg, Eric Maryniak en Jaap Murre.

 


University of AmsterdamUniversity of Amsterdam
Department of Psychology
Page last modified: 2003-03-02. Validate html.
Copyright © 2000-2007 neuroMod Group. Send us Feedback!