【发布时间】: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