Van neuron tot taalmodel

Hoofdstuk 5 · de uitbreiding

Van optellen naar rekenen

Optellen lukte vlot. Nu vragen we meer: hetzelfde soort netwerk moet vier bewerkingen leren — optellen, aftrekken, vermenigvuldigen en delen — voor diezelfde getallen 0 tot 4. Daarvoor moeten de invoer, de uitvoer én het netwerk zelf groeien. In dit hoofdstuk bouwen we het ontwerp; in het volgende kijken we wat die extra moeilijkheid met het netwerk doet.

5.1 — het idee

Eén netwerk, vier bewerkingen

We zouden vier aparte netwerkjes kunnen maken, maar dat is saai en leert ons weinig. Veel interessanter: één netwerk dat we erbij vertellen wélke bewerking het moet doen. Het krijgt dus drie dingen binnen — getal a, getal b, én de gevraagde bewerking — en moet leren zijn rekenwijze aan te passen aan dat laatste. Dat “schakelen tussen taken” is precies wat het netwerk complexer maakt.

5.2 — de invoer

Een extra code voor de bewerking

In de optel-versie was de invoer 10 getallen: twee one-hot blokken voor a en b. Nu plakken we daar een derde one-hot blok achter, dat zegt welke bewerking gevraagd wordt. Vier bewerkingen, dus vier vakjes:

De bewerking als one-hot code van lengte 4.
bewerking+−×÷
optellen +1000
aftrekken −0100
maal ×0010
delen ÷0001

De invoer groeit zo van 10 naar 14 getallen: 5 voor a, 5 voor b, 4 voor de bewerking. Bijvoorbeeld “3 × 2”:

a = 3 → [0,0,0,1,0]   b = 2 → [0,0,1,0,0]   × → [0,0,1,0]
invoer = [0,0,0,1,0,  0,0,1,0,0,  0,0,1,0] ← 14 getallen
5.3 — de uitvoer

Veel meer mogelijke antwoorden

Bij optellen liep het antwoord van 0 tot 8. Nu niet meer. Aftrekken kan negatief worden (0 − 4 = −4), en vermenigvuldigen schiet hoog (4 × 4 = 16). Het antwoord ligt dus ergens tussen −4 en 16 — dat zijn 21 mogelijke uitkomsten.

We geven het netwerk dus 21 uitvoerknopen, één per mogelijk resultaat. We nummeren ze van −4 (positie 0) tot 16 (positie 20): de positie is gewoon resultaat + 4.

resultaat −4 → positie 0    resultaat 0 → positie 4    resultaat 16 → positie 20

Sommige uitkomsten (10, 11, 13, 14, 15) komen bij deze getallen nooit voor. We houden het bereik tóch aaneengesloten van −4 tot 16 — dat is eenvoudiger, en het netwerk leert vanzelf dat die posities nooit het antwoord zijn. Zo groeit de uitvoer van 9 naar 21 knopen.

5.4 — deling is speciaal

Delen, maar netjes

Delen geeft een probleem dat de andere drie niet hebben: 3 ÷ 2 is 1,5 — geen heel getal. En delen door 0 bestaat niet. We lossen dat hier op twee manieren op:

  • Gehele deling. We gebruiken delen zoals Java dat met gehele getallen doet: 3 ÷ 2 = 1, 1 ÷ 4 = 0. Het resultaat is altijd een heel getal, en past dus netjes bij de andere bewerkingen.
  • Geen deling door 0. Combinaties met b = 0 laten we gewoon weg uit de dataset. Onbestaand antwoord, dus niets te leren.

Dat “echte” deling (met 1,5 als antwoord) lastiger ligt, is geen toeval — het dwingt je tot een heel ander soort netwerk. Daar komen we in hoofdstuk 6 op terug, als voorbeeld van diepere complexiteit.

5.5 — de volledige waarheid

Nu vier tabellen in plaats van één

Waar het netwerk vroeger één tabel van 25 sommen moest leren, zijn het er nu vier. Samen 95 feiten (deling heeft er maar 20, want b = 0 valt weg). Hier is alles wat het moet leren:

optellen  a + b
+01234
001234
112345
223456
334567
445678
aftrekken  a − b
−01234
00-1-2-3-4
110-1-2-3
2210-1-2
33210-1
443210
maal  a × b
×01234
000000
101234
202468
3036912
40481216
gehele deling  a ÷ b
÷01234
0–0000
1–1000
2–2100
3–3110
4–4211

Let op het verschil in karakter. Optellen en aftrekken zijn “glad”: buurvakjes verschillen netjes met 1. Vermenigvuldigen springt veel grilliger (0, 4, 8, 12, 16 op één rij), en delen propt veel verschillende invoeren op dezelfde uitkomst (kijk hoeveel nullen). Die laatste twee zijn voor een netwerk merkbaar moeilijker — precies wat we in het volgende hoofdstuk gaan meten.