Werkplaats / De werkplaats
In jouw eigen tempo
← Wiskunde-fundament
MODULE 03 · LES 10

Een helling voor elk gewicht

Bereken een gradiënt, controleer hem numeriek en zet een gezamenlijke leersprong.

45 min3 checkpoints
DIT GA JE ONTDEKKEN
  • Je interpreteert de gradiënt als een vector van partiële afgeleiden.
  • Je controleert gradiënten met centrale verschillen zonder de invoer te wijzigen.

Een eenvoudig woningprijsmodel gebruikt instelbare getallen voor oppervlakte en kamers: de gewichten (weights). Je wilt weten bij welk gewicht een kleine wijziging het verlies het sterkst verandert en welke kant je op moet. Eén helling is dan niet genoeg: iedere instelling krijgt haar eigen gevoeligheid.

Stel je twee knoppen voor boven een komvormig landschap. Een punt vertegenwoordigt de twee instellingen; de hoogte staat voor een verlies (loss), een foutscore die je wilt verlagen. Verander eerst alleen de ene knop, daarna alleen de andere: de kom kan in die richtingen verschillend steil zijn.

TWEE GEWICHTEN, ÉÉN VERLIESDalen over een verlieslandschap

Ellipsen verbinden punten met gelijk verlies: L = w₁² + 4w₂². De pijl wijst tegen de gradiënt in.

149162536w₁w₂
w (3.00, 2.00)∇L (6.00, 16.00)Verlies 25.000

Begin bij (3, 2), met verlies 25. De ellipsen verbinden punten met dezelfde verlieswaarde; dichter bij het midden liggen lagere waarden. De groene pijl wijst naar lokale daling, niet noodzakelijk rechtstreeks naar het midden.

1. Eén helling voor iedere knop

Onze foutscore neemt het kwadraat van het eerste gewicht plus viermaal het kwadraat van het tweede. Bij (3, 2) is dat 9 + 4 × 4 = 25. Een kleine verhoging naar (3.1, 2) geeft 25.61; naar (3, 2.1) geeft 26.64: de tweede richting stijgt hier sneller.

L(w)=w12+4w22

L benoemt de verliesfunctie; w is de hele vector met twee gewichten. De kleine indices 1 en 2 benoemen haar componenten; in Python staan die op posities w[0] en w[1]. Je kunt L als een gewone functie schrijven die één lijst ontvangt:

def verlies(w):
    return w[0] ** 2 + 4 * w[1] ** 2

print(verlies([3, 2]))     # 25
print(verlies([3.1, 2]))   # ongeveer 25.61
print(verlies([3, 2.1]))   # ongeveer 26.64

Houd het tweede gewicht vast en differentieer naar het eerste: de helling is tweemaal het eerste gewicht, hier 6. Houd het eerste vast en differentieer naar het tweede: viermaal tweemaal het tweede gewicht, hier 16. De gradiënt (gradient) verzamelt die partiële afgeleiden in één vector:

∇L(w)=[2w18w2]

Het teken ∇ heet “nabla” en betekent hier “verzamel de hellingen”. Als de gradiënt niet nul is, wijst hij lokaal naar de sterkste stijging bij richtingen met gelijke Euclidische lengte; voor dalen kies je de tegenovergestelde richting. Een nulgradiënt zoals (0, 0) heeft geen richting.

w = [3, 2]
g = [2 * w[0], 8 * w[1]]
print(g)   # [6, 16]

Maak grad_kom(w) voor deze tweedimensionale verliesfunctie. Vergeet de factor vier niet: de tweede helling is achtmaal het tweede gewicht.

01
CHECKPOINTHoud de andere coördinaat stil

2. Controleer zonder dezelfde afleidingsregel

Je kunt elke component onafhankelijk schatten met een centraal verschil. Voor het eerste gewicht gebruik je (3.1, 2) en (2.9, 2): verliezen 25.61 en 24.41. Het verschil 1.2 over afstand 0.2 geeft helling 6.

Voor het tweede gebruik je (3, 2.1) en (3, 1.9): verliezen 26.64 en 23.44. Het verschil 3.2 gedeeld door 0.2 geeft 16. De andere component blijft telkens gelijk.

w = [3, 2]
h = 0.1
plus = w.copy()
minus = w.copy()
plus[0] = plus[0] + h
minus[0] = minus[0] - h
verschil = verlies(plus) - verlies(minus)
print(verschil / (2 * h))   # ongeveer 6
print(w)                   # [3, 2]

.copy() maakt hier een nieuwe lijst met dezelfde getallen. Alleen plus = w zou dezelfde lijst een tweede naam geven; wijzigen via plus zou dan ook w veranderen. Dat is de veelgemaakte fout die de controle op een verkeerd punt laat rekenen.

Bouw numerieke_grad(f, w, h=1e-5) voor h groter dan nul: loop met i over alle componenten, maak binnen die lus twee verse kopieën en varieer alleen positie i. Vraag f bij beide lijsten op en voeg de centrale schatting aan een resultaatlijst toe. Dit werkt ook voor drie of meer gewichten; h heeft dezelfde standaardbetekenis als in Helling.

02
CHECKPOINTControleer iedere component onafhankelijk

3. Eén gezamenlijke stap omlaag

Bij gradiëntafdaling (gradient descent) trek je een klein deel van de gradiënt van de gewichten af. Hoe groot dat deel is, bepaalt de leersnelheid (learning rate). De Griekse letter η, uitgesproken “eta”, benoemt deze factor.

wnieuw=w−η∇L(w)

De gradiënt hoort helemaal bij de oude vector. Bij w = (3, 2), g = (6, 16) en eta = 0.15 wordt de eerste component 3 − 0.15 × 6 = 2.1. De tweede wordt 2 − 0.15 × 16 = −0.4.

w = [3, 2]
g = [6, 16]
eta = 0.15
nieuw = []
for i in range(len(w)):
    nieuw.append(w[i] - eta * g[i])
print(nieuw)   # ongeveer [2.1, -0.4]
print(verlies(nieuw))   # ongeveer 5.05

Het nieuwe verlies is 2.1² + 4 × (−0.4)² = 4.41 + 0.64 = 5.05: lager dan 25. Zet in het diagram één stap en vergelijk de getallen. Herstart en probeer leersnelheid 0.4: je krijgt (0.6, −4.4), met verlies 77.8, dus juist méér verlies.

Een negatieve gradiëntrichting garandeert geen verbetering bij een willekeurig grote stap. Het punt kan zelfs buiten het diagram vallen; controleer daarom ook de getallen. Maak update(w, g, eta) voor even lange lijsten, met een nieuwe uitvoerlijst zodat w behouden blijft.

03
CHECKPOINTAlle gewichten tegelijk aanpassen

Wat neem je mee?

  • De gradiënt verzamelt één helling per gewicht; de andere gewichten blijven bij iedere partiële afgeleide vast.
  • Centrale verschillen op verse kopieën leveren een onafhankelijke numerieke controle.
  • Bereken de hele gradiënt op de oude gewichten; een te grote leersnelheid kan het verlies verhogen.

Je kunt nu gevoeligheden berekenen en een leersprong zetten. Hierna onderzoek je onzekerheid en kansen; later gebruik je deze hellingen om echte modellen te trainen.

Verder lezen & bronnen

Inhoud gecontroleerd op 2026-10-27.
DE VOLGENDE STAPWat betekent een kans?
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
Houd de andere coördinaat stil

Maak grad_kom(w) voor de verliesfunctie w[0]**2 + 4*w[1]**2.

Een hint

Houd telkens de andere component vast. De factor 4 blijft bij het differentiëren staan.

02
Controleer iedere component onafhankelijk

Maak numerieke_grad(f, w, h=1e-5) voor h groter dan nul en een functie die één lijst ontvangt. Laat w intact.

Een hint

Maak binnen iedere indexlus plus=w.copy() en minus=w.copy(). Varieer alleen die index en voeg de centrale schatting aan een nieuwe lijst toe.

03
Alle gewichten tegelijk aanpassen

Maak update(w, g, eta) voor even lange lijsten en geef een nieuwe gewichtenvector terug.

Een hint

Voeg voor elke i w[i]-eta*g[i] toe aan een nieuwe lijst. Verander w zelf niet.

Vastgelopen? Bekijk de voorbeeldoplossing
def grad_kom(w):
    return [2 * w[0], 8 * w[1]]


def numerieke_grad(f, w, h=1e-5):
    resultaat = []
    for i in range(len(w)):
        plus = w.copy()
        minus = w.copy()
        plus[i] = plus[i] + h
        minus[i] = minus[i] - h
        verschil = f(plus) - f(minus)
        resultaat.append(verschil / (2 * h))
    return resultaat


def update(w, g, eta):
    nieuw = []
    for i in range(len(w)):
        nieuw.append(w[i] - eta * g[i])
    return nieuw

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