【发布时间】:2020-05-14 23:28:31
【问题描述】:
我正在实现一个带有 Metropolis 和 barkes alpha 的马尔可夫链 Montecarlo,用于数值积分。我创建了一个名为MCMCIntegrator() 的类。我已经为它加载了一些属性,其中之一是我们试图集成的函数(一个 lambda)的 pdf,称为 g。
import numpy as np
import scipy.stats as st
class MCMCIntegrator:
def __init__(self):
self.g = lambda x: st.gamma.pdf(x, 0, 1, scale=1 / 1.23452676)*np.abs(np.cos(1.123454156))
self.size = 10000
self.std = 0.6
self.real_int = 0.06496359
这个类还有其他方法,size是类必须生成的样本大小,std是Normal Kernel的标准差,几秒钟后你就会看到。 real_int 是我们正在积分的函数从 1 到 2 的积分值。我用 R 脚本生成了它。现在,解决问题。
def _chain(self, method=None):
"""
Markov chain heat-up with burn-in
:param method: Metrpolis or barker alpha
:return: np.array containing the sample
"""
old = 0
sample = np.zeros(int(self.size * 1.5))
i = 0
if method:
def alpha(a, b): return min(1, self.g(b) / self.g(a))
else:
def alpha(a, b): return self.g(b) / (self.g(a) + self.g(b))
while i != len(sample):
new = st.norm(loc=old, scale=self.std).rvs()
new = abs(new)
al = alpha(old, new)
u = st.uniform.rvs()
if al > u:
sample[i] = new
old = new
i += 1
return np.array(sample)
这个方法下面是一个integrate()方法,计算[1, 2]区间内数字的比例:
def integrate(self, method=None):
"""
Integration step
"""
sample = self._chain(method=method)
# discarding 30% of the sample for the burn-in
ind = int(len(sample)*0.3)
sample = sample[ind:]
setattr(self, "sample", sample)
sample = [1 if 1 < v < 2 else 0 for v in sample]
return np.mean(sample)
这是主要功能:
def main():
print("-- RESULTS --".center(20), end='\n')
mcmc = MCMCIntegrator()
print(f"\t{mcmc.integrate()}", end='\n')
print(f"\t{np.abs(mcmc.integrate() - mcmc.real_int) / mcmc.real_int}")
if __name__ == "__main__":
main()
我陷入了无限循环,我不知道为什么会这样。
【问题讨论】:
-
代码无法如图所示执行。
_chain中的new变量未定义。除此之外还有许多其他风格推荐...... -
...将
g转换为类函数...标记 lambda 有点违背 lambda 的目的。您正在有条件地定义函数alpha,这是一种错误的形式。只需创建一个函数并将其发送输入以定义如何操作。稍后,您将 alpha 重新定义为变量,覆盖命名函数.... -
我已经看到了变量的问题,我已经改变了它,就像我现在的代码一样,仍然存在同样的问题。我很高兴听到您更改代码的建议
标签: python numpy while-loop montecarlo markov-chains