【问题标题】:efficient sampling from beta-binomial distribution in pythonpython中beta二项分布的有效采样
【发布时间】:2023-12-29 02:03:01
【问题描述】:

对于随机模拟,我需要绘制大量的随机数,它们是 beta 二项式分布的。

目前我以这种方式实现它(使用python):

import scipy as scp
from scipy.stats import rv_discrete

class beta_binomial(rv_discrete):
       """
       creating betabinomial distribution by defining its pmf
       """
       def _pmf(self, k, a, b, n):
          return scp.special.binom(n,k)*scp.special.beta(k+a,n-k+b)/scp.special.beta(a,b)

所以可以通过以下方式对随机数 x 进行采样:

betabinomial = beta_binomial(name="betabinomial")
x = betabinomial.rvs(0.5,0.5,3) # with some parameter 

问题是,对一个随机数进行采样需要 ca. 0.5ms,在我的例子中,这主导了整个模拟速度。限制因素是对 beta 函数(或其中的 gamma 函数)的评估。

有没有人知道如何加快采样速度?

【问题讨论】:

    标签: python random distribution stochastic beta-distribution


    【解决方案1】:

    嗯,这是工作且经过轻微测试的代码,似乎更快,使用Beta-Binomial 的复合分布属性。

    我们从 beta 中采样 p,然后将其用作二项式的参数。如果您要对大型向量进行采样,速度会更快。

    import numpy as np
    
    def sample_Beta_Binomial(a, b, n, size=None):
        p = np.random.beta(a, b, size=size)
        r = np.random.binomial(n, p)
    
        return r
    
    np.random.seed(777777)
    q = sample_Beta_Binomial(0.5, 0.5, 3, size=10)
    print(q)
    

    输出是

    [3 1 3 2 0 0 0 3 0 3]
    

    快速测试

    np.random.seed(777777)
    
    n = 10
    a = 2.
    b = 2.
    N = 100000
    
    q = sample_Beta_Binomial(a, b, n, size=N)
    
    h = np.zeros(n+1, dtype=np.float64) # histogram
    for v in q: # fill it
        h[v] += 1.0
    
    h /= np.float64(N) # normalization
    print(h)
    

    打印直方图

    [0.03752 0.07096 0.09314 0.1114  0.12286 0.12569 0.12254 0.1127  0.09548 0.06967 0.03804]
    

    这与 Beta-Binomial 的 Wiki 页面中的绿色图表非常相似

    【讨论】:

    • 谢谢!我希望得到更多技术性的响应,但这个简单的解决方案效果很好,而且速度快了十倍以上。但当然,它并不具备 rv_discrete 类的所有优点。这只是为了采样完全没问题。
    • @Balou 好吧,你总是可以用你自己的函数替换类方法:betabinomial.rvs = sample_Beta_Binomial 并有两种方式