รูปแบบที่เหมาะสมสำหรับการแจกแจงแบบปกติสองครั้งใน PyMC


10

เนื่องจากฉันเป็นวิศวกรซอฟต์แวร์พยายามที่จะเรียนรู้สถิติเพิ่มเติมคุณจะต้องยกโทษให้ฉันก่อนที่ฉันจะเริ่มนี่เป็นดินแดนใหม่ที่ร้ายแรง ...

ฉันได้เรียนรู้PyMCและทำงานผ่านตัวอย่างง่ายๆ (จริง ๆ ) จริงๆ ปัญหาหนึ่งที่ฉันไม่สามารถทำงานได้ (และไม่สามารถหาตัวอย่างที่เกี่ยวข้องได้) คือการปรับโมเดลให้สอดคล้องกับข้อมูลที่สร้างจากการแจกแจงปกติสองแบบ

บอกว่าฉันมี 1,000 ค่า 500 สร้างขึ้นจากNormal(mean=100, stddev=20)และอีก 500 Normal(mean=200, stddev=20)สร้างขึ้นจาก

ถ้าฉันต้องการให้พอดีกับแบบจำลองพวกเขาเช่นกำหนดสองวิธีและส่วนเบี่ยงเบนมาตรฐานเดียวโดยใช้ PyMC ฉันรู้ว่ามันเป็นสิ่งที่ตามแนว ...

mean1 = Uniform('mean1', lower=0.0, upper=200.0)
mean2 = Uniform('mean2', lower=0.0, upper=200.0)
precision = Gamma('precision', alpha=0.1, beta=0.1)

data = read_data_from_file_or_whatever()

@deterministic(plot=False)
def mean(m1=mean1, m2=mean2):
    # but what goes here?

process = Normal('process', mu=mean, tau=precision, value=data, observed=True)

นั่นคือกระบวนการสร้างเป็นปกติ แต่ mu เป็นหนึ่งในสองค่า ผมก็ไม่ทราบวิธีการที่จะเป็นตัวแทนของ "การตัดสินใจ" ระหว่างว่าค่ามาจากหรือm1m2

บางทีฉันอาจใช้วิธีการที่ผิดในการสร้างแบบจำลองนี้หรือไม่ ทุกคนสามารถชี้ให้ฉันเป็นตัวอย่างได้หรือไม่? ฉันสามารถอ่าน BUGS และ JAGS ได้

คำตอบ:


11

คุณแน่ใจหรือไม่ว่าครึ่งหนึ่งมาจากการกระจายหนึ่งและอีกครึ่งหนึ่งมาจากการกระจาย? ถ้าไม่เราสามารถสร้างแบบจำลองสัดส่วนเป็นตัวแปรสุ่ม (ซึ่งเป็นสิ่งที่เบย์ทำ)

ต่อไปนี้เป็นสิ่งที่ฉันจะทำเคล็ดลับบางอย่างจะถูกฝัง

from pymc import *

size = 10
p = Uniform( "p", 0 , 1) #this is the fraction that come from mean1 vs mean2

ber = Bernoulli( "ber", p = p, size = size) # produces 1 with proportion p.

precision = Gamma('precision', alpha=0.1, beta=0.1)

mean1 = Normal( "mean1", 0, 0.001 ) #better to use normals versus Uniforms (unless you are certain the value is  truncated at 0 and 200 
mean2 = Normal( "mean2", 0, 0.001 )

@deterministic
def mean( ber = ber, mean1 = mean1, mean2 = mean2):
    return ber*mean1 + (1-ber)*mean2


#generate some artificial data   
v = np.random.randint( 0, 2, size)
data = v*(10+ np.random.randn(size) ) + (1-v)*(-10 + np.random.randn(size ) )


obs = Normal( "obs", mean, precision, value = data, observed = True)

model = Model( {"p":p, "precision": precision, "mean1": mean1, "mean2":mean2, "obs":obs} )

2
การโปรโมตที่ไร้ยางอาย: ฉันเพิ่งเขียนบทความบล็อกเกี่ยวกับ Bayes และ pyMC อย่างแท้จริง 1 นาทีก่อนที่คุณจะโพสต์ข้อความนี้ดังนั้นฉันจึงเชิญให้คุณลองดู พลังอันยิ่งใหญ่ของ Bayes - ตอนที่ 1
Cam.Davidson.Pilon

! น่ากลัว วิธีการผสมสองวิธีนี้เป็นสิ่งที่ฉันพยายามทำให้หัวของฉัน
mat kelcey

ไม่แน่ใจว่าฉันเข้าใจถึงประโยชน์ของการสร้างแบบจำลองที่แท้จริงในการพูดค่าเฉลี่ย 1 และค่าเฉลี่ย 2 แทนการแจกแจงแบบสม่ำเสมอ (เหมือนกันจริง ๆ แล้วเพื่อความแม่นยำที่จะซื่อสัตย์ฉันใช้แกมม่ามาตั้งแต่ "คนอื่นทำ") ฉันมีจำนวนมากที่จะเรียนรู้ :)
เสื่อ Kelcey

การใช้เครื่องแบบเหมือนในตัวอย่างดั้งเดิมของคุณหมายความว่าคุณรู้ด้วยความมั่นใจแน่นอนว่าค่าเฉลี่ยไม่เกินค่าบางค่า นี่เป็นพยาธิสภาพ มันเป็นการดีกว่าที่จะใช้แบบปกติเพราะจะช่วยให้สามารถพิจารณาจำนวนจริงทั้งหมดได้
Cam.Davidson.Pilon

1
การเลือกแกมม่ามีเหตุผลทางคณิตศาสตร์ แกมม่าเป็นรูปแบบคอนจูเกตก่อนความแม่นยำดูตารางที่นี่
Cam.Davidson.Pilon

6

จุดสองสามประเด็นที่เกี่ยวข้องกับการอภิปรายด้านบน:

  1. ทางเลือกของการกระจายแบบปกติและแบบเครื่องแบบนั้นค่อนข้างเป็นเรื่องทางวิชาการยกเว้น (a) คุณกังวลเกี่ยวกับการผันคำกริยาซึ่งในกรณีนี้คุณจะใช้แบบปกติหรือ (b) มีโอกาสที่สมเหตุสมผลที่ค่าจริงอาจอยู่นอกจุดปลายทางของชุด . ด้วย PyMC ไม่มีเหตุผลที่จะต้องกังวลเรื่องการผันคำกริยายกเว้นว่าคุณต้องการใช้ตัวอย่าง Gibbs โดยเฉพาะ

  2. แกมม่าไม่ใช่ตัวเลือกที่ยอดเยี่ยมสำหรับ uninformative ก่อนพารามิเตอร์แปรปรวน / ความแม่นยำ มันอาจเป็นข้อมูลที่คุณคิดได้มากขึ้น ทางเลือกที่ดีกว่าคือการใส่เครื่องแบบก่อนส่วนเบี่ยงเบนมาตรฐานแล้วแปลงเป็นสี่เหลี่ยมจัตุรัส ดูGelman 2006สำหรับรายละเอียด


1
ah fonnesbeck เป็นหนึ่งในผู้พัฒนาหลักของ pymc! คุณช่วยแสดงตัวอย่างของวิธีการเขียนรหัส 2 ได้อย่างไร
Cam.Davidson.Pilon

ขอบคุณ fonnesbeck และใช่โปรด! ไปยังตัวอย่างที่รวดเร็วของจุด 2 :)
mat kelcey

1
ในความเป็นจริงฉันคาดเดาสิ่งที่คุณหมายถึงตามสายของท ... gist.github.com/4404631 ?
mat kelcey

ใช่แล้ว คุณสามารถทำการแปลงให้รัดกุมขึ้นอีกเล็กน้อย:tau = std_dev**-2
fonnesbeck

สิ่งที่จะเป็นสถานที่ที่เหมาะสมในการอ่านเกี่ยวกับความสัมพันธ์ระหว่างความแม่นยำและ std_dev นี้มาจากไหน?
user979
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.