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

Nea*_*JMD 5 python numpy distribution montecarlo scipy

我已经为蒙特卡罗模拟拟合了一系列 SciPy 连续分布,并且希望从这些分布中获取大量样本。但是,我希望能够获取相关样本,以便第ith 个样本从每个分布中获取例如第 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)
Run Code Online (Sandbox Code Playgroud)

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

rv_continuous 上的 SciPy文档几乎似乎暗示子类应该为了性能而覆盖它,但我会猴子补丁到 SciPy 以加速他们的 ppf 似乎很奇怪。我只是根据 ppf 公式计算法线,但我也使用对数正态和偏斜正态,这更难实现。

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

Nea*_*JMD 0

最终,这个问题是由我使用偏斜正态分布引起的。偏斜法线的 ppf 实际上没有闭合形式的解析定义,因此为了计算 ppf,它回退到 的scipy.continuous_rv数值近似,其中涉及迭代计算 cdf 并使用它对 ppf 进行归零价值。倾斜法线 pdf 是法线 pdf 和法线 cdf 的乘积,因此这种数值近似多次称为法线 pdf 和 cdf。这就是为什么当我分析代码时,问题似乎是正态分布,而不是 SKU 正态分布。这个问题的另一个答案是能够通过跳过类型检查来节省时间,但实际上并没有对运行时增长产生影响,只是对小n运行时产生影响。

为了解决这个问题,我用Johnson SU分布替换了偏斜正态分布。它比正态分布多 2 个自由参数,因此可以有效地拟合不同类型的偏斜和峰度。它支持所有实数,并且具有封闭形式的 ppf 定义,可以在 SciPy 中快速实现。下面您可以看到我从第 10 个、第 50 个和第 90 个百分位数拟合的 Johnson SU 分布示例。

分布示例