Werkplaats / De werkplaats
In jouw eigen tempo
← Klassieke machine learning
MODULE 04 · LES 14

Meer kunnen passen is niet altijd beter

Scheid bias en variantie, bouw polynomiale features en tem coëfficiënten met ridge.

75 min3 checkpoints
DIT GA JE ONTDEKKEN
  • Je berekent de empirische bias-variantie-identiteit voor herhaalde voorspellingen.
  • Je onderzoekt modelcapaciteit met polynomiale features en regularisatie.

Een model voorspelt voor dezelfde plant telkens iets anders wanneer je het op een nieuwe steekproef traint. Een ander model voorspelt juist bijna steeds hetzelfde, maar zit structureel te laag. Deze twee problemen vragen om een andere diagnose dan alleen één trainingsscore.

Bias beschrijft de afwijking van de gemiddelde voorspelling; variantie (variance) beschrijft de spreiding tussen herhaalde fits. Een model met te weinig vrijheid kan een patroon missen: underfitting. Een flexibel model kan toevallige trainingsdetails volgen: overfitting.

1. Houd de invoer vast en herhaal de training

Stel dat je voor één vaste invoer de voorspellingen [0,2] krijgt uit twee verschillende trainingssets. In deze simulatie kennen we de ruisvrije waarheid f = 4. De gemiddelde voorspelling m is 1, dus de gekwadrateerde bias is (1−4)² = 9.

De afwijkingen rond het gemiddelde zijn −1 en 1; hun gemiddelde kwadraat is 1. De directe fouten tegen f zijn −4 en −2: MSE = (16+4)/2 = 10. Inderdaad: bias² + variantie = 9+1 = 10.

bias2=(m−f)2V=1N∑(pi−m)2MSE=bias2+V

N telt de herhaalde voorspellingen; p_i is één voorspelling en V hun populatievariantie. Gebruik hier deler N, niet N−1, zodat de identiteit exact voor deze gegeven lijst geldt.

predictions = [0, 2]
f = 4
m = sum(predictions) / len(predictions)
bias2 = (m - f) ** 2
v, mse = 0, 0
for p in predictions:
    v = v + (p - m) ** 2
    mse = mse + (p - f) ** 2
v = v / len(predictions)
mse = mse / len(predictions)
print(bias2, v, mse)  # 9.0 1.0 10.0

Maak decompositie(predictions,true_value) als (bias2,variance,mse) en weiger lege invoer. Veelgemaakte fout: spreiding tussen voorspellingen bij verschillende planten gebruiken; dan meng je verschillende invoeren met trainingsvariatie.

Bij een nieuw doel met onafhankelijke, nulgemiddelde ruis komt in verwachting de ruisvariantie bij de fout. In echte data ken je f meestal niet: deze oefening is een inzichtelijke identiteit, geen truc om verborgen waarheid uit metingen te halen.

01
CHECKPOINTScheid gemiddelde afwijking en spreiding

2. Geef het model meer mogelijke vormen

Een rechte lijn kan geen bocht maken. Polynomiale features voegen machten van x toe: graad 2 maakt van x de rij [1,x,x²]. Het model combineert die kolommen nog steeds lineair met coëfficiënten.

y^=w0+w1x+w2x2

w_0 is het intercept; de andere gewichten horen bij hun machten. Bij x = −1,0,1 zijn de featurerijen [1,−1,1], [1,0,0] en [1,1,1]. Coëfficiënten [1,2,0] geven voorspellingen −1,1,3.

xs = [-1, 0, 1]
matrix = []
for x in xs:
    rij = []
    for macht in range(3):
        rij.append(x ** macht)
    matrix.append(rij)
print(matrix)
# [[1, -1, 1], [1, 0, 0], [1, 1, 1]]
w = [1, 2, 0]
for rij in matrix:
    p = sum(a * b for a, b in zip(rij, w))
    print(p)
# -1, 1, 3

Maak poly_features(xs,graad) voor een niet-negatieve gehele graad; ongeldige graden geven ValueError. Graad nul geeft alleen de constante kolom. Meer machten betekenen meer vrijheid, maar garanderen geen betere voorspelling op onbekende data.

WERKELIJK FITTEN, WERKELIJK METENHoeveel kromming helpt?

Twaalf vaste trainingspunten: sin(πx) plus ruis. De oranje curve is het bekende simulatiepatroon; groen is je gefitte polynoom.

-101-101
Training-MSE0.2321Validatie-MSE0.2056

Validatie gebruikt 41 andere x-waarden met ruisvrije doelen. Die waarheid kennen we alleen doordat dit een simulatie is.

Laat alpha op nul staan en vergelijk graad 1,3 en 9. Voorspel eerst of de trainingsfout daalt en of validatie mee blijft verbeteren; controleer daarna de getallen. Het diagram kent de ruisvrije sinus alleen doordat dit gesimuleerde gegevens zijn.

02
CHECKPOINTMaak de modelklasse flexibeler

3. Straf grote coëfficiënten, behalve het intercept

Ridge minimaliseert hier de som van kwadratische trainingsfouten plus alpha maal de som van gekwadrateerde gewichten, met uitzondering van w_0. Alpha is niet-negatief; groter betekent meer straf. Die schaal hoort bij een som van fouten, niet bij een gemiddelde.

Neem voor graad 1 x = [−1,0,1] en y = [−1,1,3]. De ontwerp-matrix X heeft rijen [1,−1], [1,0] en [1,1]. Vermenigvuldigen geeft XᵀX met diagonaal [3,2] en nullen daarbuiten; Xᵀy is [3,4].

(XTX+αD)w=XTy

D is een diagonale strafmatrix: eerst nul, daarna enen. Zonder straf lossen 3w_0 = 3 en 2w_1 = 4 op naar [1,2]. Met alpha = 2 wordt de tweede vergelijking 4w_1 = 4: [1,1], terwijl het intercept hier gelijk blijft.

import numpy as np
X = np.array([[1, -1], [1, 0], [1, 1]])
y = np.array([-1, 1, 3])
D = np.eye(2)
D[0, 0] = 0
for alpha in [0, 2]:
    A = X.T @ X + alpha * D
    rhs = X.T @ y
    w = np.linalg.solve(A, rhs)
    print(w.tolist())  # [1, 2]; [1, 1]

X.T wisselt rijen en kolommen; @ is matrixvermenigvuldiging. np.eye(2) maakt een eenheidsmatrix en solve(A,rhs) lost A maal w = rhs op. Gebruik geen elementgewijze deling: buiten dit symmetrische voorbeeld kan A ook niet-nulwaarden buiten de diagonaal hebben.

Maak ridge_fit(xs,ys,graad,alpha) met een floatmatrix uit je eigen features en geef de coëfficiënten als lijst in oplopende macht terug. Weiger negatieve alpha of graad en lege/ongelijke paren. Gebruik bij alpha nul gegevens waarvoor het stelsel uniek oplosbaar is; gedrag bij een singulier stelsel valt buiten deze opdracht.

Zet in het diagram graad 9 vast en verhoog alpha. Bekijk hoeveel de curve en beide fouten veranderen. Schaling beïnvloedt de straf; kies graad en alpha met validatie en bewaar de eindtest voor de laatste beoordeling.

03
CHECKPOINTBeperk coëfficiënten met een expliciete straf

Wat neem je mee?

  • Bias en variantie bekijken herhaalde fits bij dezelfde invoer.
  • Polynomiale features vergroten de modelvrijheid; ridge begrenst de coëfficiënten.
  • De simulatie verklaart gedrag, terwijl onafhankelijke evaluatie de uiteindelijke keuze onderbouwt.

Hierna onderzoek je wat je kunt leren wanneer er helemaal geen labels beschikbaar zijn.

DE VOLGENDE STAPZoek groepen zonder antwoordlabels
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
Scheid gemiddelde afwijking en spreiding

Schrijf decompositie(predictions,true_value) als (bias2,variance,mse), met ValueError bij lege invoer.

Een hint

Gebruik de populatievariantie met deler n, zodat de identiteit voor de gegeven lijst exact klopt.

02
Maak de modelklasse flexibeler

Schrijf poly_features(xs,graad), met ValueError als graad geen niet-negatief geheel getal is.

Een hint

Gebruik per x de machten van nul tot en met graad.

03
Beperk coëfficiënten met een expliciete straf

Schrijf ridge_fit(xs,ys,graad,alpha) en geef de coëfficiënten als lijst in oplopende macht. Bij alpha nul gebruiken we uniek oplosbare stelsels.

Een hint

Maak X met poly_features en een diagonale strafmatrix waarvan D[0,0]=0.

Vastgelopen? Bekijk de voorbeeldoplossing
def decompositie(predictions,true_value):
    if not predictions:
        raise ValueError("Geen voorspellingen")
    mean=sum(predictions)/len(predictions)
    bias2=(mean-true_value)**2
    variance=sum((p-mean)**2 for p in predictions)/len(predictions)
    mse=sum((p-true_value)**2 for p in predictions)/len(predictions)
    return bias2,variance,mse

def poly_features(xs,graad):
    if type(graad) is not int or graad<0:
        raise ValueError("Negatieve graad")
    return [[x**p for p in range(graad+1)] for x in xs]

def ridge_fit(xs,ys,graad,alpha):
    import numpy as np
    if alpha<0 or not xs or len(xs)!=len(ys):
        raise ValueError("Ongeldige ridge-data")
    x=np.array(poly_features(xs,graad),dtype=float)
    penalty=np.eye(graad+1)
    penalty[0,0]=0
    return np.linalg.solve(x.T@x+alpha*penalty,x.T@np.array(ys)).tolist()

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