2-गॉसियन मिक्स मॉडल एमसीसीएमसी और पायएमसी के साथ अनुमान


10

समस्या

मैं एक साधारण 2-गाऊसी मिश्रण आबादी के मॉडल मापदंडों को फिट करना चाहता हूं। Bayesian तरीकों के आसपास सभी प्रचार को देखते हुए मैं यह समझना चाहता हूं कि क्या इस समस्या के लिए Bayesian inference एक बेहतर उपकरण है जो पारंपरिक फिटिंग के तरीके हैं।

अब तक MCMC इस खिलौना उदाहरण में बहुत खराब प्रदर्शन करता है, लेकिन शायद मैं सिर्फ कुछ अनदेखी करता हूं। तो कोड देखते हैं।

उपकरण

मैं अजगर (2.7) + स्काइप स्टैक, lmfit 0.8 और PyMC 2.3 का उपयोग करूंगा।

विश्लेषण को पुन: पेश करने के लिए एक नोटबुक यहां पाया जा सकता है

डेटा जनरेट करें

पहले डेटा उत्पन्न करें:

from scipy.stats import distributions

# Sample parameters
nsamples = 1000
mu1_true = 0.3
mu2_true = 0.55
sig1_true = 0.08
sig2_true = 0.12
a_true = 0.4

# Samples generation
np.random.seed(3)  # for repeatability
s1 = distributions.norm.rvs(mu1_true, sig1_true, size=round(a_true*nsamples))
s2 = distributions.norm.rvs(mu2_true, sig2_true, size=round((1-a_true)*nsamples))
samples = np.hstack([s1, s2])

इस samplesतरह दिखता है हिस्टोग्राम :

डेटा हिस्टोग्राम

एक "व्यापक शिखर", घटकों को आंख से स्पॉट करना मुश्किल है।

शास्त्रीय दृष्टिकोण: हिस्टोग्राम फिट

आइए पहले शास्त्रीय दृष्टिकोण का प्रयास करें। Lmfit का उपयोग करके 2-चोटियों के मॉडल को परिभाषित करना आसान है:

import lmfit

peak1 = lmfit.models.GaussianModel(prefix='p1_')
peak2 = lmfit.models.GaussianModel(prefix='p2_')
model = peak1 + peak2

model.set_param_hint('p1_center', value=0.2, min=-1, max=2)
model.set_param_hint('p2_center', value=0.5, min=-1, max=2)
model.set_param_hint('p1_sigma', value=0.1, min=0.01, max=0.3)
model.set_param_hint('p2_sigma', value=0.1, min=0.01, max=0.3)
model.set_param_hint('p1_amplitude', value=1, min=0.0, max=1)
model.set_param_hint('p2_amplitude', expr='1 - p1_amplitude')
name = '2-gaussians'

अंत में हम सिंप्लेक्स एल्गोरिथ्म के साथ मॉडल फिट करते हैं:

fit_res = model.fit(data, x=x_data, method='nelder')
print fit_res.fit_report()

परिणाम निम्न छवि है (लाल धराशायी लाइनें केंद्र केंद्रित हैं):

एनएलएस फिट परिणाम

भले ही समस्या कठिन हो, उचित प्रारंभिक मूल्यों और बाधाओं के साथ मॉडल काफी उचित अनुमान में परिवर्तित हो गए।

बायेसियन दृष्टिकोण: MCMC

मैं पीएमसीएच में पदानुक्रमित फैशन में मॉडल को परिभाषित करता हूं। centersऔर sigmas2 केंद्रों और 2 गाऊसी के 2 सिगमा का प्रतिनिधित्व करने वाले हाइपरपैरेटर्स के लिए पुजारी वितरण हैं। alphaपहली जनसंख्या का अंश है और पूर्व वितरण यहाँ एक बीटा है।

एक श्रेणीगत चर दो आबादी के बीच चुनता है। यह मेरी समझ है कि इस चर को डेटा ( samples) के समान आकार की आवश्यकता है ।

अंत में muऔर tauनियतात्मक चर हैं जो सामान्य वितरण के मापदंडों को निर्धारित करते हैं (वे categoryचर पर निर्भर करते हैं ताकि वे बेतरतीब ढंग से दो आबादी के लिए दो मूल्यों के बीच स्विच करें)।

sigmas = pm.Normal('sigmas', mu=0.1, tau=1000, size=2)
centers = pm.Normal('centers', [0.3, 0.7], [1/(0.1)**2, 1/(0.1)**2], size=2)
#centers = pm.Uniform('centers', 0, 1, size=2)

alpha  = pm.Beta('alpha', alpha=2, beta=3)
category = pm.Categorical("category", [alpha, 1 - alpha], size=nsamples)

@pm.deterministic
def mu(category=category, centers=centers):
    return centers[category]

@pm.deterministic
def tau(category=category, sigmas=sigmas):
    return 1/(sigmas[category]**2)

observations = pm.Normal('samples_model', mu=mu, tau=tau, value=samples, observed=True)
model = pm.Model([observations, mu, tau, category, alpha, sigmas, centers])

फिर मैं एमसीएमसी को काफी लंबी संख्या में पुनरावृत्तियों के साथ चलाता हूं (1e5, ~ 60s मेरी मशीन पर):

mcmc = pm.MCMC(model)
mcmc.sample(100000, 30000)

हालाँकि परिणाम बहुत विषम हैं। उदाहरण के लिए ट्रेस (पहली आबादी का अंश) 0.4 के बजाय अभिसरण के लिए 0 पर जाता है और इसमें एक बहुत ही मजबूत ऑटोक्रेलेशन है:α

MCMC अल्फा सारांश

इसके अलावा गौसियों के केंद्र भी रूपांतरित नहीं होते हैं। उदाहरण के लिए:

MCMC केंद्र_0 सारांश

जैसा कि आप पूर्व चुनाव में देखते हैं, मैंने एमसीएमसी एल्गोरिथ्म को पूर्व की जनसंख्या अंश लिए बीटा वितरण का उपयोग करके "मदद" करने की कोशिश की । इसके अलावा केंद्र और सिग्मा के लिए पूर्व वितरण काफी उचित हैं (मुझे लगता है)।α

तो यहां क्या हो रहा है? क्या मैं कुछ गलत कर रहा हूं या MCMC इस समस्या के लिए उपयुक्त नहीं है?

मैं समझता हूं कि MCMC विधि धीमी होगी, लेकिन तुच्छ हिस्टोग्राम फिट आबादी को हल करने में काफी बेहतर प्रदर्शन करता है।

जवाबों:


6

समस्या इस तरह से होती है कि PyMC इस मॉडल के नमूने लेती है। जैसा कि PyMC दस्तावेज़ीकरण के खंड 5.8.1 में बताया गया है , एक सरणी चर के सभी तत्व एक साथ अपडेट किए जाते हैं। centerइस तरह की छोटी सरणियों के लिए यह एक समस्या नहीं है, लेकिन एक बड़े सरणी के लिए categoryयह कम स्वीकृति दर की ओर जाता है। आप के माध्यम से स्वीकृति दर देख सकते हैं

print mcmc.step_method_dict[category][0].ratio

प्रलेखन में सुझाए गए समाधान स्केलर-मूल्यवान चर की एक सरणी का उपयोग करना है। इसके अलावा, आपको कुछ प्रस्ताव वितरण को कॉन्फ़िगर करने की आवश्यकता है क्योंकि डिफ़ॉल्ट विकल्प खराब हैं। यहाँ कोड है कि मेरे लिए काम करता है:

import pymc as pm
sigmas = pm.Normal('sigmas', mu=0.1, tau=1000, size=2)
centers = pm.Normal('centers', [0.3, 0.7], [1/(0.1)**2, 1/(0.1)**2], size=2)
alpha  = pm.Beta('alpha', alpha=2, beta=3)
category = pm.Container([pm.Categorical("category%i" % i, [alpha, 1 - alpha]) 
                         for i in range(nsamples)])
observations = pm.Container([pm.Normal('samples_model%i' % i, 
                   mu=centers[category[i]], tau=1/(sigmas[category[i]]**2), 
                   value=samples[i], observed=True) for i in range(nsamples)])
model = pm.Model([observations, category, alpha, sigmas, centers])
mcmc = pm.MCMC(model)
# initialize in a good place to reduce the number of steps required
centers.value = [mu1_true, mu2_true]
# set a custom proposal for centers, since the default is bad
mcmc.use_step_method(pm.Metropolis, centers, proposal_sd=sig1_true/np.sqrt(nsamples))
# set a custom proposal for category, since the default is bad
for i in range(nsamples):
    mcmc.use_step_method(pm.DiscreteMetropolis, category[i], proposal_distribution='Prior')
mcmc.sample(100)  # beware sampling takes much longer now
# check the acceptance rates
print mcmc.step_method_dict[category[0]][0].ratio
print mcmc.step_method_dict[centers][0].ratio
print mcmc.step_method_dict[alpha][0].ratio

proposal_sdऔर proposal_distributionविकल्पों से वर्णन किया गया खंड 5.7.1 । केंद्रों के लिए, मैं मोटे तौर पर पीछे के मानक विचलन से मिलान करने का प्रस्ताव निर्धारित करता हूं, जो डेटा की मात्रा के कारण डिफ़ॉल्ट से बहुत छोटा है। PyMC प्रस्ताव की चौड़ाई को ट्यून करने का प्रयास करता है, लेकिन यह केवल तभी काम करता है जब आपकी स्वीकृति दर शुरू होने के लिए पर्याप्त रूप से अधिक हो। के लिए category, डिफ़ॉल्ट proposal_distribution = 'Poisson'जो खराब परिणाम देता है (मुझे नहीं पता कि यह क्यों है, लेकिन यह निश्चित रूप से एक द्विआधारी चर के लिए एक समझदार प्रस्ताव की तरह नहीं लगता है)।


धन्यवाद, यह वास्तव में उपयोगी है, हालांकि यह लगभग असहनीय रूप से धीमा हो जाता है। क्या आप संक्षेप में इसके अर्थ के बारे में बता सकते हैं proposal_distributionऔर इसका proposal_sdउपयोग Priorकरना बेहतर क्यों है?
user2304916

धन्यवाद, टॉम। मैं मानता हूं कि यहां पोइसन एक अजीब विकल्प है। मैंने एक मुद्दा खोला: github.com/pymc-devs/pymc/issues/627
twiecki

2

σ

sigmas = pm.Exponential('sigmas', 0.1, size=2)

अपडेट करें:

मैंने आपके मॉडल के इन भागों को बदलकर डेटा के प्रारंभिक मापदंडों के पास प्राप्त किया:

sigmas = pm.Exponential('sigmas', 0.1, size=2)
alpha  = pm.Beta('alpha', alpha=1, beta=1)

और कुछ पतले के साथ mcmc आह्वान:

mcmc.sample(200000, 3000, 10)

परिणाम:

अल्फा

केन्द्रों

बैठने वाली सिग्माओं

डाकिया बहुत अच्छे नहीं हैं ... बीयूजीएस बुक के खंड 11.6 में वे इस प्रकार के मॉडल और राज्य के बारे में चर्चा करते हैं कि कोई स्पष्ट समाधान नहीं है। यहां भी देखें ।


यह एक अच्छी बात है, मैं अब एक गामा का उपयोग कर रहा हूं। फिर भी, अल्फा ट्रेस हमेशा 0 (0.4 के बजाय) को जाता है। मुझे आश्चर्य है कि अगर मेरे उदाहरण में कुछ बेवकूफ बग छिपकली है।
user2304916

मैंने गामा (.1, .1) की कोशिश की, लेकिन ऍक्स्प (.1) बेहतर काम करने लगता है। इसके अलावा, जब mcmc.sample(60000, 3000, 3)
ऑटोकैरेलेशन

2

साथ ही, मिश्रण मॉडल के लिए एमसीएमसी का उपयोग करने के लिए गैर-पहचान एक बड़ी समस्या है। असल में, यदि आप अपने क्लस्टर साधन और क्लस्टर असाइनमेंट पर लेबल स्विच करते हैं, तो संभावना नहीं बदलती है, और यह नमूना (चेन के बीच या चेन के भीतर) को भ्रमित कर सकता है। एक चीज जिसे आप कम करने की कोशिश कर सकते हैं वह है PyMC3 में संभावित का उपयोग करना। संभावित के साथ एक जीएमएम का एक अच्छा कार्यान्वयन यहां है । इस तरह की समस्याओं के लिए पश्चगामी भी आमतौर पर अत्यधिक बहुपद है, जो एक बड़ी समस्या भी प्रस्तुत करता है। आप इसके बजाय EM (या वैरिएशन के संदर्भ) का उपयोग करना चाह सकते हैं।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.