#Klooienmetcomputers

Onze eigen AI

Arnout van Kempen over rommelen in een digitale wereld.

Het is makkelijk om je druk te maken over dingen die er heel intelligent uitzien, als je niet snapt wat je echt ziet. En AI, kunstmatige intelligentie, is al eeuwen (!) een onderwerp dat in golven wat paniek veroorzaakt. Eind achttiende eeuw werden mensen zo heel zenuwachtig van een schakende robot, wat vervolgens vals spel bleek te zijn.

In de jaren zestig van de vorige eeuw kreeg je ELIZA, een eerste serieuze chatbot. De meest recente ontwikkeling is ChatGPT en ineens lijkt AI overal te zijn en alles te veranderen. AI die de Turing test kan doorstaan is er nog steeds niet, maar het begint opvallend dichtbij te komen. Tijd dus om zelf wat te gaan klooien met kunstmatige intelligentie!

Het concept dat ik daarvoor gebruik is niet nieuw en ook niet heel ingewikkeld. Het is gebaseerd op een kinderspelletje, waarbij de ene speler iets in gedachten moet nemen en de andere speler dat moet zien te raden door uitsluitend vragen te stellen waarop ja of nee kan worden geantwoord. Op zich niets AI aan, maar we gaan het uitbreiden: iedere keer dat de computer het goede antwoord niet raadt, vraagt hij wat het verschil is tussen de gok van de computer en het juiste antwoord van de speler. Deze kennis slaat de computer op en wordt de volgende keer gebruikt.
Op deze manier zal de computer dus nieuwe kennis opdoen, iets leren dat niet door de programmeur vooraf bedacht is. Als dat nog geen AI is, wat dan wel?

Een compleet werkend programma staat al op GitHub, maar let op: Dit is niet te gebruiken zonder kennis van JSON en dat komt de volgende keer pas aan bod. Dus gebruik de sourcecode vooral, maar je zal er zelf nog wat mee moeten klooien om het werkend te krijgen!

De basis van ieder programma is het uitdenken van de concepten waar we mee gaan werken. Voor het vraag-spelletje is kennis vrij eenvoudig te structureren: alles begint met een vraag waar twee antwoorden op mogelijk zijn. Ieder antwoord leidt tot een nieuwe vraag, of tot een gok.

Deze simpele structuur moet wel kunnen groeien naarmate meer geleerd wordt, en daar is een dynamische gelinkte lijst het ideale middel voor in C. In een dergelijke lijst worden nodes, of knopen, aan elkaar gekoppeld. Iedere node bevat een vraag of een ding en doorverwijzingen naar de volgende nodes op basis van de antwoorden ja of nee. Om ruimte te sparen nemen we niet een ding en een vraag op per node, maar of een ding, of een vraag. Verder moeten we kunnen zien wat de inhoud van de node is en dat doen we liefst ook compact, met een enkel cijfer, maar ook goed leesbaar voor de programmeur. Hiervoor gaan we met enum werken.

De node komt er nu als volgt uit te zien, samen met een typedef voor de leesbaarheid:

typedef struct Node Node;

 struct Node
{
     Node* ja;
     Node* nee;
     enum NodeType
     {
          VRAAG,
          DING
     } type;
     union
     {
          char vraag[256];
          char ding[256];
     } data;
};

vraag en ding zijn strings met lengte 256, die dezelfde plek innemen in het geheugen. Een node kan immers nooit zowel een ding als een vraag zijn, dus er is geen reden om dubbele ruimte in beslag te nemen.

Het doel van het spel is dat de computer iets leert, dus zo vaak mogelijk fout gokt. De speler moet dus uitgedaagd worden steeds opnieuw te spelen. Binnen één spel werkt de computer stap voor stap de kennis-boom met vragen af, tot er geen vragen meer zijn en er dus gegokt moet worden. Dat betekent dus een dubbele loop:

do
{
     \* nieuw spel starten *\
     do
     {
          \*nieuwe vraag stellen of gokken*\
     } while(!geraden);

     \* als de gok fout was, vragen wat het had moeten zijn en
     met welke vraag dit geraden had kunnen worden.
     Nu verandert de l
aatste node in een VRAAG, de gok schuift
     naar node->nee en h
et goede antwoord naar node->ja *\
} while(speler_wil_nog_een_keer);

 Vervolgens moet de geleerde kennis opgeslagen worden. En bij de start zou het programma moeten bekijken of al eerder geleerde kennis aanwezig is, zodat je niet steeds opnieuw moet beginnen.

 Verder hebben we wat functies nodig:

  •  Een functie om een nieuwe node aan de kennis-boom toe te voegen.
  •  Een functie om de start kennis-boom op te zetten of in te lezen.
  •  Functies om de kennis-boom naar een bestand te schrijven en weer te lezen.
  •  Een functie om het dynamisch gealloceerde geheugen voor de kennis-boom weer vrij te geven.
  • Functies voor de invoer van gegevens.

Al die functies zijn, met de tot nu toe opgedane kennis, te schrijven, hoewel het naar een bestand schrijven nog wel een uitdaging gaat zijn. Daarover de volgende keer meer.
Voor nu is nog één concept van groot belang: de recursieve functie.

 In talen als C is het toegestaan dat een functie zichzelf aanroept. Dat heeft als grote voordeel dat je een handeling een eindig aantal keer kan herhalen, zonder te weten hoe vaak dat nodig gaat zijn. Bijvoorbeeld acties op een dynamische lijst, zoals hier. Het klassieke voorbeeld van de recursieve functie komt echter uit de wiskunde: de faculteit.

x! is gedefinieerd als 1, wanneer x = 0, of als x * (x-1) * (x-2) * … * 1.

Als je niet weet hoe groot x is, weet je ook niet hoe vaak je de vermenigvuldiging moet herhalen. Probeer het maar eens op te lossen in een functie die niet recursief is, dat is best lastig. Recursief wordt het ineens erg eenvoudig:

int fac(int x
{
     if(x == 0)
          return 1;
     else
          return x * fac(x-1);
}

en dat is alles.

Wie mee wil doen met #klooienmetcomputers kan dat doen via GitHub. Maak een account op www.github.com en zoek naar Abmvk/kmc. Het account Abmvk volgen kan ook. Lezers zijn vrij te gebruiken wat ze willen en om zelf zaken toe te voegen of aan te passen, vragen te stellen of commentaar te leveren.

Arnout van Kempen di CCO CISA is Senior manager Risk & Compliance bij Baker Tilly. Hij schrijft op persoonlijke titel. Hij is lid van de Commissie Financiële verslaggeving & Accountancy van de AFM en lid van de signaleringsraad van de NBA. Daarnaast is hij diaken van het bisdom 's-Hertogenbosch.

Gerelateerd

reacties

Reageren op een artikel kan tot drie maanden na plaatsing. Reageren op dit artikel is daarom niet meer mogelijk.

Aanmelden nieuwsbrief

Ontvang elke werkdag (maandag t/m vrijdag) de laatste nieuwsberichten, opinies en artikelen in uw mailbox.

Bent u NBA-lid? Dan kunt u zich ook aanmelden via uw ledenprofiel op MijnNBA.nl.