大城市混合高斯混合及参数确定

时间:2019-03-16 14:42:47

标签: python mcmc

所以我混合了两个高斯,我想确定均值(西格玛和权重已知)。为此,我正在尝试将Metropolis-Hasting算法实现为MCMC方法。我尝试从此网站https://python4mpia.github.io/fitting_data/Metropolis-Hastings.html重现该方法,但是我不确定我使用的方法是否正确,因为它真的很慢,我看不到任何好的结果。

我认为问题在于每次迭代的对数似然性确定。我在幻灯片https://www.ceremade.dauphine.fr/~xian/BCS/Bmix.pdf(幻灯片296)中看到,它应该可以在O(n)中计算。另外,我尝试找出这个相关问题是否可以帮助我Speed up Metropolis--Hastings in Python,但没有找到任何答案。

我的问题是,有没有一种方法可以大大加快下面的代码的速度,特别是是否有可能更快地计算对数似然性?

import matplotlib.pyplot as plt
import numpy as np
import math 

# define posterior distribution
def posterior(m1, m2, x):
    #mu, sigma = 5, 2.0 # mean and standard deviation that could be chosen
    num1 = math.exp( - ( x - m1 )**2 / ( 2.0 * sigma1 **2 ) )
    den1 = math.sqrt( 2 * math.pi * sigma1 **2)
    num2 = math.exp( - ( x - m2 )**2 / ( 2.0 * sigma2 **2 ) )
    den2 = math.sqrt( 2 * math.pi * sigma2 **2)
    return  num1 / den1+ num2/den2


# Generate toy Data
N = 10000
s = 10
x_0 = 0
mu1= 5
sigma1=1.0
mu2=1
sigma2=1.0

# Metroplis Hasting for sampling 
def Metroplis_sampling(N, s, x_0):

        p = posterior(mu1, mu2,  x_0)

        samples = []
        x = x_0

        for i in range(N):
            xn = x + np.random.normal(size=1)
            pn = posterior(mu1,  mu2, xn)
            if pn >= p:
                p = pn
                x = xn
            else:
                u = np.random.rand()
                if u < pn/p:
                    p = pn
                    x = xn
            if i % s == 0:
                samples.append(x)

        samples = np.array(samples)

        return samples

Samples = Metroplis_sampling(N, s, x_0)


#Define probabilities for samples
def probabilities(mus, samples):
    mu_1, mu_2 = mus[0], mus[1]
    probas = np.asarray( [math.log(posterior(mu_1, mu_2,  x)) for x in samples] )
    # return log likelihood.
    return np.sum(probas)



# initial guess for mu's as array.
guess = [4.5, 1.5]
# Prepare storing MCMC chain as array of arrays.
A = [guess]
# define stepsize of MCMC.
stepsizes = [0.005, 0.005]  # array of stepsizes
accepted  = 0.0
new_loglik = probabilities(guess, samples)
# Metropolis-Hastings with 10,000 iterations.
for n in range(10000):
    old_mus  = A[len(A)-1]  # old parameter values as array
    old_loglik = new_loglik
    # Suggest new candidate from Gaussian proposal distribution.
    new_mus = numpy.zeros([len(old_mus)])
    for i in range(len(old_mus)):
        # Use stepsize provided for every dimension.
        new_mus[i] = random.gauss(old_mus[i], stepsizes[i])
    new_loglik = probabilities(new_mus, samples)
    # Accept new candidate in Monte-Carlo fashing.
    if (new_loglik > old_loglik):
        A.append(new_mus)
        accepted = accepted + 1.0  # monitor acceptance
    else:
        u = random.uniform(0.0,1.0)
        if (u < math.exp(new_loglik - old_loglik)):
            A.append(new_mus)
            accepted = accepted + 1.0  # monitor acceptance
        else:
            A.append(old_mus)

print ("Acceptance rate = "+str(accepted/10000.0))

0 个答案:

没有答案