我想从两个截断正态分布之和的分布中抽取 N 个随机样本。我通过从 rv_continuous
子类化 scipy.stats
类并提供一个 pdf 来得到我想要的东西,该 pdf 是两个给定 pdf 的平均值:
import numpy as np
from scipy import stats
my_lim = [0.05, 7] # lower and upper limit
my_loc = [1.2, 3] # loc values of the two truncated normal distributions
my_scale = [0.6, 2] # scale values of the two truncated normal distributions
class sum_truncnorm(stats.rv_continuous):
def _pdf(self, x):
return (stats.truncnorm.pdf(x,
a=(my_lim[0] - my_loc[0]) / my_scale[0],
b=(my_lim[1] - my_loc[0]) / my_scale[0],
loc=my_loc[0],
scale=my_scale[0]) +
stats.truncnorm.pdf(x,
a=(my_lim[0] - my_loc[1]) / my_scale[1],
b=(my_lim[1] - my_loc[1]) / my_scale[1],
loc=my_loc[1],
scale=my_scale[1]) / 2
但是,使用:
my_dist = sum_truncnorm()
my_rvs = my_dist.rvs(size=10)
非常很慢,每个随机值大约需要 5 秒。
我确信这可以更快地完成,但我不知道该怎么做。我是否应该将我的分布定义为(非截断的)正态分布的总和,然后强制截断?我在这个方向上做了一些测试,但这只是快了大约 10 倍,因此仍然很慢。
Google 告诉我,我可能需要使用逆变换采样并覆盖 _rvs
方法,但我未能使其适用于我的截断分布。
答案 0 :(得分:1)
首先,您必须确保 _pdf 已规范化。 框架不会检查它,否则会默默地产生废话。
其次,为了使绘图变量更快,您需要实现一个 _ppf 或 _rvs。仅使用 _pdf,它会通过通用代码路径(数字集成和根查找),这就是为什么您当前的版本很慢。