Werkplaats / De werkplaats
In jouw eigen tempo
← Neurale netwerken
MODULE 02 · LES 05

Een activatie maakt een nieuwe grens mogelijk

Vergelijk ReLU en tanh, bereken hun afgeleiden en bouw een klein netwerk voor XOR.

65 min3 checkpoints
DIT GA JE ONTDEKKEN
  • Je implementeert activaties en hun lokale afgeleiden.
  • Je bouwt een niet-lineaire oplossing voor XOR en verklaart de grenzen van de demonstratie.

Een laag heeft gewogen sommen berekend. Hoeveel daarvan geeft zij door, en hoe gevoelig is de uitvoer voor een kleine verandering? Een activatiefunctie bepaalt beide: haar waarde stuurt de volgende laag en haar afgeleide bepaalt later hoe een leersignaal teruggaat.

Je vergelijkt ReLU en tanh en bouwt daarna een klein netwerk dat XOR oplost. De gewichten van dat netwerk kiezen we met de hand. Het voorbeeld laat zien wat een verborgen laag kan uitdrukken; het is nog geen bewijs dat training die oplossing vanzelf vindt.

1. ReLU laat de positieve helft door

Je kent ReLU uit het eerste neuron: negatieve invoer wordt nul, positieve invoer blijft gelijk. Voor z = [−1,0,1] krijg je [0,0,1]. Op een hele array kun je diezelfde vergelijking elementgewijs uitvoeren.

import numpy as np
def relu(z):
    z = np.asarray(z, dtype=float)
    return np.maximum(0, z)

z = np.array([-1., 0., 1.])
a = relu(z)
print(a.tolist())  # [0.0, 0.0, 1.0]

De lokale helling is nul onder nul en één boven nul. Precies op de knik bestaat geen gewone afgeleide. In deze cursus kiezen we daar de rekenconventie nul, zodat de terugweg een vaste afspraak heeft.

ReLU′(z)={1z>00z≤0
gevoelig = (z > 0).astype(float)
print(gevoelig.tolist())  # [0.0, 0.0, 1.0]

De vergelijking maakt een booleaanse array; .astype(float) zet False en True om naar 0.0 en 1.0. Maak relu(z) en relu_afgeleide(z) als NumPy-arrays met dezelfde vorm als de invoer. Ook een matrix moet element voor element werken.

Een negatieve som krijgt langs deze rekenroute dus geen lokaal leersignaal terug. Als een ReLU voor alle trainingsvoorbeelden negatief blijft, kan die eenheid moeilijk weer actief worden. Een nulafgeleide betekent niet dat de volledige verliesfunctie nul is.

01
CHECKPOINTEen knik laat één helft door

2. Tanh buigt geleidelijk en verzadigt

Tanh, de hyperbolische tangens, maakt een vloeiende S-vorm tussen −1 en 1. De functie is oneven: de waarde bij −z is het tegengestelde van de waarde bij z. Bij nul is de waarde nul en de helling één.

In de formule is e het vaste getal ongeveer 2.718; e tot de macht z is de exponentiële functie, in NumPy np.exp(z).

tanh(z)=ez−e−zez+e−zdtanh(z)dz=1−tanh(z)2

Bij z = 1 is tanh ongeveer 0.761594 en de afgeleide ongeveer 0.419974. Bij z = −1 draait de waarde van teken om, maar blijft de afgeleide positief en even groot. Gebruik np.tanh voor de numerieke berekening; rechtstreeks grote exponenten uitrekenen kan overlopen.

z = np.array([-1., 0., 1., 4.])
a = np.tanh(z)
g = 1 - a * a
print(np.round(a, 6).tolist())
# [-0.761594, 0.0, 0.761594, 0.999329]
print(np.round(g, 6).tolist())
# [0.419974, 1.0, 0.419974, 0.001341]

Maak tanh_en_afgeleide(z) als (activatie,afgeleide) met twee NumPy-arrays. Bewaar de juiste activatietekens: alleen haar kwadraat controleren zou een tekenfout in de uitvoer verbergen.

WAARDE EN LOKALE GEVOELIGHEIDHoeveel signaal laat de activatie door?

Groen: activatie. Oranje: afgeleide. Verplaats de invoer en vergelijk de twee getallen.

-101234-4-2024
Activatie0.762Afgeleide0.420

Vergelijk in het diagram tanh bij z = 0 en z = 4. De uitvoer nadert één, terwijl de afgeleide bijna verdwijnt: verzadiging. Bij meerdere terugwaartse vermenigvuldigingen kunnen zulke kleine factoren het signaal sterk verzwakken.

Schakel daarna naar ReLU en vergelijk −1 met 1. Een grote uitvoer en een grote afgeleide zijn verschillende eigenschappen; kijk steeds naar beide getallen.

02
CHECKPOINTVerzadiging dempt het leersignaal

3. Maak twee verborgen features voor XOR

XOR geeft één wanneer precies één van twee binaire invoeren één is. De positieve gevallen [0,1] en [1,0] liggen op tegenoverliggende hoeken; één rechte grens kan ze niet beide van [0,0] en [1,1] scheiden. Met twee geknikte features lukt het wel.

Bereken eerst s = x₁+x₂. Laat h₁ = ReLU(s) en h₂ = ReLU(s−1), en combineer ze tot h₁−2h₂. De tweede verborgen feature trekt alleen bij de dubbele één weer twee af.

Invoersh₁h₂Uitvoer
[0,0]0000
[0,1]1101
[1,0]1101
[1,1]2210
x = np.array([[0, 0], [0, 1],
              [1, 0], [1, 1]], dtype=float)
s = x.sum(axis=1)
h1 = relu(s)
h2 = relu(s - 1)
uitvoer = h1 - 2 * h2
print(uitvoer.tolist())  # [0.0,1.0,1.0,0.0]

sum(axis=1) telt de twee features binnen iedere rij op en geeft één getal per voorbeeld. Maak xor_netwerk(x) voor een matrix met twee binaire kolommen en retourneer een uitvoervector. Gebruik je eigen ReLU-functie voor de twee verborgen features.

Veelgemaakte fout: alleen extra affine lagen stapelen en dezelfde scheiding verwachten. De niet-lineariteit maakt hier het verschil; de laatste combinatie zelf mag gewoon lineair zijn. Buiten de vier binaire hoeken heeft dit handgekozen netwerk niet automatisch een zinvolle betekenis.

03
CHECKPOINTBouw twee verborgen features voor XOR

Wat neem je mee?

  • Activatiewaarde en afgeleide beschrijven wat doorgaat en hoe gevoelig dat is.
  • ReLU heeft een knikconventie; tanh kan aan beide kanten verzadigen.
  • Verborgen niet-lineaire features maken een scheiding mogelijk die één rechte grens mist.

Hierna zet je meerdere uitvoerscores om in een kansverdeling en bereken je het passende verlies.

Verder lezen & bronnen

Inhoud gecontroleerd op 2026-10-28.
DE VOLGENDE STAPVan meerdere scores naar een stabiel verlies
JOUW EXPERIMENT

Probeer het zelf

Python
main.py

Python start zodra jij code uitvoert.

UITVOER

Je uitvoer verschijnt hier.
Alles rekent in je eigen browser.

Jouw checkpoints0 / 3
01
Een knik laat één helft door

Schrijf relu(z) en relu_afgeleide(z), beide elementgewijs voor NumPy-arrays.

Een hint

np.maximum geeft de activatie; (z>0).astype(float) geeft de gekozen afgeleide.

02
Verzadiging dempt het leersignaal

Schrijf tanh_en_afgeleide(z) als (activatie,afgeleide), beide NumPy-arrays.

Een hint

Bereken de activatie eenmaal en gebruik haar kwadraat voor de afgeleide.

03
Bouw twee verborgen features voor XOR

Schrijf xor_netwerk(x) voor een matrix met twee binaire invoerfeatures; retourneer een vector uitvoerscores.

Een hint

Maak de twee verborgen features met de eerder geschreven relu en combineer ze lineair.

Vastgelopen? Bekijk de voorbeeldoplossing
import numpy as np

def relu(z):
    return np.maximum(0,np.asarray(z,dtype=float))

def relu_afgeleide(z):
    return (np.asarray(z)>0).astype(float)

def tanh_en_afgeleide(z):
    a=np.tanh(np.asarray(z,dtype=float))
    return a,1-a*a

def xor_netwerk(x):
    x=np.asarray(x,dtype=float)
    s=x.sum(axis=1)
    return relu(s)-2*relu(s-1)

Voer de code uit en verklaar voor jezelf waarom elke stap werkt.