对于相关分布采样,是否有scipy _norm_pdf的快速替代方案?

问题描述 投票:2回答:1

我已经为蒙特卡洛模拟拟合了一系列SciPy连续分布,并希望从这些分布中获取大量样本。但是,我希望能够获取相关样本,以使第i个样本从每个分布中获取例如第90个百分点。

[这样做时,我发现SciPy的表现有些古怪:

# very fast way to many uncorrelated samples of length n
for shape, loc, scale, in distro_props:
    sp.stats.norm.rvs(*shape, loc=loc, scale=scale, size=n)

# verrrrryyyyy slow way to take correlated samples of length n
correlate = np.random.uniform(size=n)
for shape, loc, scale, in distro_props:
    sp.stats.norm.ppf(correlate, *shape, loc=loc, scale=scale)

关于该结果的大多数结果都声称,如果来自类型检查等包装程序,则这些SciPy发行版的运行缓慢。但是,当我分析代码时,大部分时间都花在基础数学函数[_continuous_distns.py:179(_norm_pdf)] 1上。此外,它以n缩放,这意味着它在内部遍历每个元素。

SciPy docs on rv_continuous几乎似乎建议子类为性能而重写此子类,但是我将猴子补丁加入SciPy以加快其ppf的工作似乎很奇怪。我只是从ppf公式中计算出法线,但是我也使用对数法线和偏斜法线,这很难实现。

所以,在Python中为正态,对数正态和偏态正态分布计算快速ppf的最佳方法是什么?或更广泛地说,是从几个这样的分布中获取相关样本?

python numpy scipy distribution montecarlo
1个回答
0
投票

如果只需要普通的ppf,确实很慢,但确实令人困惑,但是您可以改用scipy.special.erfinv

x = np.random.uniform(0,1,100)
np.allclose(special.erfinv(2*x-1)*np.sqrt(2),stats.norm().ppf(x))
# True
timeit(lambda:stats.norm().ppf(x),number=1000)
# 0.7717257660115138
timeit(lambda:special.erfinv(2*x-1)*np.sqrt(2),number=1000)
# 0.015020604943856597
© www.soinside.com 2019 - 2024. All rights reserved.