在 Python 中更快的插值?

问题描述

我正在寻找一种非常快速的 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。