在最近的作业中,我被要求使用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中的数据看起来像
在我运行run之后没有任何错误消息显示,但是python给我输出输出需要花费很多时间。 我在这里做什么错了?
答案 0 :(得分:1)
您的算法设计为一直运行,直到它接受给定数量的提案(示例中为1000)。因此,如果它运行了很长时间,您可能会拒绝一堆建议。当步长太大时会发生这种情况,导致新的建议最终落入似然空间的遥远,低概率区域。 尝试减小步长。这可能还需要您增加样本数量,以确保充分探究后方空间。
因为您仅将接受的提案附加到链v
,所以您实际上并没有实现Metropolis算法,而是获得了一组有偏见的样本,这些样本倾向于过分代表不太可能后部空间区域。每当新提案被拒绝时,真正的Metropolis实施都会重新附加上一个提案。您仍然可以强制执行最少数量的已接受提案,但实际上每次都必须添加一些内容。