Python 为什么norm.cdf比scipy中的norm.pdf快?

Python 为什么norm.cdf比scipy中的norm.pdf快?,python,scipy,statistics,normal-distribution,Python,Scipy,Statistics,Normal Distribution,我现在使用scipy进行一些norm.pdf和norm.cdf计算。我想知道为什么cdf比pdf快 我知道有一些关于norm.cdf的渐近方法,而在scipy中,似乎使用了norm.pdf的积分。这就是为什么我无法想象cdf比pdf快。如果集成是这样的话,cdf应该比pdf慢得多(也许并行计算会有很大帮助?);如果采用渐近方法,我仍然认为cdf可能比pdf慢一点 下面是一些简单的示例: import scipy.stats as st from datetime import datetime

我现在使用
scipy
进行一些
norm.pdf
norm.cdf
计算。我想知道为什么
cdf
pdf

我知道有一些关于
norm.cdf
的渐近方法,而在
scipy
中,似乎使用了
norm.pdf
的积分。这就是为什么我无法想象
cdf
pdf
快。如果集成是这样的话,
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

快速查看源代码可以发现,
scipy.stats.norm.pdf
只需使用NumPy返回pdf的
x
值:

def _norm_pdf(x):
return np.exp(-x**2/2.0) / _norm_pdf_C
其中
\u norm\u pdf\u C=np.sqrt(2*np.pi)

对于cdf,因为我们讨论的是正态分布,所以使用了特殊函数(用于它们与正态分布之间的关系,)

SciPy实现特殊的功能。特别是,累积分布函数是根据。所以,即使NumPy真的很快,我想在这种情况下C还是更快

编辑

对不起,我刚刚意识到我的答案并不能完全回答你的问题

首先,NumPy还用C实现数学运算。 因此,要理解为什么时间不同,我们应该理解C

  • 如果你看这个,似乎数值和硬件结构会影响时间
所以我再次检查了cdf的C实现,我发现计算特殊函数的多项式的常数和系数不是计算出来的,而是存储在数组和变量中!例如,
1/sqrt(2)
包含在
NPY\u SQRT1\u 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循环中,您每次都在调用该方法,这会减慢速度


附言:如果您试图摆脱原始代码中的循环,只需使用
x=np.arange(x_lower,x_upper,(x_upper-x_lower)/(num_iter-1))
,cdf会更快。原因可能是cdf是用多项式近似计算的。但是我没有找到关于C如何精确处理指数的信息来进行比较。

非常感谢您的详细回答,这很有意义。