首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >马尔可夫链montecarlo积分与无限时间循环

马尔可夫链montecarlo积分与无限时间循环
EN

Stack Overflow用户
提问于 2020-05-14 23:28:31
回答 1查看 80关注 0票数 0

我正在实现一个马尔可夫链Montecarlo与大都会和巴克阿尔法的数值积分。我创建了一个名为MCMCIntegrator()的类。我给它添加了一些属性,其中之一就是我们试图集成的函数( lambda)的pdf,称为g

代码语言:javascript
复制
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是普通内核的标准偏差,几秒钟后就会看到。real_int是积分从1到2的积分的值。我用R脚本生成了它。现在说到问题上。

代码语言:javascript
复制
 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)

在此方法下面是一个计算1,2间隔中数字比例的integrate()方法:

代码语言:javascript
复制
    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)

这是主要的功能:

代码语言:javascript
复制
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()

我被困在无穷大的循环中,我不知道为什么会发生这种情况。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2020-05-15 00:51:30

一些事情..。您挂在chain方法中,因为alpha计算返回NaN,因为g()返回NaN。看看我插入到您的代码中的打印语句并运行它..。

贴士:

对于某些测试值,chain.

  • Test
  1. g()是一个类函数,就像 g()一样,很明显,
    1. 没有有条件地定义像alpha这样的函数。容易混淆,容易出错/很难排除故障。只需传递它需要的内容,也可以使它成为类函数alpha(a, b, method=None)
    2. Take,查看`_chain函数中更新i的位置.您意识到,您正面临一个漫长的循环过程的风险,因为您只更新i,conditionally!
    3. You就会因为使用numpy数组而被设置为灾难。在实际数据之后,可能会有一堆尾随零,因为您正在过写大的零列表。这里不需要numpy数组,只需使用python空列表并在其上追加新值,无论是0还是one...based。

在进行故障排除(或单元测试功能)时,添加几个打印语句。试试我在你下面的功能.这是我过去用来弄清楚发生了什么

代码语言:javascript
复制
def _chain(self, method=None, verbose=True):

    """
        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): 
            if verbose: print(f'g(a): {self.g(a)}, g(b): {self.g(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 verbose: print(f'old: {old:.3f} new: {new:.3f} alpha: {al:.3f} u: {u:.3f}')
        if al > u:
            sample[i] = new
            old = new
            i += 1              # do you really want to conditionally update i?
        sys.exit(-1)            # to breakout of infinite loop...


    return np.array(sample)
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/61809144

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档