python:自定义概率函数的随机抽样

时间:2017-01-04 17:41:31

标签: python numpy random scipy

我有一个具有概率密度函数的分段四次分布:

p(x)= c(x/a)^2 if 0≤x<a; 
      c((b+a-x)^2/b)^2 if a≤x≤b;
      0 otherwise

假设c,a,b已知,我试图从分布中抽取100个随机样本。我怎么能用numpy / scipy来做呢?

2 个答案:

答案 0 :(得分:4)

一种标准方法是为累积分布函数的倒数找到显式公式G(U)。这在这里是可行的(尽管它自然会被分段定义),然后使用U f(a,b,c,d,x) = c*x**2 #if 0 <= x <= a 在[0,1]上统一来生成样本。

在这种情况下,我认为我已经制定了详细信息,但您需要检查微积分/代数。

首先,为了简化一些事情,它有助于引入一些新参数。让

f(a,b,c,d,x) = d*(x-e)**4 #if a < x <= b

p(x)

然后您的p(x) = f(a,b,c/a**2,c/b**2,a+b)

提供
f

我整合def Finverse(a,b,c,d,e,x): if x <= (c*a**3)/3: return (3*x/c)**(1/3) else: return e + ((a-e)**5 - (5*c*a**3)/(3*d))**(1/5) 以找到累积分布,然后反转并得到以下内容:

def randX(a,b,c):
    u = random.random()
    return Finverse(a,b,c/a**2,c/b**2,a+b,u)

假设这是对的,那么简单地说:

wsh

在这种情况下,可以制定出明确的公式。当你无法计算逆的这样的公式时,可以考虑使用@lucianopaz描述的蒙特卡罗方法

答案 1 :(得分:2)

由于您的功能在xp(x)都有效,我建议您使用Monte Carlo rejection sampling。基本原则是您绘制两个统一的随机数,一个代表x空间边界x中的候选[0,b],另一个代表y。如果y低于或等于规范化的p(x),则会返回采样的x,否则会继续下一次迭代

import numpy as np
def rejection_sampler(p,xbounds,pmax):
    while True:
        x = np.random.rand(1)*(xbounds[1]-xbounds[0])+xbounds[0]
        y = np.random.rand(1)*pmax
        if y<=p(x):
            return x

此处,p应该可以按规范化分段概率密度调用,xbounds可以是包含下限和上限的列表或元组,{{1 x区间中概率密度的最大值。