Python中更快的插值方法?

3
我正在寻找 Python 中非常快速的插值方法。以下是我的代码:
from scipy.integrate import quad
import numpy as np
from scipy import interpolate
import time
from scipy.interpolate import interp1d
import matplotlib.pyplot as plt

input="-0.5 0.0 \
-0.4 0.6 \
-0.3 0.9    \
-0.2 0.85 \
-0.1 0.82 \
0.0 0.8 \
0.1 0.7 \
0.2 0.6 \
0.3 0.4 \
0.4 0.3 \
0.5 0.02"

start_time = time.time()

input_coordinates = np.genfromtxt(input.splitlines()).reshape(-1,2) # shape to 2 columns, any number of rows
x_coordinates = input_coordinates[:,0]
H_values = input_coordinates[:,1]
H_interpolation = interpolate.InterpolatedUnivariateSpline(x_coordinates, H_values)
# H_interpolation = interp1d(x_coordinates, H_values)
# H_interpolation = interp1d(x_coordinates, H_values, kind='cubic')

def function(x):
    return H_interpolation(x)*np.exp(2/np.sqrt(1+x))

complex_integral = quad(function, -0.5, 0.5)

print("Quad",complex_integral)

print("--- %s seconds ---" % (time.time() - start_time))

xnew = np.arange(-0.5, 0.5, 0.01)
ynew = H_interpolation(xnew)   # use interpolation function returned by `interp1d`
plt.plot(x_coordinates, H_values, '.', label='original data')
plt.plot(xnew, ynew, '-', label='interpolation')
plt.legend()
plt.show()

用途:

interpolate.InterpolatedUnivariateSpline

时间为0.011002779006958008秒 而对于:

interp1d type linear

时间为0.05301189422607422秒 并且针对:

interp1d type cubic

时间为0.03500699996948242秒。

但我正在寻找一些更快的东西,因为在大循环中有多个计算。在Python中是否有任何更快的函数近似?它还应该是准确的。

我观察到,如果我减少输入点的数量

input

计算时间也会减少,但是我没有太多降低输入数据点数的可能性。

2
我注意到你的时间测量包括在print()函数中花费的时间以及调用quad()函数处理结果所花费的时间,因此你可能无法准确地计算插值调用的时间。 - undefined
所以你正在使用quad内的插值。这将会多次调用插值函数(至少21次?),每次只传入一个值。你可能想尝试其他积分方法,寻找一种能够让你少次调用插值函数,但每次传入多个点的方法。这样可能会更快。 - undefined
你是对的 @hpaulj。你有没有办法不要多次调用H_interpolation(x)?当我在def function(x)中打印时,方程式中的H_interpolation(x)部分会导致额外的计算,可能是不必要的。 - undefined
问题在于scipy.integrate.quad会多次调用函数。最简单的解决方案是使用可以向量化的方法。例如,ynew = function(xnew);simps(ynew,xnew) 这样做速度更快,但根据输入可能不够准确。另一种可能性是实现一个低级可调用函数,这样做速度也更快,并且得到相同的结果。但这需要更多的工作(包装/重新实现评估样条的Fortran代码,并创建一个低级可调用函数,然后将其传递给scipy.integrate.quad)。 - undefined
2个回答

0

你的插值速度几乎完全取决于你的逼近函数的复杂性。你能保证哪些数学属性关于你的输入点和期望输出?你需要充分利用它们来改进你正在使用的通用方法。

最重要的是,记住现在几乎所有的CPU都实现了芯片上的超越函数:基本三角函数、指数函数、平方根、对数等。这些都是微码编码的,速度极快,例如sin(x)exp(x)x的五次多项式(五个乘法,五个加法)更快。

你还应该探索使用向量化操作,以并行处理一组插值。


interp1d实际上有相当大的开销。 - undefined
如何将我的计算向量化?使用Pandas数据框架可以吗? - undefined
是的。PANDAS和NumPy都采用了向量化技术。 - undefined

0

如果您关心性能,请勿使用interp1d。直接使用插值器:

  • 对于线性插值,请使用np.interp(是的,numpy)
  • 对于三次插值,请使用CubicSpline或make_interp_spline

请注意,后者允许矢量化评估,因此您可能完全避免使用Python循环。

还要注意,scipy插值器具有例如.integrate方法,因此您也可以避免使用quad。


如何在def function(x):之外使用np.interp进行插值?我想避免多次计算插值。使用以下代码:def function(x): res=np.interp(x, x_coordinates, H_values) return np.exp(1j*2/np.sqrt(1+x))*res计时为0.314秒。而使用以下代码:def function(x): res=H_interpolation(x) return np.exp(1j*2/np.sqrt(1+x))*res计时为0.15秒。 - undefined
好的,也许你找到了一个情况,其中interp1d比np.interp更快。 - undefined

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接