Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/306.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 计算二维插值积分时出错。比较numpy阵列_Python_Numpy_Scipy_Integration_Interpolation - Fatal编程技术网

Python 计算二维插值积分时出错。比较numpy阵列

Python 计算二维插值积分时出错。比较numpy阵列,python,numpy,scipy,integration,interpolation,Python,Numpy,Scipy,Integration,Interpolation,我的优化任务是计算以下积分,并找到xl和xu的最佳值: 迭代时间太长,所以我决定通过计算所有可能值xl和xu的积分来加速迭代,然后在优化过程中插值计算值 我编写了以下函数: def k_integrand(x, xl, xu): return((x**2)*mpmath.exp(x))/((xu - xl)*(mpmath.exp(x)-1)**2) @np.vectorize def K(xl, xu): y, err = integrate.quad(k_integr

我的优化任务是计算以下积分,并找到
xl
xu
的最佳值:

迭代时间太长,所以我决定通过计算所有可能值
xl
xu
的积分来加速迭代,然后在优化过程中插值计算值

我编写了以下函数:

def k_integrand(x, xl, xu):
    return((x**2)*mpmath.exp(x))/((xu - xl)*(mpmath.exp(x)-1)**2)
@np.vectorize   
def K(xl, xu):
    y, err = integrate.quad(k_integrand, xl, xu, args = (xl, xu))
    return y
以及两个相同的数组
grid_xl
grid_xu
,它们的值以dinamic增量递增

当我运行代码时,我得到以下信息:

K(grid_xl, grid_xu)
Traceback (most recent call last):

  File "<ipython-input-2-5b9df02f12b7>", line 1, in <module>
    K(grid_xl, grid_xu)

  File "C:/Users/909404/OneDrive/Работа/ZnS-FeS/Теплоемкость/Python/CD357/4 - Optimization CD357 interpolation.py", line 75, in K
    y, err = integrate.quad(k_integrand, xl, xu, args = (xl, xu))

  File "C:\Users\909404\Anaconda3\lib\site-packages\scipy\integrate\quadpack.py", line 323, in quad
    points)

  File "C:\Users\909404\Anaconda3\lib\site-packages\scipy\integrate\quadpack.py", line 372, in _quad
    if (b != Inf and a != -Inf):

ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()
K(grid\u xl,grid\u xu)
回溯(最近一次呼叫最后一次):
文件“”,第1行,在
K(网格xl,网格xu)
文件“C:/Users/909404/OneDrive/Паааааааа/ZnS-FeS/Пааааааааа1072
y、 err=integrate.quad(k_被积函数,xl,xu,args=(xl,xu))
文件“C:\Users\909404\Anaconda3\lib\site packages\scipy\integrate\quadpack.py”,第323行,四行
积分)
文件“C:\Users\909404\Anaconda3\lib\site packages\scipy\integrate\quadpack.py”,第372行,在_quad中
如果(b!=Inf和a!=Inf):
ValueError:包含多个元素的数组的真值不明确。使用a.any()或a.all()
我猜这是因为
xl
应该总是小于
xu
。 如果
xl>=xu
,有没有办法比较
xl
xu
的值并返回NaN

最后,我想要这样的东西:

并且能够使用插值


也许我选错了路?非常感谢您的帮助。

除非省略
np.vectorize
decorator,否则我无法重现您的错误。但是,如果将
xl
/
xu
值设置为一致,则会产生
零分错误

无论如何,没有什么可以阻止您在更高级别的函数中检查
xu
vs
xl
的值。这样,您就可以完全跳过无意义数据点的集成,并尽早返回
np.nan

import numpy as np
import mpmath
import scipy.integrate as integrate

def k_integrand(x, xl, xu):    
    return ((x**2)*mpmath.exp(x))/((xu - xl)*(mpmath.exp(x)-1)**2)

@np.vectorize   
def K(xl, xu):
    if xu <= xl:
        # don't even try to integrate
        return np.nan
    y, err = integrate.quad(k_integrand, xl, xu, args = (xl, xu))
    return y

grid_xl = np.linspace(0.1,1,10)        # shape (10,) ~ (1,10)
grid_xu = np.linspace(0.5,4,8)[:,None] # shape (8,1)
您可以看到这些值与链接图像完全一致

现在,我有坏消息和好消息。坏消息是,虽然
np.vectorize
为使用数组输入调用标量积分函数提供了语法上的甜头,但与本机for循环相比,它实际上不会给您带来速度提升。好消息是,您可以将对
mpmath.exp
的调用替换为对
np.exp
的调用,从而更快地得到相同的结果:

def k_integrand_np(x, xl, xu):    
    return ((x**2)*np.exp(x))/((xu - xl)*(np.exp(x)-1)**2)

@np.vectorize   
def K_np(xl, xu):
    if xu <= xl:
        # don't even try to integrate
        return np.nan
    y, err = integrate.quad(k_integrand_np, xl, xu, args = (xl, xu))
    return y
因此,这两种方法给出了相同的结果(确切地说!),但numpy版本的速度几乎快了15倍。

使用低级回调函数进行集成 下面的答案是对@Andras Deak answer的一个评论,但它渴望得到一个评论

scipy积分函数多次调用k_被积函数(np函数),速度相当慢。使用纯Python函数的替代方法是使用。这个函数可以直接用C语言编写,也可以使用像Numba这样的编译器用Python编写。以下是对此的稍微修改版本

示例

import time
import numpy as np
import numba
import scipy.integrate as integrate
from scipy import LowLevelCallable
from numba import cfunc
from numba.types import intc, CPointer, float64


##wrapper for a function that takes 3 input values
def jit_integrand_function(integrand_function):
    jitted_function = numba.njit(integrand_function)
    
    @cfunc(float64(intc, CPointer(float64)))
    def wrapped(n, xx):
        return jitted_function(xx[0], xx[1],xx[2])
    return LowLevelCallable(wrapped.ctypes)

#your function to integrate
def k_integrand_np(x, xl, xu):
  return ((x**2)*np.exp(x))/((xu - xl)*(np.exp(x)-1)**2)

#compile integrand
k_integrand_nb=jit_integrand_function(k_integrand_np)

#now we can use the low-level callable
@np.vectorize
def K_nb(xl, xu):
    if xu <= xl:
        # don't even try to integrate
        return np.nan
    y, err = integrate.quad(k_integrand_nb, xl, xu, args = (xl, xu))
    return y

#for comparison
@np.vectorize
def K_np(xl, xu):
    if xu <= xl:
        # don't even try to integrate
        return np.nan
    y, err = integrate.quad(k_integrand_np, xl, xu, args = (xl, xu))
    return y
#create some data
grid_xl = np.linspace(0.1,1,500)      
grid_xu = np.linspace(0.5,4,800)[:,None] 

t1=time.time()
res_nb = K_nb(grid_xl, grid_xu)
print(time.time()-t1)
t1=time.time()
res_np = K_np(grid_xl, grid_xu)
print(time.time()-t1)

inds = ~np.isnan(res_nb)
np.allclose(res_nb[inds], res_np[inds])

K_np: 24.58s
K_nb: 0.97s (25x speedup)
allclose: True

在您的案例中,
a
b
是什么?提供完整的错误回溯会很有帮助。我已经添加了完整的错误回溯,希望它能有所帮助。
(b!=Inf和a!=-Inf)
不可能在
b
a
为多值数组的情况下进行计算。记下源代码,从第372行开始;根据边界
a
b
是否有限,代码决定使用不同的积分方法。通常,除非显示
\u quadpack
例程接受向量参数,否则您的方法将不起作用。第
75
77
行上的参数说明特别指出
a
b
需要是
float
s。干得好。我想知道;数组不是完全相等吗?我怀疑这很容易做到,因为numba编译不一定会影响操作顺序,所以两种方法之间的浮点错误可能是相同的。我还想知道这种加速是否足以直接解决OP最初的问题。不,它们并不完全相同。我真的不知道为什么会发生这种情况,但我怀疑Numba将x**2(或np.power(x,2))简化为x*x,这在精度上可能不同,但速度要快得多。关于SIMD的矢量化运算精度可能也会有所不同谢谢,真的很有帮助!通过使用np.sinh()函数重写初始被积函数,并像您建议的那样在K_np中添加“if”语句,我已经设法加快了计算速度。
import time
import numpy as np
import numba
import scipy.integrate as integrate
from scipy import LowLevelCallable
from numba import cfunc
from numba.types import intc, CPointer, float64


##wrapper for a function that takes 3 input values
def jit_integrand_function(integrand_function):
    jitted_function = numba.njit(integrand_function)
    
    @cfunc(float64(intc, CPointer(float64)))
    def wrapped(n, xx):
        return jitted_function(xx[0], xx[1],xx[2])
    return LowLevelCallable(wrapped.ctypes)

#your function to integrate
def k_integrand_np(x, xl, xu):
  return ((x**2)*np.exp(x))/((xu - xl)*(np.exp(x)-1)**2)

#compile integrand
k_integrand_nb=jit_integrand_function(k_integrand_np)

#now we can use the low-level callable
@np.vectorize
def K_nb(xl, xu):
    if xu <= xl:
        # don't even try to integrate
        return np.nan
    y, err = integrate.quad(k_integrand_nb, xl, xu, args = (xl, xu))
    return y

#for comparison
@np.vectorize
def K_np(xl, xu):
    if xu <= xl:
        # don't even try to integrate
        return np.nan
    y, err = integrate.quad(k_integrand_np, xl, xu, args = (xl, xu))
    return y
#create some data
grid_xl = np.linspace(0.1,1,500)      
grid_xu = np.linspace(0.5,4,800)[:,None] 

t1=time.time()
res_nb = K_nb(grid_xl, grid_xu)
print(time.time()-t1)
t1=time.time()
res_np = K_np(grid_xl, grid_xu)
print(time.time()-t1)

inds = ~np.isnan(res_nb)
np.allclose(res_nb[inds], res_np[inds])

K_np: 24.58s
K_nb: 0.97s (25x speedup)
allclose: True