首页 > 解决方案 > 为什么 norm.cdf 在 scipy 中比 norm.pdf 快?

问题描述

我现在正在使用scipy一些norm.pdfnorm.cdf计算。我想知道为什么cdf比 快pdf

我知道 有一些渐近方法norm.cdf,而在 中似乎使用scipy了 的集成norm.pdf。这就是为什么我无法想象cdfpdf. 如果是集成的话,cdf应该会慢很多pdf(也许并行计算能帮上大忙?);如果应用渐近方法,我仍然认为cdf可能比pdf.

下面显示了一些简单的示例:

import scipy.stats as st
from datetime import datetime
import numpy as np
num_iter = 100000
x_lower = 0.25
x_upper = 0.75

time_start = datetime.now()
for x in np.arange(x_lower, x_upper, (x_upper - x_lower) / (num_iter - 1)):
    y = st.norm.pdf(x)
time_end = datetime.now()
print(time_end - time_start)

time_start = datetime.now()
for x in np.arange(x_lower, x_upper, (x_upper - x_lower) / (num_iter - 1)):
    y = st.norm.cdf(x)
time_end = datetime.now()
print(time_end - time_start)

以下是运行结果:

0:00:05.736985
0:00:04.896390

标签: pythonscipystatisticsnormal-distribution

解决方案


快速查看源代码表明,它只是使用 NumPyscipy.stats.norm.pdf返回 pdf 的值:x

def _norm_pdf(x):
return np.exp(-x**2/2.0) / _norm_pdf_C

哪里_norm_pdf_C = np.sqrt(2*np.pi)

对于 cdf,由于我们谈论的是正态分布,因此使用了特殊函数(关于它们与正态分布之间的关系,请参见此处)。

SciPy直接在 C 中实现特殊功能。特别是,累积分布函数是从 计算的ndtr.c。所以,即使 NumPy 真的很快,我认为在这种情况下 C 仍然更快。

编辑

对不起,我刚刚意识到我的回答并没有完全回答你的问题。

首先,NumPy 在 C 中也实现了数学运算。因此,要了解为什么会出现时代差异,就应该了解 C 中发生了什么。

  • 如果你看这个问题,似乎数值和硬件架构会影响时间。

所以我再次检查了 cdf 的 C 实现,我发现评估特殊函数的多项式的常数和系数不是计算的,而是存储在数组和变量中的!例如,1/sqrt(2)包含在NPY_SQRT1_2. 这可能是 cdf 比 pdf 快的原因!

因此,我尝试计算已初始化常量的 pdf:

import scipy.stats as st
from datetime import datetime
import numpy as np
num_iter = 100000
x_lower = 0.25
x_upper = 0.75

const = np.sqrt(2*np.pi)
time_start = datetime.now()
for x in np.arange(x_lower, x_upper, (x_upper - x_lower) / (num_iter - 1)):
    # y = st.norm.pdf(x)
    y = np.exp((x**2 / 2)) / const
time_end = datetime.now()
print(time_end - time_start)

time_start = datetime.now()
for x in np.arange(x_lower, x_upper, (x_upper - x_lower) / (num_iter - 1)):
    y = st.norm.cdf(x)
time_end = datetime.now()

这段代码给了我:

0:00:00.202531
0:00:07.703083

请注意,这也norm.pdf预先初始化了 pdf 的分母,但是在 for 循环中,您每次都调用该方法,从而减慢速度。

PS:如果您尝试摆脱原始代码中的循环并简单地使用x = np.arange(x_lower, x_upper, (x_upper - x_lower) / (num_iter - 1)), cdf 再次更快。原因可能是 cdf 是用多项式近似计算的。但我没有找到有关 C 如何准确处理指数以进行比较的信息。


推荐阅读