首页 文章

在python中为一对发行版生成MLE

提问于
浏览
5

好的,所以我当前的曲线拟合代码有一个步骤,使用scipy.stats根据数据确定正确的分布,

distributions = [st.laplace, st.norm, st.expon, st.dweibull, st.invweibull, st.lognorm, st.uniform]
mles = []

for distribution in distributions:
    pars = distribution.fit(data)
    mle = distribution.nnlf(pars, data)
    mles.append(mle)

results = [(distribution.name, mle) for distribution, mle in zip(distributions, mles)]

for dist in sorted(zip(distributions, mles), key=lambda d: d[1]):
    print dist
best_fit = sorted(zip(distributions, mles), key=lambda d: d[1])[0]
print 'Best fit reached using {}, MLE value: {}'.format(best_fit[0].name, best_fit[1])          


print [mod[0].name for mod in sorted(zip(distributions, mles), key=lambda d: d[1])]

数据是数值列表 . 到目前为止,这对于拟合单峰分布非常有效,在脚本中确认,该脚本随机生成随机分布的值并使用curve_fit重新确定参数 .

A fitted normal distribution

现在我想使代码能够处理双峰分布,如下例所示:

A normal and an exponential distribution combined

是否有可能从scipy.stats获取一对模型的MLE,以确定特定的一对分布是否适合数据?,类似于

distributions = [st.laplace, st.norm, st.expon, st.dweibull, st.invweibull, st.lognorm, st.uniform]
distributionPairs = [[modelA.name, modelB.name] for modelA in distributions for modelB in distributions]

并使用这些对来获得适合数据的那对分布的MLE值?

1 回答

  • 2

    这不是一个完整的答案,但它可以帮助您解决您的问题 . 假设您知道您的问题是由两个密度产生的 . 解决方案是使用 k-mean or EM algorithm.

    Initalization . 您可以通过将每个观察值影响到一个或另一个密度来初始化算法 . 并初始化两个密度(初始化密度的参数,你的情况中的一个参数是“高斯”,“拉普拉”等等...迭代 . 然后,迭代,你运行以下两个步骤:

    Step 1. 优化参数,假设每个点的影响是正确的 . 您现在可以使用任何优化求解器 . 此步骤为您提供适合您数据的最佳两个密度(使用给定参数)的估计 .

    Step 2. 您可以根据最大可能性将每个观察分类为一个密度或另一个密度 .

    你重复直到收敛 .

    这个网页很好地解释了https://people.duke.edu/~ccc14/sta-663/EMAlgorithm.html

    如果您不知道有多少密度生成了您的数据,则问题就更加困难了 . 你必须处理惩罚性的分类问题,这有点难 .

    以下是一个简单的编码示例:您知道您的数据来自2个不同的高斯(您不知道每个密度生成了多少变量) . 在您的情况下,您可以调整此代码以循环每个可能的密度对(计算更长,但我会根据经验工作)

    import scipy.stats as st
    import numpy as np
    
    #hard coded data generation
    data = np.random.normal(-3, 1, size = 1000)
    data[600:] = np.random.normal(loc = 3, scale = 2, size=400)
    
    #initialization
    
    mu1 = -1
    sigma1 = 1
    
    mu2 = 1
    sigma2 = 1
    
    #criterion to stop iteration
    epsilon = 0.1
    stop = False
    
    while  not stop :  
        #step1
        classification = np.zeros(len(data))
        classification[st.norm.pdf(data, mu1, sigma1) > st.norm.pdf(data, mu2, sigma2)] = 1
    
        mu1_old, mu2_old, sigma1_old, sigma2_old = mu1, mu2, sigma1, sigma2
    
        #step2
        pars1 = st.norm.fit(data[classification == 1])
        mu1, sigma1 = pars1
        pars2 = st.norm.fit(data[classification == 0])
        mu2, sigma2 = pars2
    
        #stopping criterion
        stop = ((mu1_old - mu1)**2 + (mu2_old - mu2)**2 +(sigma1_old - sigma1)**2 +(sigma2_old - sigma2)**2) < epsilon
    
    #result    
    print("The first density is gaussian :", mu1, sigma1)
    print("The first density is gaussian :", mu2, sigma2)
    print("A rate of ", np.mean(classification), "is classified in the first density")
    

    希望能帮助到你 .

相关问题