我正在尝试获得作为集成结果的expected_W或H函数:
其中:
这是我实施问题的方式。我确定我制作的包装函数很乱,所以我也乐意接受任何帮助。
from __future__ import division
from scipy import integrate
from scipy.stats import norm
import math
import numpy as np
def exp_w(w_B, sigma_eps = 1, **kwargs):
'''
Integrates the w_B function
Input:
+ w_B : the function to be integrated.
+ sigma_eps : variance of the epsilon term. Set to 1 by default
'''
#The integrand function gives everything under the integral:
# w(B(p, \theta, \epsilon, \beta)) f(\beta | \theta ) q(\epsilon)
def integrand(eps, beta, p, theta_0, theta_1, sigma_eps=sigma_eps):
q_e = norm.pdf(eps, loc=0, scale=math.sqrt(sigma_eps))
f_beta = norm.pdf(beta, loc=theta_0, scale=math.sqrt(theta_1))
return w_B(p = p,
theta_0 = theta_0, theta_1 = theta_1,
eps = eps, beta=beta)* q_e *f_beta
#limits of integration. Using limited support for now.
eps_inf = lambda beta : -10 # otherwise: -np.inf
eps_sup = lambda beta : 10 # otherwise: np.inf
beta_inf = -10
beta_sup = 10
def integrated_f(p, theta_0, theta_1):
return integrate.dblquad(integrand, beta_inf, beta_sup,
eps_inf, eps_sup,
args = (p, theta_0, theta_1))
# this integrated_f is the H referenced at the top of the question
return integrated_f
我用一个简单的w函数测试了这个函数,我知道解析解决方案(通常情况并非如此)。
def test_exp_w():
def w_B(p, theta_0, theta_1, eps, beta):
return 3*(p*eps + p*(theta_0 + theta_1) - beta)
# Function that I get
integrated = exp_w(w_B, sigma_eps = 1)
# Function that I should get
def exp_result(p, theta_0, theta_1):
return 3*p*(theta_0 + theta_1) - 3*theta_0
args = np.random.rand(3)
d_args = {'p' : args[0], 'theta_0' : args[1], 'theta_1' : args[2]}
if not (np.allclose(
integrated(**d_args)[0], exp_result(**d_args)) ):
raise Exception("Integration procedure isn't working!")
因此,我的实现似乎正在起作用,但对我的目的来说这很慢。我需要重复这个过程数十次或数十万次(这是Value函数迭代中的一个步骤。如果人们认为它是相关的,我可以提供更多信息。)
scipy
版本0.14.0和numpy
版本1.8.1,此积分需要15秒才能计算。
有人对如何解决这个问题有任何建议吗? 首先,tt可能有助于获得有限的整合领域,但我还没弄清楚如何做到这一点,或者SciPy中的高斯求积法是否以一种好的方式处理它(它是否使用Gauss-Hermite?)
感谢您的时间。
----编辑:添加分析时间-----
%lprun结果表明大部分时间花费在
_distn_infraestructure.py:1529(pdf)
和
_continuous_distns.py:97(_norm_pdf)
每个号码都有83244个号码。
答案 0 :(得分:1)
如果功能不是一个令人讨厌的功能,整合你的功能所需的时间听起来很长。
我建议你做的第一件事是分析花费时间的地方。它是在dblquad
或其他地方度过的吗?在集成期间向w_B
拨打了多少电话?如果时间花费在dblquad
并且调用次数非常高,那么您可以在集成中使用更宽松的容差吗?
似乎高斯的乘法实际上使你能够大大限制积分限制,因为高斯的大部分能量都在很小的范围内。您可能想尝试计算合理的更严格的界限。你已经把面积限制在-10..10;在-100..100,-10..10和-1..1之间是否有任何显着的性能变化?
如果您知道您的功能相对平稳,那么集成的米老鼠版本就会出现:
这是非常低技术但也非常快。它是否为您提供足够好的外部迭代结果是一个有趣的问题。它只是可能。