Werkplaats / De werkplaats
In jouw eigen tempo
← Klassieke machine learning
MODULE 03 · LES 10

Laat verschillende bomen samen beslissen

Maak bootstrapsteekproeven, vind out-of-bag-rijen en train een echt random forest.

55 min3 checkpoints
DIT GA JE ONTDEKKEN
  • Je onderscheidt bootstrapping en willekeurige featurekeuze.
  • Je traint een reproduceerbaar forest en begrijpt welke rijen een boom niet heeft gezien.

Je beslisboom ziet één extra zieke plant en kiest ineens een andere eerste vraag. Zo'n verandering kan alle volgende takken beïnvloeden. Wat gebeurt er als je meerdere bomen elk een iets andere versie van dezelfde training geeft?

Bagging laat modellen op verschillende steekproeven leren en combineert hun uitkomsten. Een random forest doet dit met bomen en beperkt bovendien willekeurig welke features een split mag onderzoeken. Minder gelijksoortige fouten kunnen elkaar daardoor gedeeltelijk uitmiddelen.

1. Trek rijen met teruglegging

Geef vier trainingsrijen de indices 0,1,2,3. Trek vier keer, waarbij na elke trekking alle vier indices weer beschikbaar zijn. Een mogelijke uitkomst is [1,0,2,0]: dezelfde lengte als de training, maar rij 0 telt tweemaal en rij 3 ontbreekt.

Zo'n bootstrapsteekproef bewaart dus zowel herhalingen als volgorde. Zet de uitkomst niet om in een verzameling: daarmee verdwijnen de extra stemmen van herhaalde rijen.

import random
rng = random.Random(1)
indices = []
for i in range(4):
    indices.append(rng.randrange(4))
print(indices)  # [1, 0, 2, 0]

Random(1) maakt een eigen generator met seed 1. randrange(4) kiest een index van 0 tot en met 3; iedere aanroep verplaatst de generator naar zijn volgende toestand. Maak de generator daarom één keer vóór de lus.

Een vaste seed laat je dezelfde proef herhalen. Hij maakt de steekproef niet eerlijker of representatiever. De visualisatie gebruikt een andere eenvoudige generator: dezelfde seed hoeft tussen die generator en Python geen gelijke reeks te geven.

TREKKEN MET TERUGLEGGINGAcht trekkingen zijn niet acht unieke rijen

Elke rij A–H heeft bij iedere trekking dezelfde kans. De tellingen laten zien welke rijen deze steekproef mist.

Rij A2×
Rij B1×
Rij C1×
Rij D0×
Rij E1×
Rij F0×
Rij G1×
Rij H2×

Getrokken volgorde:

BHEHAGCA
Trekkingen8Unieke rijen6Out of bagD F

Seed 7. Dit voorbeeld gebruikt een vaste eenvoudige generator voor herhaalbaarheid; Python gebruikt zijn eigen generator.

Maak bootstrap(n,seed) voor een positief geheel aantal rijen. Trek n indices met één lokale random.Random(seed) en randrange(n); een ongeldige n geeft ValueError. De globale randomgenerator mag door jouw functie niet veranderen.

01
CHECKPOINTTrek evenveel rijen, met teruglegging

2. Zoek de rijen die deze boom niet zag

Bij [1,0,2,0] zijn de aanwezige indices 0,1,2. Rij 3 is out of bag (OOB): buiten deze steekproef. Dat is geen fout, maar een gevolg van teruglegging.

aanwezig = set(indices)
buiten = []
for i in range(4):
    if i not in aanwezig:
        buiten.append(i)
print(buiten)  # [3]

Hier is een set wél geschikt, omdat alleen aanwezigheid telt. De oplopende lus zorgt meteen voor gesorteerde uitvoer. Maak buiten_steekproef(n,indices) voor n ≥ 0 en geldige getrokken indices; een lege steekproef laat alle rijen buiten.

Waarom ontbreekt überhaupt een rij? Eén gekozen rij wordt bij iedere trekking met kans 3/4 gemist. Bij vier onafhankelijke trekkingen vermenigvuldig je die kansen:

P(ontbreekt)=(34)4≈0.316

Dit is de kans voor één bepaalde rij, niet het gegarandeerde aandeel ontbrekende rijen in iedere trekking. Voor OOB-evaluatie laat je een rij alleen voorspellen door bomen waarvoor hij ontbrak. Bomen die hem wel zagen zouden informatie uit hun training terugbrengen in die beoordeling.

OOB is nuttig, maar vervangt geen passende groeps- of tijdsplitsing. Bij opeenvolgende metingen van dezelfde plant kan gewone rijbootstrapping informatie tussen sterk verwante voorbeelden mengen.

02
CHECKPOINTZoek welke rijen deze boom niet zag

3. Combineer echte bomen met de bibliotheek

Nu train je RandomForestClassifier. Net als in het regressielab is x een tabel: iedere binnenste lijst is één rij, iedere positie een feature. y bevat precies één klasse per rij; fit leert en predict verwerkt nieuwe rijen.

from sklearn.ensemble import (
    RandomForestClassifier)
x = [[0, 0], [0, 1], [1, 0], [1, 1]]
y = [0, 0, 1, 1]
model = RandomForestClassifier(
    n_estimators=32, max_depth=4,
    max_features="sqrt", bootstrap=True,
    random_state=7, n_jobs=1)
model.fit(x, y)
print(model.predict([[0, .5], [1, .5]]))
# [0 1]

n_estimators kiest 32 bomen en max_depth begrenst elke boom tot vier niveaus met vragen. max_features="sqrt" bepaalt hoeveel willekeurige featurekandidaten een split in beginsel onderzoekt; bij twee features is dat één. De bibliotheek kan verder zoeken als die kandidaten geen geldige split opleveren.

bootstrap=True maakt de rijsteekproeven; random_state=7 zet de toevalsbron vast. n_jobs=1 schakelt parallelle uitvoering uit. Maak fit_forest(x,y) met precies deze instellingen en geef het gefitte model terug.

Veelgemaakte fout: denken dat het forest altijd een harde meerderheid van boomlabels neemt. Deze bibliotheek middelt de klassekansen van de bomen. Drie bomen met kansen 0.49, 0.49 en 0.90 voor klasse 1 laten het verschil zien:

kansen = [0.49, 0.49, 0.90]
gemiddelde = sum(kansen) / len(kansen)
print(gemiddelde)  # ongeveer 0.626667
print(gemiddelde >= 0.5)  # True

Twee harde boomkeuzes zouden klasse 0 kiezen; de gemiddelde kans kiest klasse 1. Dit zijn voorbeeldkansen om de combinatieregel te begrijpen, geen beweerde uitkomsten van het model hierboven.

Meer bomen kunnen toevallige schommelingen verminderen, maar herstellen geen systematisch verkeerde labels. Ook 32 bomen moeten op onafhankelijke gegevens worden beoordeeld.

03
CHECKPOINTTrain een echt ensemble

Wat neem je mee?

  • Bootstrapping trekt met teruglegging; dubbele en ontbrekende rijen zijn onderdeel van het ontwerp.
  • OOB-voorspellingen gebruiken per rij alleen bomen die die rij niet zagen.
  • Een forest varieert rijen én featurekeuze en combineert klassekansen.

Hierna bouwen modellen niet naast elkaar, maar na elkaar verder aan de resterende fout.

Verder lezen & bronnen

Inhoud gecontroleerd op 2026-10-28.
DE VOLGENDE STAPLaat het volgende model de resterende fout leren
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
Trek evenveel rijen, met teruglegging

Schrijf bootstrap(n,seed) met één lokale random.Random(seed) en n randrange(n)-trekkingen. Weiger n die geen positief geheel getal is.

Een hint

random.Random(seed).randrange(n) levert één index; herhaal n keer met dezelfde generator.

02
Zoek welke rijen deze boom niet zag

Schrijf buiten_steekproef(n,indices) als gesorteerde lijst ontbrekende indices.

Een hint

Neem het verschil tussen set(range(n)) en de verzameling getrokken indices.

03
Train een echt ensemble

Schrijf fit_forest(x,y) met de genoemde instellingen.

Een hint

Maak het model met vaste parameters, roep fit aan en geef het model terug.

Vastgelopen? Bekijk de voorbeeldoplossing
def bootstrap(n, seed):
    import random
    if type(n) is not int or n < 1:
        raise ValueError("Positief geheel aantal rijen vereist")
    rng = random.Random(seed)
    indices = []
    for i in range(n):
        indices.append(rng.randrange(n))
    return indices


def buiten_steekproef(n, indices):
    aanwezig = set(indices)
    buiten = []
    for i in range(n):
        if i not in aanwezig:
            buiten.append(i)
    return buiten


def fit_forest(x, y):
    from sklearn.ensemble import RandomForestClassifier
    model = RandomForestClassifier(
        n_estimators=32, max_depth=4,
        max_features="sqrt", bootstrap=True,
        random_state=7, n_jobs=1)
    model.fit(x, y)
    return model

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