Ich habe ein einfaches Stichprobenproblem, bei dem meine innere Schleife wie folgt aussieht:
v = sample_gamma(k, a)
wobei sample_gamma
Proben aus der Gamma-Verteilung eine Dirichlet-Probe bilden.
Es funktioniert gut, aber für einige Werte von k / a läuft ein Teil der nachgeschalteten Berechnung unter.
Ich habe es angepasst, um Log Space-Variablen zu verwenden:
v = log(sample_gamma(k, a))
Nachdem Sie den Rest des Programms angepasst haben, funktioniert es ordnungsgemäß (zumindest in Testfällen erhalte ich die gleichen genauen Ergebnisse). Es ist jedoch langsamer als zuvor.
Gibt es eine Möglichkeit, direkt abzutasten , ohne langsame Funktionen wie log ( ) zu verwenden ? Ich habe versucht, dafür zu googeln, aber ich weiß nicht einmal, ob diese Distribution einen gemeinsamen Namen hat (log-gamma?).
sampling
gamma-distribution
Luispedro
quelle
quelle
Antworten:
Betrachten wir einen kleinen Formparameter in der Nähe von 0 ist , wie beispielsweise α = 1 / 100 . Im Bereich zwischen 0 und α ist e - α ungefähr 1 , so dass das Gamma pdf ungefähr x α - 1 d x / Γ ( α ) ist . Dies kann zu einer annähernden CDF integriert werden, F α ( x ) = x αα α=1/100 α e−α 1 xα−1dx/Γ(α) . Wenn wir es invertieren, sehen wir eine1/α-Potenz: einen riesigen Exponenten. FürαFα(x)=xααΓ(α) 1/α Das bewirktgewisse Wahrscheinlichkeit des Unterschreitung (einen Wertdoppelter Genauigkeitweniger als 10 - 300 , mehr oder weniger). Hier ist eine Darstellung der Wahrscheinlichkeit eines Unterlaufens als Funktion des Zehn-Basis-Logarithmus von α :α=1/100 10−300 α
Eine Lösung besteht darin, diese Näherung für die Erzeugung von Gamma-Variablen zu nutzen: Versuchen Sie im Endeffekt, eine Gamma-Variable zu erzeugen, und generieren Sie, wenn sie zu klein ist, ihren Logarithmus anhand dieser ungefähren Leistungsverteilung (siehe unten). (Wiederholen Sie diesen Vorgang, bis sich das Protokoll innerhalb des Unterlaufbereichs befindet, sodass es einen gültigen Ersatz für die ursprüngliche Unterlaufvariable darstellt.) Subtrahieren Sie für die Dirichlet-Berechnung das Maximum aller Logarithmen von jedem der Protokollwerte: Dadurch wird implizit alle neu skaliert Das Gamma variiert, sodass es die Dirichlet-Werte nicht beeinflusst. Behandeln Sie jedes resultierende Protokoll, das zu klein ist (z. B. weniger als -100), als Protokoll einer echten Null. Potenzieren Sie die anderen Protokolle. Jetzt können Sie ohne Unterlauf fortfahren.
Dies wird noch länger dauern als zuvor, aber zumindest wird es funktionieren!
Berechnen Sie C = log ( Γ ( α ) ) +, um eine ungefähre log Gamma-Variation mit dem Formparameter erstellenα . Dies ist einfach, da es Algorithmen gibt, mit denen dieWerte von log Gamma direkt berechnet werden können. Erzeugen Sie einen gleichmäßigen Zufalls-Float zwischen 0 und 1, nehmen Sie seinen Logarithmus, dividieren Sie durch α und addieren Sie C dazu.C=log(Γ(α))+log(α) α C
Da der Parameter scale die Variable lediglich neu skaliert, ist es kein Problem, sie in diesen Prozeduren unterzubringen. Sie brauchen es nicht einmal, wenn alle Skalenparameter gleich sind.
Bearbeiten
In einer weiteren Antwort beschreibt das OP ein Verfahren, bei dem die Potenz einer gleichförmigen Variation (a B ( α ) -Variate) mit einer Γ ( α + 1 ) -Variate multipliziert wird . Dies funktioniert, weil das PDF der gemeinsamen Verteilung dieser beiden Variablen gleich ( α x α - 1 ) ist ( y α e - y d y / Γ ( α + 1 ) ) . Um das pdf von z = x y zu finden1/α B(α) Γ(α+1) (αxα−1)(yαe−ydy/Γ(α+1)) z=xy wir setzen , dividieren durch das jakobinische x bis ∞ , da 0 ≤ y ≤ 1 isty→z/x x , und integriere . Das Integral muss im Bereich von zx z ∞ 0≤y≤1
Das ist das PDF einer -Distribution.Γ(α)
Der springende Punkt ist, dass, wenn , es unwahrscheinlich ist, dass ein aus Γ ( α + 1 ) gezogener Wert unterschritten wird, und dass sein log und 1 /0<α<1 Γ(α+1) mal das Protokolls eines unabhängigen einheitliches variate werden wir das Protokoll eines haben Γ ( α ) variieren. Das Protokoll ist wahrscheinlich sehr negativ, aber wir haben die Erstellung des Antilog umgangen, der in einer Gleitkommadarstellung unterlaufen wird.1/α Γ(α)
quelle
Ich beantworte meine eigene Frage, habe aber eine ziemlich gute Lösung gefunden, auch wenn ich sie nicht vollständig verstehe. Wenn Sie sich den Code aus der GNU Scientific Library ansehen, sehen Sie hier, wie er Gammavariablen abtastet (α β
r
ist der Zufallszahlengenerator,a
ist undb
ist ):gsl_ran_gamma
ist die Funktion, die eine Gamma-Zufallsstichprobe zurückgibt (obiger Aufruf ist also rekursiv), währendgsl_rng_uniform_pos
eine gleichmäßig verteilte Zahl in (diesist streng positiv, da garantiert wird, dass sie nicht 0.0 zurückgibt)._pos
Daher kann ich das Protokoll des letzten Ausdrucks nehmen und verwenden
Um zu bekommen, was ich wollte. Ich habe jetzt zwei1/a 1/a
log()
Anrufe (aber einen wenigerpow()
), aber das Ergebnis ist wahrscheinlich besser. Zuvor hatte ich, wie Whuber betonte, etwas mit der Potenz von erhöht , möglicherweise eine riesige Zahl. Jetzt multipliziere ich im Logspace mit 1 / a . Es ist also weniger wahrscheinlich, dass es unterläuft.quelle