【问题标题】:Much faster interpolation in Python?Python中的插值要快得多?
【发布时间】:2021-08-25 21:39:42
【问题描述】:

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

计算的时间也减少了,但我没有太多可能减少输入数据中的点数。

【问题讨论】:

  • 我注意到您的时间测量包括在 print() 函数中花费的时间以及在结果中调用 quad() 所花费的时间,因此您可能无法获得插值调用的准确时间。
  • 所以您在quad 中使用插值。这将多次调用插值(至少 21 次?),每次只有一个值。您可能想探索其他积分方法,寻找一种可以让您多次调用插值但每次有很多点的方法。这可能会更快。
  • 你是真的@hpaulj。你知道如何不多次拨打H_interpolation(x)吗?当我在def function(x) 中打印时,方程的H_interpolation(x) 部分负责额外的计算,可能是不必要的。
  • 问题是 scipy.integrate.quad 调用函数数百次。最简单的解决方案是使用可以矢量化的东西。例如。 ynew = function(xnew);simps(ynew,xnew) 这要快得多,但取决于输入不太准确。另一种速度更快并给出相同结果的可能性是实现低级可调用。但这需要做更多的工作(包装/重新实现评估样条曲线的 fortran 代码并创建可以传递给 scipy.integrate.quad 的低级可调用对象。

标签: python performance scipy interpolation


【解决方案1】:

插值的速度几乎完全取决于近似函数的复杂性。您可以保证输入点和所需输出的哪些数学属性?您需要充分利用这些优势来改进您正在使用的通用方法。

最重要的是,请记住,现在几乎所有 CPU 都实现了片上超越函数:基本的三角函数、exp、sqrt、log 等。这些都是微编码的,以提高速度,例如 sin(x)exp(x)x 中的五次多项式更快(五次乘法,五次加法)。

您还应该探索使用矢量化操作来并行处理一组插值。

【讨论】:

  • interp1d 实际上有相当多的开销
  • 如何向量化我的计算?使用熊猫数据框?
  • 是的。 PANDAS 和 NumPy 都包含矢量化。
【解决方案2】:

如果您关心性能,请不要使用 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 秒。
  • 好吧,也许你发现了 interp1d 比 np.插播
猜你喜欢
  • 1970-01-01
  • 2017-09-01
  • 2022-09-30
  • 2020-12-30
  • 2016-03-21
  • 2014-03-30
  • 2013-09-01
  • 2021-02-23
  • 2016-09-12
相关资源
最近更新 更多