Kausal inferens
Kunna använda DAG:ar, confounders och interventioner för att resonera om orsak i observationsdata.
Förkunskaper
Intuition
Randomiserade experiment ger kausalitet gratis. Men ofta finns bara observationsdata — och då måste antagandena göras explicita.
Rita en DAG (riktad acyklisk graf) över vad som påverkar vad:
erfarenhet
↙ ↘
verktyg → produktivitet
Här är erfarenhet en confounder: den påverkar både om man använder verktyget och hur produktiv man är. Jämför man bara verktygsanvändare med icke-användare mäter man till stor del erfarenhet. Lösningen är att kontrollera för erfarenhet (stratifiera, matcha eller inkludera i modellen).
Men kontrollera inte för allt. Det leder till nästa fälla.
Formellt
Tre strukturer, tre olika beslut:
| Struktur | Bild | Åtgärd |
|---|---|---|
| Confounder (gemensam orsak) | kontrollera för Z | |
| Mediator (kedja) | kontrollera inte om du vill ha totaleffekten | |
| Collider (gemensam effekt) | kontrollera aldrig för Z — det skapar ett falskt samband |
Collider bias i praktiken: bland antagna studenter korrelerar högskoleprov negativt med betyg, trots att de är okorrelerade i befolkningen — antagningen är en collider. Samma sak i ML: om du bara analyserar användare som stannat kvar i tjänsten, är «stannat kvar» en collider och alla samband inom den gruppen blir snedvridna.
Backdoor-kriteriet (Pearl) formaliserar valet: kontrollera för en mängd som blockerar alla bakdörrsvägar från till utan att öppna collider-vägar. Då är .
Metoder när ingen randomisering finns: matchning, propensity scores, difference-in-differences, instrumentvariabler, regression discontinuity. Alla vilar på antaganden som inte går att testa i datan — därför ska de skrivas ut.
Kod
import numpy as np
import statsmodels.api as sm
rng = np.random.default_rng(0); n = 5000
erfarenhet = rng.normal(0, 1, n) # confounder
verktyg = (rng.normal(0, 1, n) + 0.8 * erfarenhet > 0).astype(float)
produktivitet = 0.3 * verktyg + 1.0 * erfarenhet + rng.normal(0, 0.5, n) # sann effekt: 0,3
X1 = sm.add_constant(verktyg)
print("utan kontroll:", sm.OLS(produktivitet, X1).fit().params[1].round(3)) # ≈ 0.95 ← 3× för högt
X2 = sm.add_constant(np.column_stack([verktyg, erfarenhet]))
print("med kontroll: ", sm.OLS(produktivitet, X2).fit().params[1].round(3)) # ≈ 0.30 ← rätt
# Collider: kontrollera för något BÅDA orsakar → falskt samband uppstår
anstalld = (verktyg + produktivitet + rng.normal(0, 0.3, n) > 1.2)
m = anstalld
print("bland anställda:", np.corrcoef(verktyg[m], produktivitet[m])[0, 1].round(3)) # negativt!
Behärskning innebär
- Ritar en DAG och identifierar confounders
- Skiljer confounding från collider bias
- Vet när observationsdata kan ge kausala svar
Logga in för att göra övningarna och bygga upp din behärskning.
Källor
- Pearl & Mackenzie — The Book of Why (referens) — CC BY-SA 4.0 (uppslagsverk)
- Wikipedia — Confounding (CC BY-SA 4.0) — CC BY-SA 4.0
- Wikipedia — Collider (statistics) (CC BY-SA 4.0) — CC BY-SA 4.0