python - 为什么 norm.cdf 在 scipy 中比 norm.pdf 快?
问题描述
我现在正在使用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
解决方案
快速查看源代码表明,它只是使用 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 如何准确处理指数以进行比较的信息。
推荐阅读
- c# - 在 C# 中使用 AES 进行确定性加密
- xml - PyZillow 不返回属性详细信息
- azure - 具有长期 Azure Functions 的 Azure 数据工厂
- javascript - 谷歌图表调试
- python - 通过使用条件添加列来创建列
- android - 如何将 android MediaRecorder 输出转换为 MP3 文件
- ios - 如何仅在较小的设备上隐藏状态栏?
- c++ - Marshal 管理非托管的无符号整数数组
- java - 在 PrintWriter 格式错误中使用 PrintStream
- reactjs - 在 Docker 中使用 React 和 Nginx 授权 Spotify