如何使用数组输入调用 python scipyquad

问题描述 投票:0回答:4
我正在使用嵌套的 scipy.integrate.quad 调用来积分二维被积函数。被积函数由 numpy 函数组成 - 因此向其传递一组输入比循环输入并为每个输入调用一次要高效得多 - 由于 numpy 的数组,速度快了约 2 个数量级。

但是......如果我只想在一个维度上积分我的被积函数 - 但在其他维度上输入一组输入,事情就会失败 - 似乎“scipy”quadpack 包无法执行任何操作numpy 用来处理数组输入。有没有其他人看到过这个 - 或者找到了解决它的方法 - 或者我误解了它。我从四边形得到的错误是:

Traceback (most recent call last): File "C:\Users\JP\Documents\Python\TestingQuad\TestingQuad_v2.py", line 159, in <module> fnIntegrate_x(0, 1, NCALLS_SET, True) File "C:\Users\JP\Documents\Python\TestingQuad\TestingQuad_v2.py", line 35, in fnIntegrate_x I = Integrate_x(yarray) File "C:\Users\JP\Documents\Python\TestingQuad\TestingQuad_v2.py", line 23, in Integrate_x return quad(Integrand, 0, np.pi/2, args=(y))[0] File "C:\Python27\lib\site-packages\scipy\integrate\quadpack.py", line 247, in quad retval = _quad(func,a,b,args,full_output,epsabs,epsrel,limit,points) File "C:\Python27\lib\site-packages\scipy\integrate\quadpack.py", line 312, in _quad return _quadpack._qagse(func,a,b,args,full_output,epsabs,epsrel,limit) quadpack.error: Supplied function does not return a valid float.

我在下面放了一个我想要做的事情的卡通版本 - 我实际上正在做的事情有一个更复杂的被积函数,但这就是 gyst。

重点在顶部 - 底部正在做基准测试来表明我的观点。

import numpy as np import time from scipy.integrate import quad def Integrand(x, y): ''' Integrand ''' return np.sin(x)*np.sin( y ) def Integrate_x(y): ''' Integrate over x given (y) ''' return quad(Integrand, 0, np.pi/2, args=(y))[0] def fnIntegrate_x(ystart, yend, nsteps, ArrayInput = False): ''' ''' yarray = np.arange(ystart,yend, (yend - ystart)/float(nsteps)) I = np.zeros(nsteps) if ArrayInput : I = Integrate_x(yarray) else : for i,y in enumerate(yarray) : I[i] = Integrate_x(y) return y, I NCALLS_SET = 1000 NSETS = 10 SETS_t = np.zeros(NSETS) for i in np.arange(NSETS) : XInputs = np.random.rand(NCALLS_SET, 2) t0 = time.time() for x in XInputs : Integrand(x[0], x[1]) t1 = time.time() SETS_t[i] = (t1 - t0)/NCALLS_SET print "Benchmarking Integrand - Single Values:" print "NCALLS_SET: ", NCALLS_SET print "NSETS: ", NSETS print "TimePerCall(s): ", np.mean(SETS_t) , np.std(SETS_t)/ np.sqrt(SETS_t.size) print "TotalTime: ",np.sum(SETS_t) * NCALLS_SET ''' Benchmarking Integrand - Single Values: NCALLS_SET: 1000 NSETS: 10 TimePerCall(s): 1.23999834061e-05 4.06987868647e-06 ''' NCALLS_SET = 1000 NSETS = 10 SETS_t = np.zeros(NSETS) for i in np.arange(NSETS) : XInputs = np.random.rand(NCALLS_SET, 2) t0 = time.time() Integrand(XInputs[:,0], XInputs[:,1]) t1 = time.time() SETS_t[i] = (t1 - t0)/NCALLS_SET print "Benchmarking Integrand - Array Values:" print "NCALLS_SET: ", NCALLS_SET print "NSETS: ", NSETS print "TimePerCall(s): ", np.mean(SETS_t) , np.std(SETS_t)/ np.sqrt(SETS_t.size) print "TotalTime: ",np.sum(SETS_t) * NCALLS_SET ''' Benchmarking Integrand - Array Values: NCALLS_SET: 1000 NSETS: 10 TimePerCall(s): 2.00009346008e-07 1.26497018465e-07 ''' NCALLS_SET = 1000 NSETS = 100 SETS_t = np.zeros(NSETS) for i in np.arange(NSETS) : t0 = time.time() fnIntegrate_x(0, 1, NCALLS_SET, False) t1 = time.time() SETS_t[i] = (t1 - t0)/NCALLS_SET print "Benchmarking fnIntegrate_x - Single Values:" print "NCALLS_SET: ", NCALLS_SET print "NSETS: ", NSETS print "TimePerCall(s): ", np.mean(SETS_t) , np.std(SETS_t)/ np.sqrt(SETS_t.size) print "TotalTime: ",np.sum(SETS_t) * NCALLS_SET ''' NCALLS_SET: 1000 NSETS: 100 TimePerCall(s): 0.000165750000477 8.61204306241e-07 TotalTime: 16.5750000477 ''' NCALLS_SET = 1000 NSETS = 100 SETS_t = np.zeros(NSETS) for i in np.arange(NSETS) : t0 = time.time() fnIntegrate_x(0, 1, NCALLS_SET, True) t1 = time.time() SETS_t[i] = (t1 - t0)/NCALLS_SET print "Benchmarking fnIntegrate_x - Array Values:" print "NCALLS_SET: ", NCALLS_SET print "NSETS: ", NSETS print "TimePerCall(s): ", np.mean(SETS_t) , np.std(SETS_t)/ np.sqrt(SETS_t.size) ''' **** Doesn't work!!!! ***** Traceback (most recent call last): File "C:\Users\JP\Documents\Python\TestingQuad\TestingQuad_v2.py", line 159, in <module> fnIntegrate_x(0, 1, NCALLS_SET, True) File "C:\Users\JP\Documents\Python\TestingQuad\TestingQuad_v2.py", line 35, in fnIntegrate_x I = Integrate_x(yarray) File "C:\Users\JP\Documents\Python\TestingQuad\TestingQuad_v2.py", line 23, in Integrate_x return quad(Integrand, 0, np.pi/2, args=(y))[0] File "C:\Python27\lib\site-packages\scipy\integrate\quadpack.py", line 247, in quad retval = _quad(func,a,b,args,full_output,epsabs,epsrel,limit,points) File "C:\Python27\lib\site-packages\scipy\integrate\quadpack.py", line 312, in _quad return _quadpack._qagse(func,a,b,args,full_output,epsabs,epsrel,limit) quadpack.error: Supplied function does not return a valid float. '''
    
python numpy scipy numerical-integration quad
4个回答
2
投票
可以通过 numpy.vectorize 函数实现。我遇到这个问题很长时间了,然后想到了这个向量化函数。

你可以这样使用它:

vectorized_function = numpy.vectorize(your_function) output = vectorized_function(your_array_input)
    

2
投票
恐怕我在这里用否定的方式回答我自己的问题。我认为这是不可能的。似乎 Quad 是用其他东西编写的库的某种端口 - 因此它是内部的库定义了事情的完成方式 - 所以如果不重新设计库本身,可能无法做我想做的事。

对于其他在多个 D 集成上遇到计时问题的人,我发现最好的方法是使用专用的集成库。我发现“古巴”似乎有一些非常有效的多维集成例程。

http://www.feynarts.de/cuba/

这些例程是用 c 语言编写的,所以我最终使用 SWIG 与它们交谈 - 最终也是为了提高效率,用 c 语言重写了我的被积函数 - 这加快了加载速度......



0
投票
我在所有维度上从 -np.inf 到 np.inf 的概率密度函数积分时遇到了这个问题。

我通过创建一个接受 *args 的包装函数、将 args 转换为 numpy 数组并集成包装函数来修复它。

我认为使用 numpy 的向量化仅整合所有值都相等的子空间。

这是一个例子:

from scipy.integrate import nquad from scipy.stats import multivariate_normal mean = [0., 0.] cov = np.array([[1., 0.], [0., 1.]]) bivariate_normal = multivariate_normal(mean=mean, cov=cov) def pdf(*args): x = np.array(args) return bivariate_normal.pdf(x) integration_range = [[-18, 18], [-18, 18]] nquad(pdf, integration_range) Output: (1.000000000000001, 1.3429066352690133e-08)
    
© www.soinside.com 2019 - 2024. All rights reserved.