以下是高斯密度函数的基本接受/拒绝采样器的两种不同实现,只有一些“未知”归一化常数,现在基本采样器(方法1 )涉及重复循环和生成该循环中每个步骤所需的两个必需随机变量。
对于方法2 另一方面,模拟了一批这些随机变量,然后循环进行第一次接受,如果没有,则模拟新批次等等。现在当接受概率很小时方法2 看起来确实快得多,所以我的第一个问题是方法2 能否更有效地实施?如果这种预先模拟的随机变量批量是最有效的方法,那么是否有一种原则性的方法来选择这些批次应该有多大?
import numpy as np
from scipy.stats import norm
from numpy.random import uniform
q = norm(loc=0., scale=3.)
def p_(x):
return np.exp(-0.5*x**2)
k = 1./q.pdf(0.)
def AR1():
while True:
z = q.rvs()
u = uniform(low=0., high=k*q.pdf(z))
if u <= p_(z):
return z
BATCH_SIZE = 5
def AR2():
nt = 0
Zs = q.rvs(size=BATCH_SIZE) # random variables z ~ q(z)
Us = uniform(low=0., high=k*q.pdf(Zs)) # uniform rvs on [0, k*q(z)]
Pvals = p_(Zs) # unnormalised pdf p_(z)
while True:
if Us[nt] <= Pvals[nt]:
return Zs[nt]
else:
nt +=1
if nt > BATCH_SIZE - 1:
Zs = q.rvs(size=BATCH_SIZE)
Us = uniform(low=0., high=k*q.pdf(Zs))
Pvals = p_(Zs)
nt = 0
答案 0 :(得分:0)
由于来自AR的样本是独立的,因此您无需像大都会黑名单算法一样一一生成它们。因此,您可以一次全部生成它们,并通过使用数组操作来加快功能。
假设我们要1000个样本。使用您的AR2:
>> %timeit sample2 = [AR2() for _ in range(1000)]
513 ms ± 134 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
我们可以改为创建类似函数的数组:
def AR_array(size = 100):
# generate a slightly larger total samples
# based on the acceptance ratio: 1/k
Zs = q.rvs(size= np.int(size*(k+1)))
Us = uniform(low=0., high=k*q.pdf(Zs))
Pvals = p_(Zs) # unnormalized pdf p_(z)
Zs_accepted = Zs[Us <= Pvals] # select accepted samples
return Zs_accepted[0:size] # return the required sample size
生成1000个样本。
>> %timeit AR_array(1000)
1.9 ms ± 209 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
健全性检查:
>> norm.fit(AR_array(1000)) # MLE of mean and std
(-0.05960200510480021, 0.9917248073504155)