exp (X) ~ Gamma 인 경우 X를 빠르게 샘플링하는 방법?


12

내부 루프가 다음과 같은 간단한 샘플링 문제가 있습니다.

v = sample_gamma(k, a)

여기서 sample_gamma감마 분포의 샘플은 Dirichlet 샘플을 형성합니다.

잘 작동하지만 일부 k / a 값의 경우 일부 다운 스트림 계산 언더 플로가 있습니다.

로그 공간 변수를 사용하도록 조정했습니다.

v = log(sample_gamma(k, a))

나머지 모든 프로그램을 조정 한 후에는 올바르게 작동합니다 (적어도 테스트 케이스에서 동일한 결과를 얻습니다). 그러나 이전보다 느립니다.

와 같은 느린 함수를 사용하지 않고 를 직접 샘플링하는 방법이 있습니까? 나는 이것을 인터넷 검색을 시도했지만이 배포판에 공통 이름 (log-gamma?)이 있는지조차 알지 못한다.로그 ( )X,exp(X)Gammalog()


각 감마 변이를 합으로 나누면됩니다. 그러면 언더 플로는 어떻게 발생합니까? 그리고 로그를 취하면이 문제가 어떻게 해결됩니까 (어쨌든 다시 다시 지수하지 않으면 합계를 계산할 수 없습니다)?
whuber

@whuber 로그 공간에서 합계를 계산 한 다음 각 요소에서 뺍니다 . 따라서 이것은 언더 플로의 첫 번째 지점을 피합니다. 이러한 디 리틀 렛이 혼합 성분으로 작용하고 다시 소량 곱해질 때 약간의 추가 처리가 있습니다.
luispedro

로그를 추가하면 수학적으로 올바르지 않습니다. 감마를 추가하지 않고 곱하는 것에 해당 합니다. 예, 작업 결과가 나올 수 있지만 Dirichlet 배포판은 없습니다! 다시 한 번, 원래 언더 플로의 특성은 무엇이며 어떤 일이 발생할 때 어떤 계산을 수행하고 있습니까? 실제 작업중인 값은 무엇입니까?
whuber

@ whuber 내 설명에서 조금 단순화했을 수도 있습니다. 나는 모든 것을 {i = gamma (a, b); 합 + = t; d [i] = log (t)}; 로그 섬 = log (sum); forall i {d [i]-= logsum; }. 이전에는 a가 매우 작은 경우에이 수가 급증했습니다.
luispedro

알겠습니다 : 0에 가까워지면 무엇이든지 문제가 될 것입니다. 재미있는 문제! α
whuber

답변:


9

과 같이 0 근처 의 작은 모양 매개 변수 고려하십시오 . 0에서 사이의 범위 에서 는 대략 이므로 감마 pdf는 대략 입니다. 이것은 대략적인 CDF, 있습니다. 그것을 뒤집 으면, power : 거대한 지수 가 보입니다 . 를 들어 (이하 이중 정밀도 값이 언더 플로우의 일부 기회의 원인 더 이하). 다음은 밑이 10 인 로그의 함수로 언더 플로가 발생할 가능성에 대한 그림입니다.α = 1 / 100 α E - α 1 X α - (1) (D) X / Γ ( α ) F α ( X ) = X ααα=1/100αeα1xα1dx/Γ(α) 1/αα=1/10010-300αFα(x)=xααΓ(α)1/αα=1/10010300α :

여기에 이미지 설명을 입력하십시오

한 가지 해결책은 log (Gamma) 변이를 생성하기 위해이 근사법을 이용하는 것입니다. 사실상, 감마 변이를 생성하려고 시도하고 너무 작 으면이 근사 전력 분포에서 로그를 생성하십시오 (아래 참조). 로그가 언더 플로 범위 내에있을 때까지이 작업을 반복해서 수행하면 원래 언더 플로 잉 변수를 대신 할 수 있습니다. Dirichlet 계산의 경우 각 로그 값에서 모든 로그의 최대 값을 뺍니다. 감마는 변하므로 Dirichlet 값에 영향을 미치지 않습니다. 너무 작은 결과 로그 (예 : -100 미만)는 모두 0의 로그로 취급하십시오. 다른 로그를 지수화하십시오. 이제 언더 플로없이 진행할 수 있습니다.

이것은 이전보다 훨씬 오래 걸릴 것이지만 최소한 작동합니다!

모양 매개 변수가 인 근사 로그 감마 변이를 생성하려면 사전 계산 입니다. log 감마의 값을 직접 계산 하는 알고리즘이 있기 때문에 이것은 쉽다 . 0과 1 사이의 균일 한 랜덤 유동을 생성하여 로그 분열을 및 추가 그것에.C = 로그 ( Γ ( α ) ) + 로그 ( α ) α CαC=log(Γ(α))+log(α)αC

척도 모수는 단지 변량의 척도를 재조정하기 때문에 이러한 절차에서 수용하는 데 아무런 문제가 없습니다. 모든 스케일 매개 변수가 동일한 경우에는 필요하지 않습니다.

편집하다

또 다른 대답에서 OP 는 균일 변량 ( 변량) 의 power에 변량을 곱하는 방법을 설명합니다 . 이 두 변수의 합동 분포의 pdf가 . PDF를 찾는 방법은 우리 대체 코빈 의해 제산 , 아웃 통합 . 이므로 적분은 에서 사이 여야합니다 .1/αB(α)Γ(α+1)(αxα1)(yαeydy/Γ(α+1))z=xyyz/xxxz0y1

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

이것은 분포 의 pdf입니다 .Γ(α)

요점은 일 때 에서 가져온 값 은 언더 플로되지 않을 것이고 로그와 곱하기 독립적 인 균일 한 변이의 로그를 합하면 변수 의 로그를 갖습니다 . 로그는 매우 부정적 일 수 있지만 부동 소수점 표시에서 언더 플로 될 안티 로그의 구성을 무시했습니다.0<α<1Γ(α+1)1/αΓ(α)


1
편집 내용을 좀 더 우아하게 만들기위한 주장 일 뿐이므로 통합에 호소 할 필요는 없습니다. 그냥 사실을 사용하는 , 플러스 그 입니다. 이들은 베타 및 감마 분포의 표준 속성입니다. 또한 일 때 대략 있으며 이는 일반적인 랜덤 변수 보다 ( ) 시뮬레이션하는 것이 더 빠를 수 있습니다 . Γ(α)Γ(α)+Γ(1)Beta(α,1)Γ(α)+Γ(1)Γ(α+1)α0yexpo(1)log(u)Γ(α+1)
probabilityislogic

7

나는 내 자신의 질문에 대답하고 있지만 완전히 이해하지 못하더라도 꽤 좋은 해결책을 찾았습니다. 는 GNU 과학 도서관의 코드를 보면, 여기 샘플 감마 변수 (어떻게 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_gamma동안 (상기 있도록 재귀 호출이다) 감마 무작위 샘플을 반환하는 함수이다 gsl_rng_uniform_pos에서 균일하게 분포 된 다수 복귀 ((가) 가 0.0를 반환하지 보장 엄격히 포지티브된다).(0,1)_pos

따라서 마지막 표현의 로그를 가져 와서 사용할 수 있습니다.

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

내가 원하는 것을 얻으려면. 이제 두 번의 log()호출이 pow()있지만 결과는 더 좋을 것입니다. 전에 whuber가 지적했듯이, 나는 의 거듭 제곱을 일으켰습니다 . 이제 로그 공간에서 곱하고 있습니다. 따라서 언더 플로 가능성이 적습니다.1 / a1/a1/a


gsl_rng_uniform_pos 및 gsl_ran_gamma의 기능을 설명해 주시겠습니까? 첫 번째는 0과 r 사이의 균일 한 무작위 값을 반환하고 두 번째는 감마 (1 + a, b) 값과 관련이 있다고 생각합니다. 아마도 불완전한 감마입니까? 전반적으로 이것은 내가 제안한 근사치와 매우 비슷해 보입니다 (이를 검토 할 때 필연적 으로 부분으로 나누기를 지정하는 것을 잊어 버린 것이 분명합니다 !)α
whuber

더 자세한 내용을 포함하도록 답변을 편집했습니다.
luispedro

감사합니다. "r"은 무엇입니까? (재귀는
제한됨에 유의

r은 난수 생성기 (난수를 얻는 곳)입니다.
luispedro

아이 똑똑 : (a)의 생성물 과 독립적 인 변량이 밝혀 변량. 답장을 편집하여 솔루션을 가리키고 왜 작동하는지 설명합니다. B ( α , 1 ) Γ ( α )Γ(α+1)B(α,1)Γ(α)
whuber
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.