Courses  

Appendix 1: voorbeelden van Nutshell commando's

In deze appendix geven we een aantal voorbeelden van script-commando's die je nodig hebt om bijvoorbeeld de code te schrijven voor opdracht 5.1. Veel van deze commando's kan je in elk paradigma gebruiken, maar sommigen zijn specifiek voor één paradigma. Enkel degenen die je ook in de Nutshell omgeving kunt vinden als je met een paradigma, kan je in scripting gebruiken bij dat paradigma. Het volgende zal ervan uitgaan dat je dit het hards nodig hebt op het moment dat je in opdracht 5.1 zelf commando's in moet voeren; daarom zijn de voorbeelden met het 'MacGregor'-paradigma.

Hoe verwijs je naar Nutshell?

In Nutshell heb je te maken met een workspace, waar weer lagen en tracts en knopen in zitten, en een 'applicatie' (=het programma) er omheen. Om Nutshell met scripting vanuit een ander programma te besturen, moet je minstens die workspace en al die dingen kunnen bereiken. Je moet met die 'objecten', zoals dat in softewarespeak heet, kunnen 'praten'. In principe kan dat allemaal via een ingewikkelde hiërarchie naar beneden, tot je bent waar je wezen moet. Veel simpeler gaat het door een variabele te laten verwijzen naar objecten. In al onze VBA-scripts staan ergens -misschien in een subprocedure of in een andere module- de regels:

Dim workspaces As Object
Set workspcs = CreateObject("Nutshell.Workspaces")
Dim worksp As Object
Set worksp = workspcs.Add("MacGregor.np")

(waarbij in de plaats van "Macgregor.np" ook de naam van een ander paradigma kan staan). In deze vier regels worden twee variabelen aangemaakt in de Dim-statements [een variabele is een naam die een waarde kan hebben of ergens naar kan verwijzen], die komen te verwijzen naar resp. een "Workspaces"-object en een "Workspace"-object. Zo'n "Workspaces"-object is een verzameling open workspacen. Als je zoiets maakt (wat in regel 2 gebeurt) start je in feite een nieuwe Nutshell op. In die verzameling workspacen wordt in regel 4 één bepaalde workspace gemaakt, van het type "MacGregor". Als je dit niet helemaal snapt is dat niet erg (copy-paste die vier regels in al je scripts en je bent klaar), het belangrijkste is dat je een variabele overhoudt, "worksp", die verwijst naar de Nutshell workspace die is aangemaakt (in veel scripts heet deze variabele 'workspace', maar hier is het afgekort om verwarring met de echte Nutshell workspace te voorkomen). Overal waar je, tenminste binnen de procedure waarin die regels staan, nu 'worksp' schrijft, weet VBA dat je de geopende Nutshell workspace bedoelt, en dat je dus in feite orders aan een ander programma dan VBA wilt geven.

De truc met verwijzende variabelen lukt ook op lager niveau. Nieuwe lagen krijgen een nummer op volgorde dat ze zijn aangemaakt. De eerste laag die je maakt krijgt bijvoorbeeld nummer 0 (omdat bijna alle programmeertalen tellen vanaf nul). Nu kun je die laag aanwijzen door vanaf de workspace naar beneden te gaan, naar die laag. "layers" is de verzameling lagen in een workspace, en als je uit die verzameling de nulde pakt zit je goed. Dat doe je met een punt ertussen:

worksp.layers(0)

Zo wijs je de nulde laag aan. Als je de derde knoop van de nulde laag wilt aanwijzen, moet je gewoon nog wat verder naar beneden gaan:

worksp.layers(0).nodes(3)

Zo begrijpt VBA met welke knoop je iets wilt. "Nodes" is hier weer de verzameling knopen in een laag, en weer moet er een puntje tussen (zo gaat Nutshell door de hiërarchie heen). Omdat dit wat lang is kan je ook met variabelen naar de laag verwijzen.

Dim frontLayer as object

Set frontLayer = worksp.layers(0)

Nu verwijst frontLayer naar de nulde laag, en kan je naar die derde knoop verwijzen met:

frontLayer.nodes(3)

VBA weet, dankzij de toewijzing van de variabele frontLayer aan de nulde laag, waar je het over hebt.

Een commando vertalen uit de omgeving

Het basisprincipe achter de scriptcommando's is simpel: je schrijft uit wat je in Nutshell zou doen. Als je bijvoorbeeld een laag wilt 'resetten', dan moet je de laag selecteren en vervolgens de functie 'reset layer' aanklikken in het 'General'-menu. Het 'General'-menu hoort bij de workspace. Je 'stuurt' de instructie die je aanklikt naar de workspace. Tijdens het scripten kan je dat ook doen door de workspace 'aan te roepen' via de variabele 'worksp', dan een punt te zetten, en de functienaam. De functienamen -en voor de parameternamen geldt hetzelfde- die je bij het scripten gebruikt zijn precies dezelfde als degenen die je in Nutshell ziet, alleen worden de spaties weggelaten. "Reset Layer Nodes", de functienaam in Nutshell, wordt zo bijvoorbeeld "resetlayernodes". Het commando wordt dan: "worksp.resetlayernodes".

Nu moet je nog wel een laag selecteren. Dat doe je door de naam van een laag achter het commando te schrijven. Je kunt dat weer via een variabele doen die naar de laag verwijst (bijv. 'frontLayer' voor een frontale laag), of via de workspace en het laagnummer (bijv. "worksp.layer(0)"). Het volledige commando wordt dan bijvoorbeeld:

worksp.ResetLayerNodes worksp.layer(0)

Ander voorbeeld: Insert Tract. Om een tract aan te maken moet je niet één maar twee lagen selecteren, eentje waar de tract vandaan komt en eentje waar die naar toe gaat (als je één laag selecteert en op 'Insert Tract' drukt, gaat Nutshell er vanuit dat de laag met zichzelf verbonden moet worden, waardoor twee keer één en dezelfde laag geselecteerd is). Bij het scripten schrijf je de twee lagen die je selecteert (waar je een verbinding tussen wil) achter elkaar, met een komma ertussen. Hoe ziet dat eruit? Net als bij 'reset' begin je met 'worksp', een punt, en dan de functienaam zonder spaties: InsertTract. Vervolgens moet je aangeven tussen welke lagen de tract moet lopen, stel van laag 0 naar laag 1. Connectionisten hebben de wat onintuïtieve afspraak dat de ontvanger eerst komt in het benoemen van een connectie, en dan pas de zender. Daarom schrijf je eerst de laag waar de tract heen gaat, daarna waar hij vandaan komt. Met een komma tussen de twee lagen wordt het:

worksp.InsertTract worksp.layer(1), worksp.layer(0)

In het Hopfieldparadigma ben je dan klaar. In het MacGregorparadigma en veel andere paradigma's moet je echter meer informatie meegeven: de functie "Insert Tract" heeft in die paradigma's argumenten. [9] Open een nieuwe MacGregorworkspace in de Nutshell omgeving, maak twee lagen aan, selecteer die (shift ingedrukt houden, op beide lagen klikken) en druk op 'Insert Layer'. Je krijgt een venstertje waarin je twee argumenten moet opgeven: de leerparameter mu moet je instellen, en je moet aanvinken of de 'tract' normalizerende gewichten heeft of niet. Bij de leerparameter moet je een getal opgeven, en een vinkje bij "Is Normalizing" staat voor 'true' (waar, de tract is normalizing). Geen vinkje daar betekent 'false' (onwaar, de tract is niet normalizing). Bij het scripten zet je de waardes die de parameters moet krijgen, allemaal met komma's ertussen, achter de lagen. Stel ook dat je wilt dat de leerparameter gelijk moet zijn aan 0.1 en dat je een niet-normalizaerende tract wilt. Dan moet je schrijven:

worksp.InsertTract worksp.layer(1), worksp.layer(0), 0.1, false

Je moet altijd net zoveel dingen tussen komma's zetten als er argumenten zijn wanneer je de functie uitvoert in Nutshell. In dit geval moeten het er dus twee zijn, anders krijg je een foutmelding.

Het recept voor het vertalen van een Nutshell functie in een scripting-commando is dus:

♦ Je begint met een variabele, meestal 'workspace' geheten of zoals hier 'worksp', die verwijst naar de echte Nutshell workspace (zie boven hoe we die aanmaken).

♦ Achter deze variabele komt een punt, en dan de naam van de nutshell-functie zonder spaties.

worksp.DitIsEenFunctie

♦ Als er voor de functie in Nutshell iets geselecteerd moet worden, bijv. een laag of een tract of een knoop (soms hoeft er niets geselecteerd te worden), schrijf een naam of verwijzing daarnaar achter de functienaam. Meestal doe je dit met een of een variabele die direct naar je laag of tract verwijst, of vanaf de variabele 'worksp'. Dan een punt, en de laag met laagnummer of tract met de lagen waartussen de tract zit (zie hieronder voor voorbeelden).

worksp.DitIsEenFunctie laagnaamOfZo

♦ Tenslotte moet je nog de argumenten van de functie opgeven. Door de functie in Nutshell uit te voeren krijg je, tenminste als er argumenten zijn, een dialoogschermpje waarin je kunt zijn welke argumenten er zijn, in welke volgorde ze staan en van welk type ze zijn. Zet voor elk argument een waarde, allemaal door komma's gescheiden, achter het commando, en je bent klaar:

worksp.DitIsEenFunctie laagnaamOfZo, argument1, argument2.

Instellen van knoop-parameters als activatie en vuren:

Voor het instellen van parameters geldt in grote lijnen wat geldt voor functies: je doet na wat je in de Nutshell omgeving doet. In de Nutshell omgeving kan je altijd kijken wat voor parameters er zijn en waar ze bij horen. Vervolgens kan je ze bereiken met de hiërarchie uitgelegd in de sectie "Hoe verwijs je naar Nutshell?".

Hoe parameters heten hangt af van het paradigma. In het MacGregorparadigma heb je de knoop-parameters "Membrane" en "Fires" (om ze te zien: klik in een MacGregor-workspace een knoop aan, klik op de rechtermuisknop, en dan onder "node(x)" op "parameters"). In opdracht 5.1 moet je een 'Frontale' laag aanmaken en een 'Thalamuslaag'. Stel dat je "membrane" (het membraanpotentiaal) van de nulde knoop van de frontale laag (frontLayer) op 1 wilt zetten. Dan schrijf je als commando:

frontLayer.nodes(0).membrane = 1.0

frontLayer is hier een variabele die naar de frontale laag verwijst. Zonder die variabele was het geworden (gegeven dat frontLayer laag 0 is):

worksp.layers(0).nodes(0).membrane = 1.0

In dit voorbeeld is activatie (bij MacGregor gelijk aan het membraanpotentiaal) een 'reële' parameter, een parameter waarbij je reële getallen als waarden moet opgeven (vaak zijn de waarden wel aan maxima en minima gebonden; wat die zijn kan je lezen in de Nutshell help bij paradigma's). Je kunt ook andere soorten parameters hebben: parameters waarbij je enkel 'integer'-waarden op kunt geven (=natuurlijke getallen), of 'Booleans'. In het macGregor-paradigma is bijvoorbeeld vuren een 'booleaanse' parameter, een parameter die 'true' is als de knoop vuurt en 'false' als de knoop niet vuurt (ook het normalizen van een 'tract', hierboven besproken, is een boolean). Zo'n parameter kan je bijvoorbeeld als volgt instellen:

frontLayer.nodes(0).Fires = true

Instellen van een gewicht

Stel dat je het gewicht van de vierde knoop van een frontale laag naar de tweede knoop van de thalamuslaag wilt instellen op 0.5. Dan geef je als commando:

worksp.Tracts(thalLayer, frontLayer).connections(2,4).Weight=0.5

Naar connectionistenconventies komen ontvangers eerst, dan pas zenders, zowel op het niveau van 'tracts' (bundel connecties van één laag naar een andere laag) als op het niveau van individuele connecties. "Tracts(thalLayer, frontLayer)" is dus de tract van de frontlayer naar de thalamuslayer, Tracts(thalLayer, frontLayer).connections(2,4) is de connectie van de 4e frontale knoop naar de 2e thalamusknoop. Daar roep je het gewicht van aan, en dat zet je gelijk aan 0.5.

Instellen van de leerrate

Stel dat je de leerparameter, in de meeste paradigma's 'mu' geheten, wilt instellen op 0.4 in de 'tract' van de frontale laag naar de thalamuslaag. Dan schrijf je:

worksp.Tracts(frontLayer, thalLayer).mupos=0.4.

Weer gebruiken we variabelen om naar de lagen te verwijzen. Vergeet niet dat de ontvanger eerst komt in het aanroepen van de 'tract', en dan pas de zender. Er is een aparte leerparameter voor elke 'tract'; d.w.z., voor elke bundel connecties van één laag naar een andere laag. Als je de leerparameter voor de 'tract' van laag 1 naar laag 2 verandert, blijft de leerparameter van laag 2 naar laag 3 dus precies hetzelfde - om die te veranderen moet je een nieuw commando geven waarin je die leerparameter verandert.

In de meeste paradigma's hoort de leerparameter bij de 'tract', en moet je dus de 'tract' aanroepen zoals hierboven om hem te veranderen. In het Backprop-paradigma is de leerparameter hetzelfde voor de hele 'Workspace'. In dit geval stel je deze parameter (daar 'eta' geheten) in als volgt:

workspace.eta = 0.05

(Voor opdracht 5.1:Er is ook een 'muneg' die 'Long-Term Depression' regelt. Deze parameter staat in elke 'tract' op 0, en dat kan je beter zo houden.)

Leren en activatie updaten

Leren en activatie-updaten zijn commando's die je doorgeeft aan de 'workspace'. Activatie updaten (=uitrekenen voor een nieuwe iteratie) doe je met het volgende commando:

worksp.ActCycle

Enkel de activatie wordt ge-update, zonder dat er sprake is van leren. De activatie wordt ge-update voor een aantal iteraties tegelijk; de workspace-parameter 'Cycle Steps' bepaalt voor hoeveel iteraties dit is. De uitgangswaarde is voor de meeste paradigma's gelijk aan 1. Enkel voor Hopfield geldt dit niet: hier is de uitgangswaarde 100. Deze parameter kan je als volgt instellen (bijvoorbeeld op 50):

worksp.CycleSteps = 50

Voor als je zeker wilt zijn dat de activatie maar voor 1 iteratie ge-update wilt worden is er in de meeste paradigma's het commando:

worksp.ActStep

Voor leren is er het commando:

worksp.learn

Bij de meeste paradigma's gebeurt dit voor 1 iteratie. Hoe leren precies gebeurt hangt af van het paradigma: elk paradigma heeft zijn eigen leerregel.

In het MacGregor-paradigma is er ook een commando voor het tegelijk activatie-updaten en leren:

worksp.cycle

Dit zorgt ervoor dat de activatie ge-'update' en de gewichten aangepast worden. Wel is er een eigenaardigheid aan wanneer de gewichten ge-update worden (zie uitleg opdracht 5).

Resetten van een laag

Hoger in deze appendix al uitgelegd. De variabele "frontLayer" gebruikend wordt het:

worksp.resetlayernodes frontLayer

Hoe en wat ge-'reset' wordt hangt af van het paradigma. In Hopfield wordt de activatie ge-'reset' op een willekeurige waarde; in Kohonen, TraceLink en CALM wordt de activatie van knopen op 0 gezet. Knopen blijven wel geclampd of gedeactiveerd als ze dat waren. In MacGregor zorgt 'reset' ervoor dat alle knopen niet meer vuren, en dat alle activaties en kaliumconcentraties weer gelijk gezet worden aan 0.

Clampen en deactiveren

Of een knoop ge'clamped' of ge'deactiveerd' is of niet is een knoop-parameter. Je stelt ze in het script in op dezelfde manier als andere knoop-parameters.

frontLayer.nodes(0).clamped=true (of: " = false")

frontLayer.nodes(0).deactivated=true (of: " = false")

Als je een hele laag wilt clampen of deactiveren is het natuurlijk onhandig om alle knopen af te lopen. Daarom is er ook een variabele voor de laag:

frontLayer.clamped=false

frontLayer.deactivated=true

Dit ont'clampt' alle knopen in de laag eerst (door 'clamped' op 'false' te zetten), en deactiveert ze vervolgens.

Zien wat er gebeurt

'Default' in Nutshell is dat je niet ziet wat er gebeurt als je je script runt. Om op het scherm te zien hoe je simulatie erbij staat moet je een speciaal commando in je code zetten:

workspace.update

Zet dit commando overal in je script waar je wilt zien wat er gebeurt.

 

 

 

[9]   Een argument van een functie of procedure is een getalletje (of andere waarde) dat je mee moet geven om te bepalen wat er precies moet gebeuren. In de functie 'plus' (x + y) heb je twee argumenten: x en y, de twee getallen die je bij elkaar op moet tellen. Bij de functie 'Insert Layer' zijn de breedte en de hoogte van de aan te maken laag de argumenten.

 


University of AmsterdamUniversity of Amsterdam
Department of Psychology
Page last modified: 2013-10-27. Validate html.
Copyright © 2000-2009 NeuroMod Group. Send us Feedback!