exp(X)〜Gammaの場合、Xをすばやくサンプリングする方法は?


12

単純なサンプリングの問題があり、私の内部ループは次のようになります。

v = sample_gamma(k, a)

ここでsample_gamma、ガンマ分布からのサンプルがディリクレのサンプルを形成します。

うまく機能しますが、k / aの値によっては、ダウンストリームの計算の一部がアンダーフローします。

ログスペース変数を使用するように調整しました。

v = log(sample_gamma(k, a))

プログラムの残りのすべてを適応させた後、正しく動作します(少なくとも、テストケースで同じ正確な結果が得られます)。ただし、以前よりも遅くなります。

log )のような遅い関数を使用せずにを直接サンプリングする方法はありますか?私はこれをグーグルで試しましたが、このディストリビューションに共通名(log-gamma?)があるかどうかさえ知りません。X,exp(X)Gammalog()


必要なのは、各ガンマ変量を合計で除算することだけです。では、アンダーフローはどのように発生しますか?そして、対数を取ることでこの問題をどのように解決しますか(とにかく再びべき乗せずに合計を計算することはできません)?
whuber

@whuber対数空間では、合計を計算してから各要素から減算します。したがって、これによりアンダーフローの最初のポイントが回避されます。これらのディリクレが混合成分として機能し、再び小さな数で乗算されると、少し処理が続きます。
ルイスペドロ

ログを追加することは数学的に間違っています。ガンマを追加するのではなく、乗算することに相当します。はい、あなたは実際の結果を得るかもしれませんが、それらは間違いなくディリクレ分布を持っていません!繰り返しますが、元のアンダーフローの性質は何ですか?また、それが発生したときにどのような計算をしていますか?実際に使用している値は何ですか?
whuber

@whuber説明で少し単純化しすぎたかもしれません。私はforall i {t = gamma(a、b); sum + = t; d [i] = log(t)}; logsum = log(sum); forall i {d [i]-= logsum; }。以前は、aが非常に小さい場合、これはアンダーフローしていました。
ルイスペドロ

わかりました: 0に近い場合、何があっても問題が発生します。興味深い問題!α
whuber

回答:


9

小さな形状パラメータ検討ような、0近傍αは= 1 / 100。0との間の範囲のαE - αは、およそ1ガンマPDFが約あるので、X α - 1つの D X / Γ α 。これはおおよそのCDFに統合することができ、F αX = X ααα=1/100αeα1xα1dx/Γ(α)。それを逆にすると、1/αのべき乗、つまり巨大な指数が見られます。以下のためにα=1/100これは、(倍精度値未満アンダーフローのいくつかの機会原因10-300、多かれ少なかれ)。以下は、αの10を底とする対数の関数としてアンダーフローが発生する可能性のプロットです。Fα(x)=xααΓ(α)1/αα=1/10010300α

enter image description here

1つの解決策は、log(Gamma)変量を生成するためにこの近似を活用することです。実際には、Gamma変量を生成しようとし、小さすぎる場合は、この近似電力分布から対数を生成します(以下を参照)。(これが元のアンダーフロー変量の有効な代替となるように、ログがアンダーフロー範囲内になるまでこれを繰り返します。)ディリクレ計算では、各ログ値からすべての対数の最大値を減算します。ガンマが変化するため、ディリクレ値に影響しません。結果のログが小さすぎる(たとえば、-100未満)場合は、真のゼロのログとして扱います。他のログを累乗します。これで、アンダーフローなしで続行できます。

これには以前よりもさらに時間がかかりますが、少なくとも機能します!

形状パラメーターを使用して近似の対数ガンマ変量を生成するには、C = log Γ α + log α )を事前計算しますlog Gammaの値を直接計算するアルゴリズムがあるため、これは簡単です。0〜1の一様なランダムフロートを生成し、その対数を取り、αで除算し、それにCを追加します。αC=log(Γ(α))+log(α)αC

スケールパラメーターは変量を再スケーリングするだけなので、これらの手順で変数を調整しても問題はありません。すべてのスケールパラメーターが同じである場合でも必要ありません。

編集

別の回答では、OP は、一様変量(B α 変量)の乗にΓ α + 1 変量を掛ける方法を説明しています。この作品これら二つの同時分布のPDFに等しい変量ので α X α - 1Y α E - Y次元Y / Γ α + 1 z = x yの pdfを見つけるには1/αB(α)Γ(α+1)(αxα1)(yαeydy/Γ(α+1))z=xy我々は置換ヤコビアンによって、分割をX、及びアウト統合Xを。積分マスト範囲Zため0 Y 1、そこyz/xxxz0y1

pdf(z)=αΓ(α+1)z(xα/x)ex(z/x)α1dxdz=1Γ(α)zα1ezdz,

これは、分布の確率密度関数です。Γ(α)

全体のポイントは、場合、Γ α + 1 から引き出された値はアンダーフローする可能性が低く、そのログと独立した一様変量のログの1 / α倍を合計することにより、Γ α 変量。ログは非常に負の値になる可能性がありますが、浮動小数点表現でアンダーフローするアンチログの構築をバイパスします。0<α<1Γ(α+1)1/αΓ(α)


1
あなたの編集をもう少しエレガントにするための単なる議論ですが、ここでの統合に訴える必要はありません。ただ、事実を使用しています、プラスそのΓα+Γ1Γα+1。これらは両方ともベータおよびガンマ分布の標準プロパティです。また、場合α0我々は概ねYEXPO1Γ(α)Γ(α)+Γ(1)Beta(α,1)Γ(α)+Γ(1)Γ(α+1)α0yexpo(1)、一般的なΓ α + 1 確率変数よりもシミュレートするのが速い場合があります()。log(u)Γ(α+1)
確率が

7

私は自分の質問に答えていますが、完全に理解していなくても、かなり良い解決策を見つけました。GNU Scientific Libraryのコードを見ると、ガンマ変数をサンプリングする方法は次のとおりです(r乱数ジェネレーターでaあり、およびβです)。αbβ

  if (a < 1)
    {
      double u = gsl_rng_uniform_pos (r);
      return gsl_ran_gamma (r, 1.0 + a, b) * pow (u, 1.0 / a);
   }

gsl_ran_gammagsl_rng_uniform_pos(0,1)_pos

したがって、最後の式のログを取得して使用できます

return log(gsl_ran_gamma(r, 1.0 + a, b)) + log(u)/a;

log()pow()1/a1/a


α

回答を編集して、詳細を追加しました。
ルイスペドロ

Thank you: but what is "r"? (Note that the recursion is bounded: at most one recursive call will be made, because a > 0 implies 1.0+a > 1.)
whuber

r is the random number generator (where you are getting the random numbers from).
luispedro

Ah, this is clever: the product of a Γ(α+1) and an independent B(α,1) variate turns out to be a Γ(α) variate. I edited my reply so it points to your solution and explains why it works.
whuber
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.