Bootstrap och resampling
Kunna skatta osäkerhet i en modells mått med bootstrap.
Förkunskaper
- EKonfidensintervallkrävs
- EMonte Carlo-metoderkrävs
Intuition
Du har ett stickprov och vill veta hur osäker din skattning är. Idealt skulle du dra hundra nya stickprov ur populationen — men du har bara detta.
Bootstrap: behandla ditt stickprov som om det vore populationen. Dra n observationer med återläggning, beräkna måttet, upprepa några tusen gånger. Spridningen i de tusen värdena skattar spridningen i din skattning.
Varför det är så användbart i ML: det fungerar för vilket mått som helst — F1, AUC, BLEU, grundningsgrad, kostnad per löst uppgift, medianlatens. Formler finns bara för de enklaste måtten; bootstrap behöver inga.
Formellt
Percentilmetoden (enklast, oftast tillräcklig): kör B ≈ 2 000–10 000 resamplingar, sortera skattningarna, ta percentil 2,5 och 97,5.
Varianter att känna till:
| Variant | När |
|---|---|
| Percentil | standardvalet |
| BCa (bias-corrected and accelerated) | skev fördelning eller bias — mer korrekt täckning |
| Parad bootstrap | jämförelse av två modeller på samma fall — resampla fallen, behåll paren |
| Block-bootstrap | tidsserier — resampla sammanhängande block, inte enskilda punkter |
| Stratifierad | bevara klassfördelningen vid obalans |
Där bootstrap inte fungerar:
- Extremvärden (max, min) — resamplingen kan inte se bortom stickprovets största värde.
- Mycket små stickprov (n < 20) — resamplingarna blir för lika varandra.
- Beroende data utan blockstruktur — oberoenderesampling underskattar osäkerheten kraftigt.
Den vanligaste feltillämpningen i ML: att resampla förutsägelser i stället för testfall. Det är fallen som är den slumpmässiga enheten — och vid jämförelse mellan modeller måste samma resamplade index användas för båda.
Kod
import numpy as np
from sklearn.metrics import f1_score
def bootstrap_ki(y, pred, matt=lambda y, p: f1_score(y, p, average="macro"),
B=5000, alfa=0.05, seed=0):
rng = np.random.default_rng(seed)
n = len(y)
varden = np.empty(B)
for b in range(B):
idx = rng.integers(0, n, n) # med återläggning
varden[b] = matt(y[idx], pred[idx])
lo, hi = np.percentile(varden, [100*alfa/2, 100*(1-alfa/2)])
return {"skattning": float(matt(y, pred)), "ki": (float(lo), float(hi))}
def parad_bootstrap(y, pred_a, pred_b, matt, B=5000, seed=0):
"""SAMMA index för båda modellerna — annars mäter du fel sak."""
rng = np.random.default_rng(seed); n = len(y)
diff = np.empty(B)
for b in range(B):
idx = rng.integers(0, n, n)
diff[b] = matt(y[idx], pred_b[idx]) - matt(y[idx], pred_a[idx])
lo, hi = np.percentile(diff, [2.5, 97.5])
return {"skillnad": float(diff.mean()), "ki": (float(lo), float(hi)),
"andel_over_noll": float((diff > 0).mean())}
Behärskning innebär
- Skattar osäkerhet i ett mått med bootstrap
- Väljer rätt bootstrap-variant
- Känner till metodens gränser
Logga in för att göra övningarna och bygga upp din behärskning.
Källor
- Wikipedia — Bootstrapping (statistics) (CC BY-SA 4.0) — CC BY-SA 4.0
- Efron & Tibshirani — An Introduction to the Bootstrap (referens) — CC BY-SA 4.0 (uppslagsverk)