加速从叠加的截断正态分布中绘制随机值



我想从一个分布中随机抽取N个样本,这个分布是两个截断的正态分布的和。我通过从scipy.stats子类化rv_continuous类并提供一个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方法,但我未能使其适用于我的截断分布。

首先,您必须确保_pdf是规范化的。框架不会检查它,否则会静默地产生无意义的内容。

第二,为了快速绘制变量,需要实现_ppf或_rvs。如果只使用_pdf,它会遍历通用代码路径(数字集成和查找根),这就是为什么当前版本很慢的原因。

最新更新