Much faster interpolation in Python?

Viewed 1417

I am looking for a very fast interpolation in Python. Here is my code:

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()

Where for:

interpolate.InterpolatedUnivariateSpline

time is 0.011002779006958008 seconds and for:

interp1d type linear

time is 0.05301189422607422 seconds and for:

interp1d type cubic

time is 0.03500699996948242 seconds.

But I am looking for something really much faster due to multiple calculations in huge loops. Is there any much faster function approximation in Python? It should be accurate too.

I observed that if I reduce number of input points in

input

the time of calculation also drops, but I don't have much possibilities for reducing the number of points in input data.

2 Answers

The speed of your interpolation depends almost entirely upon the complexity of your approximation function. What mathematical properties can you guarantee about the your input points and the desired output? You need to take full advantage of those to improve over the general-purpose methods you're using.

Most important, remember that virtually all CPUs now implement on-chip transcendental functions: basic trig functions, exp, sqrt, log, etc. These are micro-coded for blinding speed, such that sin(x) or exp(x) is faster than a fifth-degree polynomial in x (five multiplications, five additions).

You should also explore using vectorized operations, to handle a set of interpolations in parallel.

Don't use interp1d if you care about performance. Use interpolators directly:

  • for linear interpolation, use np.interp (yes, numpy)
  • for cubic use either CubicSpline or make_interp_spline

Note that the latter objects allow vectorized evaluations, so you might avoid python looping altogether.

Also note that scipy interpolators have e.g. .integrate method, so you might avoid using quad, too.

Related