余弦波的贝叶斯拟合比预期花费更长的时间

时间:2018-09-30 18:42:45

标签: python statistics linear-regression bayesian markov-chains

在最近的作业中,我被要求使用Metropolis算法对一组数据 a b 进行贝叶斯拟合。给出 a b 之间的关系:

  

e(t)= e_0 * cos(w * t)

     

w = 2 * pi

Metropolis算法是(与其他拟合效果很好):

def metropolis(logP, args, v0, Nsteps, stepSize):

    vCur = v0
    logPcur = logP(vCur, *args)
    v = []
    Nattempts = 0

    for i in range(Nsteps):
        while(True):
            #Propose step:
            vNext = vCur + stepSize*np.random.randn(*vCur.shape)
            logPnext = logP(vNext, *args)
            Nattempts += 1

            #Accept/reject step:
            Pratio = (1. if logPnext>logPcur else np.exp(logPnext-logPcur))

            if np.random.rand() < Pratio: 
                vCur = vNext
                logPcur = logPnext
                v.append(vCur)
                break

    acceptRatio = Nsteps*(1./Nattempts)
    return np.array(v), acceptRatio

我试图使贝叶斯拟合余弦波并使用上面的Metropolis算法:

e_0 = -0.00155 

def strain_t(e_0,t):
    return e_0*np.cos(2*np.pi*t)

data = pd.read_csv('stressStrain.csv')
t = np.array(data['t'])
e = strain_t(e_0,t)

def logfitstrain_t(params,t,e):
    e_0 = params[0]
    sigmaR = params[1]
    strainModel = strain_t(e_0,t)
    return np.sum(-0.5*((e-strainModel)/sigmaR)**2 - np.log(sigmaR))


params0 = np.array([-0.00155,np.std(t)]) 
params, accRatio = metropolis(logfitstrain_t, (t,e), params0, 1000, 0.042)
print('Acceptance ratio:', accRatio)

e0 = np.mean(params[0])
print('e0=',e0)

e_t = e0*np.cos(2*np.pi*t)
sns.jointplot(t, e_t, kind='hex',color='purple')

.csv中的数据看起来像

table with columns "t", "strain", and "stress", with five rows

在我运行run之后没有任何错误消息显示,但是python给我输出输出需要花费很多时间。 我在这里做什么错了?

1 个答案:

答案 0 :(得分:1)

为什么它可能“永远带走”

您的算法设计为一直运行,直到它接受给定数量的提案(示例中为1000)。因此,如果它运行了很长时间,您可能会拒绝一堆建议。当步长太大时会发生这种情况,导致新的建议最终落入似然空间的遥远,低概率区域。 尝试减小步长。这可能还需要您增加样本数量,以确保充分探究后方空间。

更严重的担忧

因为您仅将接受的提案附加到链v,所以您实际上并没有实现Metropolis算法,而是获得了一组有偏见的样本,这些样本倾向于过分代表不太可能后部空间区域。每当新提案被拒绝时,真正的Metropolis实施都会重新附加上一个提案。您仍然可以强制执行最少数量的已接受提案,但实际上每次都必须添加一些内容。