python - 使用 scipy 集成模块规范化函数的问题
问题描述
我想在 A 到 B 的范围内对函数(例如 chi2.pdf 的 scipy)进行归一化。例如,chi2.pdf 对其范围从 0 到无穷大进行归一化,并且在该区域上的积分为 1。为了为此,我可以计算函数对 A 到 B 的积分,然后将函数除以该积分。我可以使用以下代码实现这一点:
import numpy as np
from scipy.stats import chi2
from scipy.integrate import quad
A = 2
B = 4
df = 3
z = quad(chi2.pdf,A,B,args=(df,A)[0]
Quad 将参数 df 作为自由度,将 A 作为 loc - 由于各种原因,我希望我的卡方函数被 A 移动。现在我有了z
我可以定义一个新函数:
def normalized_chi_2(x,df,A,z):
y = chi2.pdf(x,df,A)/z
return(y)
再次快速检查集成:
integral_chi2 = quad(normalized_chi_2,A,B,args=(df,A,z)[0]
print(integral_chi2)
>0.9999999999999999
说明我达到了我的目的。但是有两个函数,并且主要计算 Z 相对笨重,所以我想我可以定义一个新函数并在该函数内部计算 Z。
def normalized_chi_1(x,df,A):
z = quad(chi2.pdf,A,B,args=(df,A))[0]
y = chi2.pdf(x,df,A) / z
return(y)
现在,当我再次进行快速集成时:
integral_chi1 = quad(normalized_chi_1,A,B,args=(df,A))[0]
print(integral_chi1)
>0.42759329552910064
我没有得到 1,我得到的值等于原始的、未标准化的 chi2.pdf(上面的 z)的值。另一个问题是normalized_chi_1
(它需要df和A,并计算它自己的z)非常非常慢。例如,方法 2,我在函数外部计算 z 并将其传递给下一个函数需要 ~0.07 秒,而方法 1,我在函数内部计算 z 需要 ~7.30 秒。慢了一百倍。
解决方案
quad
可能在引擎盖下运行一个循环,每次调用你的函数时,它都会调用另一个函数quad
来计算 z,所有这些都会变得相当繁琐。为了测试这一点,我在原始函数中添加了一个带有计数器的简单打印语句。
count = 0
def normalized_chi_1(x,df,A):
global count
z = quad(chi2.pdf,A,B,args=(df,A))[0]
print(f"calculating z {count}th time")
count += 1
y = chi2.pdf(x,df,A) / z
return(y)
我得到的输出是
calculating z 0th time
...
calculating z 227th time
calculating z 228th time
calculating z 229th time
calculating z 230th time
因此,您正在计算 z 关于230
时间的积分,这或多或少地解释了100x
执行时间的增加。
如果你想要一个函数来计算 z 你可以简单地做
from functools import lru_cache
@lru_cache
def get_z(*ars,args):
return quad(*ars,args)[0]
A = 2
B = 4
df = 3
def normalized_chi_1(x,df,A):
z = get_z(chi2.pdf,A,B,args=(df,A))
y = chi2.pdf(x,df,A) / z
return(y)
integral_chi1 = quad(normalized_chi_1,A,B,args=(df,A))[0]
这给了我正确的结果和 0.07 秒的运行时间,但我认为在 main 中简单地定义 z 更好。
推荐阅读
- android - 出现错误:Android Studio 的序言中不允许有内容
- laravel - 502 错误网关 Docker + Laravel
- css - 为什么 Bootstrap 4 中的药丸没有样式?
- python - Django - 通过合成关系字段的多对多
- sql - 使用 T-SQL 在分层数据中查找特定父级
- ios - 无法找到由“PrivatePodAA”依赖的“PrivatePodBB”规范
- sql - 制作一个使用 sql express 发送自动电子邮件的存储过程
- linux - 在 shell 脚本中闪烁文本 (Putty;Linux)
- c++ - 如何使用 Gradle 向我的 c++ 可执行文件添加图标?
- jenkins - 在 JenkinsFile 中以 root 身份运行命令