9.2 Monte Carlo som inferensverktøy: simulert sannsynlighet, p-verdi og styrke
Estimér det du ikke kan regne: sannsynligheter, forventninger, p-verdier, styrke og feilforplantning ved gjentatte trekk.
- Python/MC totalt i 8 av 9 sett siden des. 2023. Denne delen (sjanger N undertype 3) er testet konkret: simulert p-verdi (Des23), simulert styrke (Mai25), «hvilken lyspære varer lengst»-simulering (Des24), feilforplantning ved simulering mot deltametoden (Mai24), og at MC-estimatet er forventningsrett (Mai26 spør eksplisitt om variansen ).
- Sjanger N betyr en oppgave der du leser, skriver eller fullfører programkode. Prioritet: kunne — dette er sammen med kap. 9.1 det som skiller en A.
Hvor poengene sitter: i å trekke under riktig fordeling — under for en p-verdi, under alternativet for styrke — og i å skrive kode som kjører. Ingen av oppskriftene står i formelsamlingen; de må kunnes aktivt. Alle fire kodeskjelettene under er komplette og faktisk kjørt.
np.random.uniform/normal, np.mean som estimat, np.var(..., ddof=1)), på styrke- og testritualet i kap. 7.3 (kritisk grense, styrke, re-standardisering under ) og på deltametoden i kap. 5.3 (feilforplantning gjennom en funksjon). Maks/min av flere levetider er fra kap. 4.1.Sist du var her — de tre resultatene MC-inferensen hviler på (ferdig oppfrisket):
1. np.mean(betingelse) estimerer — andelen True (fra kap. 9.1).
2. Styrke (7.3): for den ensidige z-testen mot forkaster vi når ; styrken regnes med data trukket under den sanne .
3. Deltametoden (5.3): — en tilnærming som kan kontrolleres ved simulering.
Du trenger ikke ny teori — bare å kombinere disse med numpy.
Kapitlet lærer deg fire oppskrifter som SKAL sitte: (i) simulert sannsynlighet/forventning for en sammensatt størrelse, (ii) simulert p-verdi, (iii) simulert styrke, og (iv) feilforplantning ved simulering — med deltametoden som fasit å kontrollere mot. Vi starter med grunnprinsippet (løkke 1) og tar så én oppskrift per løkke.
Samlet kjernetid ≈ 65 min. Naturlige pausepunkter er markert mellom løkkene. All kode er komplett og kjørt; Monte Carlo-svar varierer litt med seed, så bruk stor (antall simuleringer) og se på om tallet stemmer med den analytiske fasiten.
Løkke 1 — Grunnprinsippet: sannsynlighet som forventet indikator (~12 min)
En sannsynlighet er altså en forventning. Og en forventning estimerer vi med et gjennomsnitt. Simulerer vi hendelsen ganger, er Monte Carlo-estimatet
som i numpy er nøyaktig np.mean(betingelse) — andelen trekk der betingelsen er sann. Samme idé gir en forventning som np.mean(g(x)).
Standardfeilen er , som avtar som : firedobler du antall simuleringer, halveres usikkerheten. Det er derfor vi bruker stor (ofte –). Merk skillet: er antall simuleringer (styrer presisjonen i estimatet), mens en eventuell utvalgsstørrelse inne i hver simulering er en helt annen størrelse (den hører til problemet vi simulerer).
En måling er (varians 225, altså ). Estimer med Monte Carlo, og sammenlign med fasit.
import numpy as np
def simuler_sanns(B):
x = np.random.normal(loc=100, scale=15, size=B) # scale = SD = sqrt(225) = 15
return np.mean(x > 120) # andel over 120 = estimat paa P(X>120)
np.random.seed(0)
print(simuler_sanns(10**6)) # ~ 0.0912Kjørt gir dette . Fasit: . ✓
Usikkerheten: med og er standardfeilen — tre desimaler er trygge. Hadde vi brukt , ville SE vært , altfor grovt.
> Sensornotat: np.mean(x > 120) — andel = sannsynlighet. Og scale=15, ikke 225.
(Innstegsoppgave.) La være hendelsen «».
a) Hva er forventningen til indikatoren ?
b) Hvilket numpy-uttrykk estimerer fra en vektor x av trekk?
c) Hvordan endres standardfeilen i estimatet om du firedobler antall simuleringer ?
Løkke 2 — Oppskrift (i): sannsynlighet/forventning for en sammensatt størrelse (~12 min)
Når størrelsen du spør om er en transformasjon eller kombinasjon av flere variable — maks av levetider, sum, forhold — er det ofte enklere å simulere enn å utlede fordelingen. Oppskriften:
1. Trekk inngangsvariablene vektorisert (én vektor per variabel, lengde ).
2. Regn den sammensatte størrelsen elementvis (np.maximum, +, /, …).
3. Estimer: np.mean(størrelse > c) for en sannsynlighet, np.mean(størrelse) for en forventning.
For et parallellsystem er levetiden (systemet lever til den siste komponenten dør — kobling til kap. 4.1); for et seriesystem er den . Slik unngår du å regne ut for hånd når du bare trenger et tall.
To uavhengige komponenter har eksponensialfordelte levetider med forventning og år. De er parallellkoblet, så systemet lever til den siste dør: . Estimer og , og kontroller mot fasit.
import numpy as np
def simuler_maks(B):
t1 = np.random.exponential(scale=4, size=B) # eksponensial, forventning beta=4
t2 = np.random.exponential(scale=6, size=B) # forventning beta=6
m = np.maximum(t1, t2) # parallell = maks
return m
np.random.seed(0)
m = simuler_maks(10**6)
print(np.mean(m > 8)) # ~ 0.363
print(np.mean(m)) # ~ 7.60(Merk: np.random.exponential(scale=beta) trekker eksponensial med forventning beta — samme fordeling som inversjonsmetoden -beta*np.log(1-u) fra kap. 9.1.)
Kontroll av : betyr at begge er , så . Kjørt gir . ✓
Kontroll av : for maks av to uavhengige eksponensiale er . Kjørt gir . ✓
> Sensornotat: parallell , serie . Å simulere det tunge -integralet på tre kodelinjer er hele poenget.
To uavhengige komponenter har eksponensielle levetider med forventning og . De er seriekoblet, så systemet dør når den første dør: .
a) Skriv en komplett funksjon simuler_min(B).
b) Hvilket kall estimerer , og hvilket estimerer ?
c) Det er kjent at av to uavhengige eksponensiale igjen er eksponensiell med rate lik summen av ratene. Regn og analytisk. (Rate .)
Løkke 3 — Oppskrift (ii): simulert p-verdi (~13 min)
1. Regn den observerte testobservatoren fra dataene.
2. Generer mange datasett under (parametrene satt til nullverdiene) og regn testobservatoren i hvert.
3. P-verdien er andelen simulerte observatorer minst så ekstreme som :
Retningen på «mer ekstrem» må stemme med : ensidig oppover bruker >=, ensidig nedover <=, og tosidig bruker np.mean(np.abs(t_sim) >= abs(t_obs)). Nøkkelkravet: generer under — bruker du feil fordeling, får du feil p-verdi.
Vi tester mot med kjent og observasjoner. Vi observerte , altså . Estimer p-verdien ved simulering og sammenlign med fasit.
import numpy as np
def simuler_pverdi(B):
n, mu0, sigma, z_obs = 20, 100, 15, 1.789
x = np.random.normal(loc=mu0, scale=sigma, size=(B, n)) # generer UNDER H0
xbar = x.mean(axis=1)
z = (xbar - mu0) / (sigma / np.sqrt(n)) # testobservator i hvert datasett
return np.mean(z >= z_obs) # andel minst saa ekstrem
np.random.seed(0)
print(simuler_pverdi(200000)) # ~ 0.037Kjørt gir . Fasit: siden er standardnormal under , er . ✓
Her kunne vi lest p-verdien rett av tabellen, og det er nettopp derfor eksemplet er lærerikt: simuleringen treffer fasiten. I en ekte eksamensoppgave er testobservatoren så sammensatt at tabellen ikke rekker til — da er dette den eneste veien.
> Sensornotat: matrisen size=(B, n) gir datasett à observasjoner; x.mean(axis=1) gir de gjennomsnittene. Alt under , fordi p-verdien måles under .
Vi tester tosidig mot , kjent , , og observerer .
a) Hvilken fordeling skal datasettene genereres under?
b) Endre siste linje i funksjonen fra Eksempel 3 slik at den gir den tosidige p-verdien.
c) Regn den tosidige fasiten analytisk. (Bruk .)
Løkke 4 — Oppskrift (iii): simulert styrke (~14 min)
Styrken er sannsynligheten for å forkaste når alternativet er sant (kap. 7.3). Simuleringen speiler definisjonen:
1. Generer mange datasett under alternativet — sett den sanne parameteren til (ikke !).
2. Utfør testen i hvert datasett: regn testobservatoren og avgjør om den havner i forkastningsområdet (f.eks. ).
3. Styrken er andelen datasett der vi forkaster: np.mean(forkast).
Den kritiske forskjellen fra p-verdien: p-verdien genererer under ; styrken genererer under alternativet . Bytter du om de to, får du enten (om du feilaktig trekker under ) i stedet for styrken, eller motsatt. Når antall simuleringer vokser, konvergerer den simulerte styrken mot den analytiske fasiten fra kap. 7.3.
En z-test har , kjent , , ensidig oppover, så vi forkaster når . Estimer styrken ved den sanne verdien , og sammenlign med den analytiske fasiten.
import numpy as np
def simuler_styrke(B):
n, mu0, mu1, sigma, z_alpha = 25, 200, 210, 20, 1.645
x = np.random.normal(loc=mu1, scale=sigma, size=(B, n)) # generer UNDER alternativet mu1
z = (x.mean(axis=1) - mu0) / (sigma / np.sqrt(n)) # testobservator (mot mu0)
return np.mean(z > z_alpha) # andel forkastninger = styrke
np.random.seed(0)
print(simuler_styrke(200000)) # ~ 0.804Kjørt gir . Fasit fra kap. 7.3: kritisk grense , og styrke . ✓
Legg merke til de to ulike rollene til : dataene trekkes med loc=mu1 (sannheten), men testobservatoren standardiseres mot mu0 (påstanden vi tester). Det er nettopp re-standardiseringen fra kap. 7.3, nå gjort automatisk av simuleringen.
> Sensornotat: trekk under , test mot . Trekker du under , får du bare tilbake.
Fyll ut de to manglende linjene i funksjonen under, som skal estimere styrken til en ensidig z-test på () når , kjent , , og den sanne forventningen er .
def simuler_styrke(B):
n, mu0, mu1, sigma, z_alpha = 16, 500, 520, 40, 1.645
x = ______ # (1) generer datasettene
z = (x.mean(axis=1) - mu0) / (sigma/np.sqrt(n))
return ______ # (2) andel forkastningera) Fyll ut linje (1) og (2).
b) Forklar med én setning hvorfor svaret nærmer seg den analytiske fasiten når øker.
c) Hva ville gått galt om linje (1) hadde loc=mu0?
Løkke 5 — Oppskrift (iv): feilforplantning ved simulering (~14 min)
Deltametoden (kap. 5.3) gir en tilnærmet varians for en avledet størrelse via deriverte. Simulering gir det samme — og fungerer som kontroll:
1. Trekk inngangsvariablene fra fordelingene sine (bruk scale= for normale innganger).
2. Regn per trekk, elementvis.
3. Estimer variansen med np.var(g_verdier, ddof=1) og standardfeilen som kvadratroten.
Stemmer den simulerte variansen med delta-formelen (eller summen for flere innganger), har du kontrollert begge. Avviker de mye, er enten delta-tilnærmingen dårlig (sterkt krum eller stor usikkerhet) eller så er det en regnefeil. ddof=1 er obligatorisk her — det er en empirisk varians.
Et panel har uavhengige, målte sider (forventning , varians ) og (forventning , varians ), begge normalfordelte. Arealet er . Deltametoden ga (kap. 5.3). Kontroller med simulering.
import numpy as np
def simuler_areal(B):
x = np.random.normal(8, np.sqrt(0.25), size=B) # scale = SD = sqrt(0.25) = 0.5
y = np.random.normal(5, np.sqrt(0.16), size=B) # scale = sqrt(0.16) = 0.4
a = x * y # g(x,y) = xy per trekk
return np.mean(a), np.var(a, ddof=1) # forventning og empirisk varians
np.random.seed(0)
middel, varians = simuler_areal(10**6)
print(middel) # ~ 40.0
print(varians) # ~ 16.5Kjørt gir og empirisk varians . Delta-fasit: . Simuleringen () bekrefter delta-svaret. ✓
> Sensornotat: pass på scale=np.sqrt(varians) (her 0,5 og 0,4), og ddof=1 i variansen. Uten ddof=1 blir avviket ubetydelig ved stor , men vanen skal sitte — det er en empirisk varians.
En strømningsrate er forholdet mellom uavhengige, normalfordelte målinger: volum (forventning , varians ) og tid (forventning , varians ). Deltametoden ga (kap. 5.3).
a) Skriv en funksjon simuler_R(B) som returnerer forventning og empirisk varians til .
b) Hvilke scale-verdier skal inn i de to np.random.normal-kallene?
c) Omtrent hvilket tall forventer du at np.var(..., ddof=1) gir, og hva bekrefter det?
- Simulere under feil fordeling. P-verdien genereres under ; styrken under alternativet . Bytter du om, får du der du skulle hatt styrken (eller motsatt). Dette er den alvorligste feilen i delen.
- Feil retning på «mer ekstrem». Ensidig oppover bruker >=, nedover <=, tosidig np.abs(...) >= abs(t_obs). La retningen følge .
- Glemme ddof=1 i feilforplantningen. En empirisk varians deler på ; bruk np.var(..., ddof=1).
- Forveksle antall simuleringer med utvalgsstørrelsen . styrer presisjonen i MC-estimatet (standardfeil ); er størrelsen på datasettet inne i hver simulering (hører til testen). De er to ulike tall.
- Sende variansen som scale. np.random.normal(loc, scale, ...) vil ha standardavviket — send (kap. 9.1-fella, går igjen her).
- Rapportere for få desimaler fra for liten . Med lite er MC-estimatet støyete; bruk stort og husk at svaret varierer med seed.
Begrepsbank
Kjernekortene for Monte Carlo-inferens, samlet.
Flashcard-stoff — hopp trygt over ved førstegangslesing; tidsanslaget gjelder kjernestoffet.
En sannsynlighet er en forventet indikator: . Derfor er np.mean(betingelse) et estimat på . En forventning estimeres tilsvarende med np.mean(g(x)).
Dette kapitlet er skrevet av Anthropics toppmodeller (Claude Opus og Claude Fable) og er foreløpig ikke manuelt gjennomgått — kvalitetskontrollen gjøres av uavhengige KI-agenter, og innmeldte feil rettes fortløpende. Funnet en feil? Meld fra, så retter vi den. Les mer om hvordan innholdet lages.
Skolesaga er en uavhengig læringsressurs og er ikke tilknyttet eller godkjent av Norges teknisk-naturvitenskapelige universitet. Dette er ikke offisielt studiemateriell. Les mer.