问题描述
我正在寻找一种非常快速的 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,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,'.',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
计算时间也减少了,但是我没有太多的可能减少输入数据中的点数。
解决方法
插值的速度几乎完全取决于近似函数的复杂性。您可以保证输入点和所需输出的哪些数学属性?您需要充分利用这些来改进您正在使用的通用方法。
最重要的是,请记住,现在几乎所有 CPU 都实现了片上超越函数:基本的触发函数、exp、sqrt、log 等。这些都是微编码以提高速度,例如 sin(x)
或 {{ 1}} 比 exp(x)
中的五次多项式更快(五次乘法,五次加法)。
您还应该探索使用矢量化操作来并行处理一组插值。
,如果您关心性能,请不要使用 interp1d。直接使用插值器:
- 对于线性插值,使用 np.interp(是的,numpy)
- 对于三次方,使用 CubicSpline 或 make_interp_spline
请注意,后面的对象允许向量化计算,因此您可以完全避免 python 循环。
另请注意,scipy 插值器具有例如.integrate 方法,因此您也可以避免使用 quad。