Wie kann ich von einer Distribution mit inkompatiblem CDF probieren?


8

Semi-Computer Science Simulation bezogenes Problem hier.

Ich habe eine Verteilung wo

P (x) =(eb1)eb(nx)ebn+b1

für einige Konstanten b und n ist x eine ganze Zahl, so dass .0xn

Jetzt muss ich aus dieser Distribution probieren. Es hat eine invertierbare CDF, so dass dies theoretisch direkt möglich ist. Das Problem ist, dass die beteiligten Zahlen GROSS sind. In der Tat so groß, dass beide konventionell formatierte Variablen überlaufen und es mindestens Minuten dauert (irgendwann habe ich aufgegeben ...), um mit beliebigen Genauigkeitsformaten zu berechnen. Grundsätzlich beinhaltet die inverse CDF immer noch einen Term von für . Trotzdem werden die Ausgangsnummern immer noch im Bereich von , daher scheint es eine Möglichkeit zu geben, dies zu tun.eb(n+1)350<n<35000- -n

Was ich suche, ist eine Möglichkeit, ungefähr eine Stichprobe aus dieser Verteilung zu erstellen , die berechenbar ist. Gibt es alternative Probenahmemethoden? Was sind Sie?


2
Haben Sie darüber nachgedacht, Ihre Daten zu normalisieren oder zu skalieren, um die Domain zu verkleinern?
EngrStudent

Antworten:


7

Der CDF ist leicht invertierbar. Eine Formel für die Inversion führt zu einer der einfachsten und zweckmäßigsten möglichen Lösungen.

Beginnen Sie mit der Beobachtung, dass die Wahrscheinlichkeit des Ergebnisses , , proportional zu . Wenn wir also einen einheitlichen Wert zwischen und = müssen wir nur das größte für das0 k n e - b k q 0 q max = n k = 0 e - b kk0kne- -bkq0qmax=k=0ne- -bk(1- -e- -b(n+1))/.(1- -e- -b)k

qich=0ke- -bich=1- -e- -(k+1)b1- -e- -b.

Einfache Algebra gibt die Lösung

k=ceiling(log(1q(1eb))b).

Hier ist eine RImplementierung, die wie alle anderen Zufallszahlengeneratoren aufgebaut ist: Das erste Argument gibt an, wie viele iid- Werte generiert werden sollen, und die restlichen Argumente benennen die Parameter ( as und as ):nbbnn.max

rgeom.truncated <- function(n=1, b, n.max) {
  a <- 1 - exp(-b)
  q.max <- (1 - exp(-b*(n.max+1))) / a
  q <- runif(n, 0, q.max)
  return(-ceiling(log(1 - q*a) / b))
}

Lassen Sie uns als Beispiel für seine Verwendung eine Million zufälliger Variablen gemäß dieser Verteilung generieren:

b <- 0.001
n.max <- 3500
n.sim <- 10^6
set.seed(17)
system.time(sim <- rgeom.truncated(n.sim, b,n.max))

( Sekunden wurden benötigt.)0.10

h <- hist(sim+1, probability=TRUE, breaks=50, xlab="Outcome+1")
pmf <- exp(-b * (0: n.max)); pmf <- pmf / sum(pmf)
lines(0:n.max, pmf, col="Red", lwd=2)

Histogramm

( Zu jedem Wert wurde hinzugefügt, um ein besseres Histogramm zu erstellen: Die Prozedur weist eine Eigenart (= Fehler) auf, bei der der erste Balken zu hoch ist, wenn der linke Endpunkt auf Null gesetzt ist.) Die rote Kurve ist die Referenzverteilung dass diese Simulation versucht zu reproduzieren. Lassen Sie uns die Anpassungsgüte mit einem Chi-Quadrat-Test bewerten :1Rhist

observed <- table(sim)
expected <- n.sim * pmf
chi.square <- (observed-expected)^2 / expected
pchisq(sum(chi.square), n.max, lower.tail=FALSE)

Der p-Wert beträgt : eine schöne Passform.0.84


3
Tolle Lösung. Ich hätte nie gedacht, dass man auf diese Weise probieren kann (das heißt, man stützt sich auf Proben von anstelle von ), aber es ist im Nachhinein offensichtlich. U n i ( 0 , 1 )Uni(0,k),k>1Uni(0,1)
Cam.Davidson.Pilon

6

Sie haben es mit einer abgeschnittenen geometrischen Verteilung mit tun . Es gibt verschiedene Möglichkeiten, dies zu erreichen.p=1eb

Ich würde verschiedene Optionen in verschiedenen Situationen empfehlen. Einige Optionen umfassen das Simulieren aus einem geometrischen und das Regenerieren außerhalb des Bereichs, das Verwenden des ganzzahligen Teils eines geeigneten abgeschnittenen Exponentials ( wie hier ) oder das Verwenden einer von mehreren schnellen Techniken, die auf diskrete Verteilungen über einen endlichen Bereich zugeschnitten sind. Angesichts der Tatsache, dass groß ist, ist es wahrscheinlich relativ schnell, das Wort eines abgeschnittenen Exponentials zu ergreifen, aber ob es die beste Wahl ist, hängt auch von .bnb

Hier ist eine verwandte Frage zu math.SE

Was ist ein typischer Wertebereich für bevor ich bestimmte Vorschläge versuche ?b


Danke für deine Antwort! b ~ ln (1 + epsilon), wobei epsilon ein zusätzlicher Parameter> 0 ist.
John Doucette

1
Sie haben also meine Frage nach dem typischen Bereich von b in eine Frage nach dem typischen Bereich von ε umgewandelt. Was ist ein typischer Wertebereich für ε, bevor ich bestimmte Vorschläge versuche?
Glen_b -Rate State Monica

Der Grund, den ich frage, ist, welche bestimmten Ansätze effizienter sind, hängt von den Merkmalen der Situation ab. Es hört sich so an, als wären Sie mit der anderen Antwort bereits zufrieden. Vielleicht lohnt es sich also nicht, sich über zusätzliche potenzielle Effizienz Gedanken zu machen.
Glen_b -State Monica

{0,,n\]

1
nbb0(1- -e- -(n+1)b)/.((n+1)(1- -e- -b)) (1- -exp(- -nb))/.(nb)nb1

4

P.(x)e- -bxxfloor()

Das cdf eines abgeschnittenen Exponentials ist

F.(x;;n,b)=1- -e- -bx1- -e- -bn.

F.(x;;n,b)=ux=- -1bLog[1- -u(1- -e- -bn)]]bne- -bn0x- -1bLog[1- -u]]

rweirdp <- function(ns,n,b){
u <- runif(ns)
samp <- - log(1-u*(1-exp(-n*b)))/b
return(floor(samp))
}

rweirdp(1000,10,1)

Ich denke, das ist im Grunde das, wonach ich gesucht habe. bn ist immer sehr groß, eine proportionale Stichprobe ist sinnvoll. War sich der Zuordnung nicht bewusst, obwohl es im Nachhinein klar ist. Vielen Dank!
John Doucette

Ich bin froh zu sehen, dass das geholfen hat. Ich glaube, ich habe es nicht richtig erklärt, aber dieser Ansatz liefert Stichproben aus der genauen Zielverteilung. Prost.
Person

e- -bn

P.(x)

1
Eigentlich @ Xi'an, sofern diese Werke rweirdpauf Änderung geändert nzu n+1. (Wie hier angegeben, wird niemals ein Wert zurückgegeben, der gleich ist n: das ist der Effekt der Approximation.) Eine etwas strengere Analyse ist in meiner Antwort angegeben. Obwohl ich eine anders aussehende Formel erhalte, entspricht sie der hier angegebenen (einfacheren!) Formel, sobald die n-> n+1Änderung vorgenommen wurde.
whuber

4

p(k)exp{- -bk}}

  1. {0,1,,n}}

    metro=function(N,b,n){
    x=sample(0:n,N,rep=TRUE)
    for (t in 2:N){
      x[t]=prop=x[t-1]+sample(c(-1,1),1)
    
      if ((prop<0)||(prop>n)||(log(runif(1))>b*(x[t]-prop)))
          x[t]=x[t-1]
      }
    return(x)
    }
    
  2. {k0,,k1}}p(k)exp{- -bk+bk0}}

p()k0=0bnkb{0,1,,n}}

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.