我有一个具有概率密度函数的分段四次分布:
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来做呢?
答案 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)
由于您的功能在x
和p(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区间中概率密度的最大值。