我想在python中实现一个函数(使用numpy
),该函数采用数学函数(例如下面的p(x) = e^(-x)
)作为输入并生成随机数,并根据该随机数进行分配数学函数的概率分布。我需要绘制它们,以便我们可以看到分布。
实际上,我确实需要一个随机数生成器函数来将以下两个数学函数作为输入,但是如果可以使用其他函数,为什么不呢?
1)p(x) = e^(-x)
2)g(x) = (1/sqrt(2*pi)) * e^(-(x^2)/2)
有人知道这在python中如何实现吗?
答案 0 :(得分:4)
NumPy提供了a wide range of probability distributions。
第一个功能是带有参数1的exponential distribution。
np.random.exponential(1)
第二个是normal distribution,平均值为0,方差为1。
np.random.normal(0, 1)
请注意,在这两种情况下,参数都是可选的,因为这些是这些分布的默认值。
作为旁注,您还可以在random
模块中分别以random.expovariate
和random.gauss
的形式找到这些分布。
尽管NumPy可能满足您的所有需求,但请记住,您始终可以计算分布的倒数cumulative distribution function并从uniform distribution输入值。
inverse_cdf(np.random.uniform())
例如,如果NumPy不提供指数分布,则可以执行此操作。
exponential = lambda: -np.log(-np.random.uniform())
如果遇到不容易计算CDF的分布,请考虑filippo's great answer。
答案 1 :(得分:2)
对于简单的分布(如所需的分布),或者如果您易于转换为封闭形式的CDF,则可以按照Olivier的答案正确指出的那样,在NumPy中找到大量采样器。
对于任意分布,可以使用马尔可夫链蒙特卡洛采样方法。
这些算法中最简单且可能更容易理解的变量是Metropolis采样。
基本思想如下:
x
开始并采取随机步骤xnew = x + delta
p(x)
和新的p(xnew)
中评估所需的概率分布p(xnew)/p(x) >= 1
接受此举可以显示,例如Sokal 2 ,该方法采样的点遵循接受概率分布。
可以在PyMC3
包中找到Python中Montecarlo方法的广泛实现。
这里只是一个玩具示例,目的只是向您展示基本思想,而不以任何方式作为参考实现。请认真阅读成熟的软件包。
def uniform_proposal(x, delta=2.0):
return np.random.uniform(x - delta, x + delta)
def metropolis_sampler(p, nsamples, proposal=uniform_proposal):
x = 1 # start somewhere
for i in range(nsamples):
trial = proposal(x) # random neighbour from the proposal distribution
acceptance = p(trial)/p(x)
# accept the move conditionally
if np.random.uniform() < acceptance:
x = trial
yield x
让我们看看它是否适用于一些简单的发行版
def gaussian(x, mu, sigma):
return 1./sigma/np.sqrt(2*np.pi)*np.exp(-((x-mu)**2)/2./sigma/sigma)
p = lambda x: gaussian(x, 1, 0.3) + gaussian(x, -1, 0.1) + gaussian(x, 3, 0.2)
samples = list(metropolis_sampler(p, 100000))
def cauchy(x, mu, gamma):
return 1./(np.pi*gamma*(1.+((x-mu)/gamma)**2))
p = lambda x: cauchy(x, -2, 0.5)
samples = list(metropolis_sampler(p, 100000))
您实际上不必从适当的概率分布中采样。您可能只需要强制执行一个有限的域,即可在其中采样随机步骤 3
p = lambda x: np.sqrt(x)
samples = list(metropolis_sampler(p, 100000, domain=(0, 10)))
p = lambda x: (np.sin(x)/x)**2
samples = list(metropolis_sampler(p, 100000, domain=(-4*np.pi, 4*np.pi)))
关于提案的分布,收敛,相关性,效率,应用,贝叶斯形式主义,其他MCMC采样器等,还有很多话要说。 我认为这不是合适的地方,而且有很多资料比我在网上可以找到的更好。
此处的想法是倾向于概率较高的勘探,但仍会关注低概率区域,因为它们可能导致其他峰值。基本是建议提案分布的选择,即如何选择要探索的新点。步长太小可能会限制您到发行版的有限区域,步长太大可能会导致效率非常低下。
面向物理。如今,贝叶斯形式主义(Metropolis-Hastings)受到人们的青睐,但是恕我直言,对于初学者而言,它有点难掌握。在线上有很多教程,请参见例如this one来自杜克大学。
未显示实现不会增加太多混乱,但是很简单,您只需要将试验步骤包装在域边缘或使所需函数在域外变为零即可。