Approssimativo


35

Di recente ho osservato la simulazione Monte Carlo e l'ho usata per approssimare costanti come π (cerchio all'interno di un rettangolo, area proporzionata).

Tuttavia, non riesco a pensare a un metodo corrispondente per approssimare il valore di e [numero di Eulero] usando l'integrazione di Monte Carlo.

Hai qualche suggerimento su come farlo?


7
Ci sono molti, molti, molti modi per farlo. Che sia così potrebbe diventare evidente contemplando ciò che il Rcomando 2 + mean(exp(-lgamma(ceiling(1/runif(1e5))-1)))fa. (Se l'utilizzo della funzione Log Gamma ti dà fastidio, sostituiscilo con 2 + mean(1/factorial(ceiling(1/runif(1e5))-2)), che utilizza solo addizione, moltiplicazione, divisione e troncamento e ignora gli avvisi di overflow.) Ciò che potrebbe essere di maggiore interesse sarebbero simulazioni efficienti : puoi minimizzare il numero di passi computazionali necessari per stimare e con una certa precisione?
whuber

4
Che domanda deliziosa! Non vedo l'ora di leggere le risposte degli altri. Un modo in cui potresti davvero attirare l'attenzione su questa domanda - forse un'altra mezza dozzina di risposte - sarebbe quello di rivedere la domanda e chiedere risposte efficaci , come suggerisce whuber. È come catnip per gli utenti CV.
Sycorax dice di reintegrare Monica il

1
@EngrStudent Non sono sicuro che esista l'analogo geometrico per e . Semplicemente non è una quantità geometrica naturale (intesa per gioco di parole) come π .
Aksakal,

6
@Aksakal e è una quantità eccezionalmente geometrica. Al livello più elementare appare naturalmente nelle espressioni per le aree correlate alle iperbole. A un livello leggermente più avanzato è intimamente connesso a tutte le funzioni periodiche, comprese le funzioni trigonometriche, il cui contenuto geometrico è evidente. La vera sfida qui è che è così semplice simulare i valori relativi a e !
whuber

2
@StatsStudent: e per sé non è interessante. Tuttavia, se ciò porta a stimatori imparziali di quantità come
exp{0xf(y)dG(y)}
ciò può rivelarsi più utile per gli algoritmi MCMC.
Xi'an,

Risposte:


34

Il modo semplice ed elegante per stimare di Monte Carlo è descritto in questo documento . Il documento riguarda in realtà l'insegnamento e . Quindi, l'approccio sembra perfettamente adatto al tuo obiettivo. L'idea si basa su un esercizio tratto da un popolare libro di testo russo sulla teoria della probabilità di Gnedenko. Vedi ex.22 a p.183ee

Succede in modo che , dove ξ è una variabile casuale definita come segue. È il numero minimo di n tale che Σ n i = 1 r i > 1 e r i sono numeri casuali da una distribuzione uniforme su [ 0 , 1 ] . Bello, no ?!E[ξ]=eξnΣio=1nrio>1rio[0,1]

Dal momento che è un esercizio, non sono sicuro che sia bello per me pubblicare la soluzione (prova) qui :) Se desideri dimostrarlo tu stesso, ecco un suggerimento: il capitolo si chiama "Momenti", che dovrebbe indicare tu nella giusta direzione.

Se vuoi implementarlo da solo, allora non leggere oltre!

Questo è un semplice algoritmo per la simulazione Monte Carlo. Disegna un casuale uniforme, quindi un altro e così via fino a quando la somma non supera 1. Il numero di random estratti è la tua prima prova. Diciamo che hai:

 0.0180
 0.4596
 0.7920

Quindi viene eseguito il rendering della tua prima prova 3. Continua a fare queste prove e noterai che in media ottieni .e

Seguono il codice MATLAB, il risultato della simulazione e l'istogramma.

N = 10000000;
n = N;
s = 0;
i = 0;
maxl = 0;
f = 0;
while n > 0
    s = s + rand;
    i = i + 1;
    if s > 1
        if i > maxl
            f(i) = 1;
            maxl = i;
        else
            f(i) = f(i) + 1;
        end
        i = 0;
        s = 0;
        n = n - 1;
    end
end

disp ((1:maxl)*f'/sum(f))
bar(f/sum(f))
grid on

f/sum(f)

Il risultato e l'istogramma:

2.7183


ans =

  Columns 1 through 8

         0    0.5000    0.3332    0.1250    0.0334    0.0070    0.0012    0.0002

  Columns 9 through 11

    0.0000    0.0000    0.0000

inserisci qui la descrizione dell'immagine

AGGIORNAMENTO: ho aggiornato il mio codice per eliminare la matrice dei risultati della prova in modo che non richieda RAM. Ho anche stampato la stima del PMF.

Aggiornamento 2: ecco la mia soluzione Excel. Inserisci un pulsante in Excel e collegalo alla seguente macro VBA:

Private Sub CommandButton1_Click()
n = Cells(1, 4).Value
Range("A:B").Value = ""
n = n
s = 0
i = 0
maxl = 0
Cells(1, 2).Value = "Frequency"
Cells(1, 1).Value = "n"
Cells(1, 3).Value = "# of trials"
Cells(2, 3).Value = "simulated e"
While n > 0
    s = s + Rnd()
    i = i + 1
    If s > 1 Then
        If i > maxl Then
            Cells(i, 1).Value = i
            Cells(i, 2).Value = 1
            maxl = i
        Else
            Cells(i, 1).Value = i
            Cells(i, 2).Value = Cells(i, 2).Value + 1
        End If
        i = 0
        s = 0
        n = n - 1
    End If
Wend


s = 0
For i = 2 To maxl
    s = s + Cells(i, 1) * Cells(i, 2)
Next


Cells(2, 4).Value = s / Cells(1, 4).Value

Rem bar (f / Sum(f))
Rem grid on

Rem f/sum(f)

End Sub

Immettere il numero di prove, ad esempio 1000, nella cella D1 e fare clic sul pulsante. Ecco come dovrebbe apparire lo schermo dopo la prima esecuzione:

inserisci qui la descrizione dell'immagine

AGGIORNAMENTO 3: Silverfish mi ha ispirato in un altro modo, non elegante come il primo ma comunque bello. Ha calcolato i volumi di n-simplex usando sequenze di Sobol .

s = 2;
for i=2:10
    p=sobolset(i);
    N = 10000;
    X=net(p,N)';
    s = s + (sum(sum(X)<1)/N);
end
disp(s)

2.712800000000001

Per coincidenza ha scritto il primo libro sul metodo Monte Carlo che ho letto al liceo. Secondo me è la migliore introduzione al metodo.

AGGIORNAMENTO 4:

Silverfish nei commenti ha suggerito una semplice implementazione della formula Excel. Questo è il tipo di risultato che ottieni con il suo approccio dopo circa 1 milione di numeri casuali e 185.000 prove:

inserisci qui la descrizione dell'immagine

Ovviamente, questo è molto più lento dell'implementazione VBA di Excel. In particolare, se modifichi il mio codice VBA per non aggiornare i valori della cella all'interno del ciclo e lo fai solo una volta raccolte tutte le statistiche.

AGGIORNAMENTO 5

La soluzione n. 3 di Xi'an è strettamente correlata (o anche la stessa in un certo senso come nel commento di jwg nel thread). È difficile dire chi abbia avuto l'idea prima di Forsythe o Gnedenko. L'edizione 1950 originale di Gnedenko in russo non ha sezioni Problemi nei Capitoli. Quindi, non riuscivo a trovare questo problema a prima vista dove si trova nelle edizioni successive. Forse è stato aggiunto in seguito o seppellito nel testo.

Come ho commentato nella risposta di Xi'an, l'approccio di Forsythe è collegato a un'altra area interessante: la distribuzione delle distanze tra picchi (estremi) in sequenze casuali (IID). La distanza media risulta essere 3. La sequenza discendente nell'approccio di Forsythe termina con un fondo, quindi se continui il campionamento otterrai un altro fondo in un punto, poi un altro ecc. Puoi tracciare la distanza tra loro e costruire la distribuzione.


Caspita! Potresti aggiungere uno o due paragrafi che spiegano perché questo funziona?
Sycorax dice di reintegrare Monica il

7
(+1) Fantastico! La risposta merita il voto più alto in quanto si basa solo su simulazioni uniformi. E non usa alcuna approssimazione ma quella dovuta a Monte Carlo. Che si ricolleghi a Gnedenko è un ulteriore vantaggio.
Xi'an,

2
Freddo! Ecco il codice Mathematica per lo stesso, come una
Mean[Table[ Length[NestWhileList[(Random[]+#) &, Random[], #<1&]], {10^6}]]
riga

4
@wolfies La seguente traduzione diretta della Rsoluzione che ho pubblicato nella risposta di Xi'an è venti volte più veloce:n=10^6; 1. / Mean[UnitStep[Differences[Sort[RandomReal[{0, n}, n + 1]]] - 1]]
whuber

1
Ho pubblicato il "perché è la media ?" domanda come domanda a sé stante ; Sospetto che la mia soluzione di schizzo (che è quella che mi è venuta subito in mente come "ovvia" visualizzazione del problema) non sia necessariamente il modo in cui gli studenti russi erano intenzionati a farlo! Quindi soluzioni alternative sarebbero benvenute. e
Silverfish,

19

Suggerisco di votare la risposta di Aksakal. È imparziale e si basa solo su un metodo per generare deviazioni uniformi dell'unità.

La mia risposta può essere resa arbitrariamente precisa, ma è ancora distorta dal vero valore di .e

La risposta di Xi'an è corretta, ma penso che la sua dipendenza dalla funzione o da un modo di generare deviate casuali di Poisson sia un po 'circolare quando lo scopo è di approssimare e .loge

Stima tramite Bootstrappinge

Invece, considera la procedura di bootstrap. Uno ha un gran numero di oggetti che sono disegnati con la sostituzione di una dimensione del campione di n . Ad ogni pareggio, la probabilità di non disegnare un particolare oggetto i è 1 - n - 1 e non vi sono n tali pareggi. La probabilità che un particolare oggetto venga omesso da tutti i sorteggi è p = ( 1 - 1nnio1n1np=(11n)n.

Perché presumo sappiamo che

exp(1)=limn(11n)n

così anche noi possiamo scrivere

exp(1)p^=i=1mIiBjm

Cioè, la nostra stima di si trova stimando la probabilità che una specifica osservazione sia omessa da m bootstrap replica B j attraverso molti di questi replicati - cioè la frazione di occorrenze dell'oggetto i nei bootstrap.pmBji

Ci sono due fonti di errore in questa approssimazione. finito significa sempre che i risultati sono approssimativi, ovvero che la stima è distorta. Inoltre, p fluttuerà intorno al vero valore, perché questa è una simulazione.np^

Trovo che questo approccio un po 'affascinante perché uno studente o di un'altra persona con sufficiente poco a che fare potrebbe approssimare utilizzando un mazzo di carte, un mucchio di piccole pietre, o altri oggetti a portata di mano, nella stessa vena come una persona potrebbe stimare π utilizzando una bussola, una retta e alcuni granelli di sabbia. Penso che sia pulito quando la matematica può essere separata dalle comodità moderne come i computer.eπ

risultati

Ho condotto diverse simulazioni per un numero diverso di repliche bootstrap. Gli errori standard sono stimati utilizzando intervalli normali.

Si noti che la scelta di il numero di oggetti sottoposti a bootstrap imposta un limite superiore assoluto sull'accuratezza dei risultati poiché la procedura Monte Carlo sta valutando p e p dipende solo da n . L'impostazione di n come inutilmente grande semplicemente ingombrerà il tuo computer, o perché hai solo bisogno di un'approssimazione "approssimativa" a e o perché il bias sarà sommerso dalla varianza dovuta al Monte Carlo. Questi risultati sono per n = 10 3 e p - 1e è preciso al terzo decimale.nppnnen=103p1e

Questo grafico mostra che la scelta di ha conseguenze dirette e profonde per la stabilità a p . La linea tratteggiata blu mostra p e la linea rossa indica e . Come previsto, aumentando la dimensione del campione produce stime sempre più accurate p . mp^pep^inserisci qui la descrizione dell'immagine

Ho scritto una sceneggiatura R imbarazzantemente lunga per questo. Suggerimenti per il miglioramento possono essere inviati sul retro di una fattura di $ 20.

library(boot)
library(plotrix)
n <- 1e3

## if p_hat is estimated with 0 variance (in the limit of infinite bootstraps), then the best estimate we can come up with is biased by exactly this much:
approx <- 1/((1-1/n)^n)

dat <- c("A", rep("B", n-1))
indicator <- function(x, ndx)   xor("A"%in%x[ndx], TRUE) ## Because we want to count when "A" is *not* in the bootstrap sample

p_hat <- function(dat, m=1e3){
    foo <- boot(data=dat, statistic=indicator, R=m) 
    1/mean(foo$t)
} 

reps <- replicate(100, p_hat(dat))

boxplot(reps)
abline(h=exp(1),col="red")

p_mean <- NULL
p_var <- NULL
for(i in 1:10){
    reps <- replicate(2^i, p_hat(dat))
    p_mean[i] <- mean(reps)
    p_var[i] <- sd(reps)
}
plotCI(2^(1:10), p_mean, uiw=qnorm(0.975)*p_var/sqrt(2^(1:10)),xlab="m", log="x", ylab=expression(hat(p)), main=expression(paste("Monte Carlo Estimates of ", tilde(e))))
abline(h=approx, col='red')

4
+1 Ha molto senso. Hai qualche possibilità di condividere il tuo codice se lo hai scritto?
Antoni Parellada,

2
Anche se questo può essere arbitrariamente accurata, in ultima analisi è insoddisfacente perché simula solo un'approssimazione di anziché e stessa. ee
whuber

1
Sicuro. Finiresti con una chiamata replicata all'interno di un'altra, che è essenzialmente la stessa di quella che abbiamo ora.
Sycorax dice di ripristinare Monica

1
ee

1
@jwg Oltre ad essere concettualmente importante, è anche praticamente importante perché l'implementazione di un'approssimazione ad un'approssimazione richiede di tenere traccia dell'accuratezza di ciascuna delle due approssimazioni. Ma dovrei concordare sul fatto che quando entrambe le approssimazioni sono accettabilmente buone, l'approccio globale va bene.
whuber

14

Soluzione 1:

P(λ)

P(X=k)=λkk!eλ
XP(1)
P(X=0)=P(X=1)=e-1
e-1

U(io:n)-U(io-1:n)B(1,n)

P(n{U(io:n)-U(io-1:n)}1)=(1-1n)n
e-1n

Soluzione 2:

e

X1,X2~iidN(0,1)
(X12+X22)~χ12
E(1/2)
P(X12+X222)=1-{1-exp(-2/2)}=e-1
e(X1,X2)X12+X222πX12+X22<1

Soluzione 3:

u1,u2,...un+1>unNeNe-1expsol(X)ee-1

1/n!n

Una rapida implementazione R del metodo di Forsythe è quella di rinunciare a seguire precisamente la sequenza di uniformi a favore di blocchi più grandi, che consente l'elaborazione parallela:

use=runif(n)
band=max(diff((1:(n-1))[diff(use)>0]))+1
bends=apply(apply((apply(matrix(use[1:((n%/%band)*band)],nrow=band),
2,diff)<0),2,cumprod),2,sum)

12
e

5
eE(1)loge1P(1)

5
logexpn <- 1e5; 1/mean(n*diff(sort(runif(n+1))) > 1)

3
XnΣnXioXn1-Σn-1Xio1-ΣnXio1-Σn-1Xio

3
n+1n

7

Non una soluzione ... solo un breve commento che è troppo lungo per la casella dei commenti.

Aksakal

Aksakal ha pubblicato una soluzione in cui calcoliamo il numero previsto di disegni uniformi standard che devono essere presi, in modo che la loro somma superi 1. In Mathematica , la mia prima formulazione è stata:

mrM := NestWhileList[(Random[] + #) &, Random[], #<1 &]

Mean[Table[Length[mrM], {10^6}]] 

EDIT: ho appena avuto un gioco veloce con questo, e il seguente codice (stesso metodo - anche in Mma - solo codice diverso) è circa 10 volte più veloce:

Mean[Table[Module[{u=Random[], t=1},  While[u<1, u=Random[]+u; t++]; t] , {10^6}]]

Xian / Whuber

Whuber ha suggerito un codice cool veloce per simulare la soluzione di Xian 1:

Versione R: n <- 1e5; 1/mean(n*diff(sort(runif(n+1))) > 1)

Versione MMA: n=10^6; 1. / Mean[UnitStep[Differences[Sort[RandomReal[{0, n}, n + 1]]] - 1]]

che nota è 20 volte più veloce del primo codice (o circa due volte più veloce del nuovo codice sopra).

Solo per divertimento, ho pensato che sarebbe stato interessante vedere se entrambi gli approcci fossero altrettanto efficienti (in senso statistico). Per fare ciò, ho generato 2000 stime di e usando:

  • Metodo di Aksakal: dataA
  • Metodo 1 di Xian usando il codice whuber: dataB

... entrambi a Mathematica . Il diagramma seguente contrappone una stima della densità del kernel non parametrica dei set di dati risultanti A e dataB.

inserisci qui la descrizione dell'immagine

Quindi, mentre il codice di whuber (curva rossa) è circa due volte più veloce, il metodo non sembra essere "affidabile".


Una linea verticale nella posizione del valore reale migliorerebbe notevolmente questa immagine.
Sycorax dice di reintegrare Monica il

1
È un'osservazione molto interessante, grazie. Poiché la mezza larghezza si ridimensionerà quadraticamente con la dimensione della simulazione e la mezza larghezza del metodo di Xi'an è circa il doppio di quella di Aksakal, quindi eseguire quattro volte più iterazioni le renderà ugualmente accurate. Rimane la questione di quanto sforzo sia necessario in ogni iterazione: se una iterazione del metodo di Xi'an richiede meno di un quarto dello sforzo, quel metodo sarebbe ancora più efficiente.
whuber

1
n

1
running four times as many iterations will make them equally accurate106106

1
Ben fatto con il codice - sarà difficile migliorare molto su questo.
whuber

2

Metodo che richiede una quantità empia di campioni

f(X)=eXX¯12n~˙N(0,1)e quando la dimensione del campione si avvicina all'infinito.

N(0,1)eX regola !). Per rendere coerenti le stime della densità, dovrai lasciare che il tuo df (numero di bin nell'istogramma, inverso della finestra per più uniforme) si avvicini all'infinito, ma più lentamente della dimensione del campione.

N(0,1)φ^(X)ϕ((2))=(2π)1/2e1e=ϕ^(2)2π

22π

Metodo che richiede pochissimi campioni, ma causa una quantità empia di errore numerico

Una risposta completamente stupida, ma molto efficiente, basata su un commento che ho fatto:

Xuniform(1,1)Yn=|(x¯)n|e^=(1Yn)1/Yn

Questo converge molto velocemente, ma si imbatte anche in un errore numerico estremo.

Yn1/YnnYnYn=0e


2
e

1
@whuber: Non ho usato Box-Muller a causa della trasformazione del registro richiesta troppo direttamente in esponenziale nel mio libro. Io avrei già riflesso permesso cos e il peccato, ma che era solo perché mi ero dimenticato di analisi complessa per un attimo, così buon punto.
Cliff AB,

1
n1n2φ(2)n1n2en2n1

2

Ecco un altro modo in cui può essere fatto, anche se è piuttosto lento. Non pretendo di essere efficiente, ma offro questa alternativa nello spirito di completezza.

nU1,,Un~IID U(0,1)e

E(io(Uio1/e)Uio)=1/e1duu=1.

eu(1)u(n)

Sn(K)1nΣio=1K1u(io)per tutti K=1,..,n.

mmin{K|S(K)1}1/ee

e^2u(m)+u(m+1).

1/eee

Implementazione in R: il metodo può essere implementato Rusando runifper generare valori uniformi. Il codice è il seguente:

EST_EULER <- function(n) { U <- sort(runif(n), decreasing = TRUE);
                           S <- cumsum(1/U)/n;
                           m <- min(which(S >= 1));
                           2/(U[m-1]+U[m]); }

e

set.seed(1234);

EST_EULER(10^3);
[1] 2.715426

EST_EULER(10^4);
[1] 2.678373

EST_EULER(10^5);
[1] 2.722868

EST_EULER(10^6); 
[1] 2.722207

EST_EULER(10^7);
[1] 2.718775

EST_EULER(10^8);
[1] 2.718434

> exp(1)
[1] 2.718282

e

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.