วิธีตัวอย่าง X อย่างรวดเร็วถ้า exp (X) ~ Gamma


12

ฉันมีปัญหาในการสุ่มตัวอย่างอย่างง่ายโดยที่วงในของฉันดูเหมือน:

v = sample_gamma(k, a)

โดยที่sample_gammaตัวอย่างจากการแจกแจงแกมม่าเป็นตัวอย่าง Dirichlet

มันใช้งานได้ดี แต่สำหรับค่าบางส่วนของ k / a การคำนวณ downstream underflows บางส่วน

ฉันปรับมันเพื่อใช้ตัวแปรพื้นที่บันทึก:

v = log(sample_gamma(k, a))

หลังจากปรับโปรแกรมที่เหลือทั้งหมดมันทำงานได้อย่างถูกต้อง (อย่างน้อยมันก็ให้ผลลัพธ์ที่แน่นอนเหมือนกันในกรณีทดสอบ) อย่างไรก็ตามมันช้ากว่าเดิม

มีวิธีการโดยตรงตัวอย่างโดยไม่ใช้ฟังก์ชั่นช้าเช่นlog ( ) ? ฉันลอง googling สำหรับสิ่งนี้ แต่ฉันไม่รู้ด้วยซ้ำว่าการกระจายนี้มีชื่อสามัญ (log-gamma?)X,exp⁡(X)∼Gammalog⁡()


สิ่งที่คุณต้องทำคือการแบ่งแต่ละแกมม่าแปรตามผลรวมของพวกเขา underflow เกิดขึ้นได้อย่างไร และการลอการิทึมจะแก้ปัญหานี้ได้อย่างไร (คุณไม่สามารถคำนวณผลรวมได้โดยไม่ต้องยกกำลังกลับมาอีกครั้ง)
— whuber

@whuber ในพื้นที่บันทึกคุณคำนวณผลรวมแล้วลบออกจากแต่ละองค์ประกอบ ดังนั้นสิ่งนี้จะหลีกเลี่ยงจุดแรกของความไม่พอ มีการประมวลผลเพิ่มเติมเล็กน้อยเมื่อ dirichlets เหล่านี้ทำหน้าที่เป็นส่วนประกอบผสมและได้รับการคูณด้วยตัวเลขขนาดเล็กอีกครั้ง
— luispedro

การเพิ่มบันทึกนั้นไม่ถูกต้องทางคณิตศาสตร์: มันสอดคล้องกับการคูณ gammas แทนที่จะเพิ่มมัน ใช่คุณอาจได้รับผลการทำงาน แต่แน่นอนว่าพวกเขาจะไม่มีการแจกจ่าย Dirichlet! อีกครั้งธรรมชาติของอันเดอร์โฟลว์ดั้งเดิมคืออะไรและคุณคำนวณอะไรเมื่อมันเกิดขึ้น? คุณค่าที่แท้จริงของคุณคืออะไร
— whuber

@ คนที่ฉันอาจจะง่ายขึ้นเล็กน้อยในคำอธิบายของฉัน ฉันทำทั้งหมดฉัน {t = gamma (a, b); รวม + = t; d [i] = log (t)}; logsum = log (ผลรวม); forall i {d [i] - = logsum; } ก่อนหน้านี้สิ่งนี้ underflowed ถ้า a มีขนาดเล็กมาก
— luispedro

เตรียมพร้อม: สำหรับใกล้ 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มากกว่าหรือน้อยกว่า) นี่คือพล็อตของโอกาสในการรับอันเดอร์โฟลว์ในฐานะฟังก์ชันลอการิทึมฐานสิบของα:Fα(x)=xααΓ(α)1/αα=1/10010−300α

ป้อนคำอธิบายรูปภาพที่นี่

ทางออกหนึ่งคือการใช้ประโยชน์จากการประมาณนี้สำหรับการสร้างรูปแบบการบันทึก (Gamma): ผลลองสร้างรูปแบบแกมมาและถ้ามันมีขนาดเล็กเกินไปสร้างลอการิทึมจากการกระจายพลังงานโดยประมาณนี้ (ดังแสดงด้านล่าง) (ทำสิ่งนี้ซ้ำ ๆ จนกว่าบันทึกจะอยู่ในช่วง underflow เพื่อให้มันเป็นสิ่งทดแทนที่ถูกต้องสำหรับตัวแปร underflowing ดั้งเดิม) สำหรับการคำนวณ Dirichlet ให้ลบค่าสูงสุดของค่าลอการิทึมทั้งหมดจากค่าบันทึกแต่ละค่าโดยปริยาย แกมมาแปรปรวนดังนั้นมันจะไม่ส่งผลกระทบต่อค่า Dirichlet ปฏิบัติกับบันทึกผลลัพธ์ที่มีขนาดเล็กเกินไป (พูดน้อยกว่า -100) ว่าเป็นบันทึกของศูนย์จริง ยกกำลังบันทึกอื่น ๆ ตอนนี้คุณสามารถดำเนินการต่อได้โดยไม่ต้อง underflow

สิ่งนี้จะใช้เวลานานกว่าเดิม แต่อย่างน้อยมันก็ใช้ได้!

αC=log⁡(Γ(α))+log⁡(α)αC

เนื่องจากพารามิเตอร์สเกลช่วยลดความแปรปรวนเพียงอย่างเดียวจึงไม่มีปัญหาในการรองรับในขั้นตอนเหล่านี้ คุณไม่จำเป็นต้องใช้มันหากพารามิเตอร์สเกลทั้งหมดเหมือนกัน

แก้ไข

1/αB(α)Γ(α+1)(αxα−1)(yαe−ydy/Γ(α+1))z=xyy→z/xxxz∞0≤y≤1

pdf(z)=αΓ(α+1)∫z∞(xα/x)e−x(z/x)α−1dxdz=1Γ(α)zα−1e−zdz,

Γ(α)

0<α<1Γ(α+1)1/αΓ(α)


1
Γ(α)Γ(α)+Γ(1)∼Beta(α,1)Γ(α)+Γ(1)∼Γ(α+1)α≈0y∼expo(1)−log⁡(u)Γ(α+1)

7

raα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


α

ฉันแก้ไขคำตอบเพื่อรวมรายละเอียดเพิ่มเติมตอนนี้
— luispedro

ขอบคุณ: แต่ "r" คืออะไร? (โปรดทราบว่าการเรียกซ้ำถูก จำกัด ขอบเขต: การเรียกซ้ำแบบเรียกซ้ำมากที่สุดจะทำได้เนื่องจาก> 0 หมายถึง 1.0 + a> 1)
— whuber

r คือตัวสร้างตัวเลขสุ่ม (ซึ่งคุณจะได้รับตัวเลขสุ่มจาก)
— luispedro

Γ(α+1)B(α,1)Γ(α)
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.