более быстрый способ выполнить интерполяцию сплайнов в python

#python #sympy

#python #sympy

Вопрос:

Я пытаюсь интерполировать 30 точек с помощью сплайна 3 степени следующим образом:

 from sympy import interpolating_spline
domain_points = [0.01, 0.01888888888888889, 0.027777777777777776, 0.03666666666666667, 0.04555555555555556, 0.05444444444444445, 0.06333333333333332, 0.07222222222222222, 0.0811111111111111, 0.09, 0.09888888888888889, 0.10777777777777778, 0.11666666666666665, 0.12555555555555556, 0.13444444444444445, 0.14333333333333334, 0.15222222222222223, 0.16111111111111112, 0.17, 0.30833333333333335, 0.44666666666666666, 0.5850000000000001, 0.7233333333333334, 0.8616666666666667, 1.0, 2.5, 4.0, 5.5, 7.0, 8.5]
range_points = list(map(lambda x: x-1/x, domain_points))

interpolating_spline(3, x, domain_points, range_points)
  

На моей машине это занимает примерно ~ 1 минуту 42 секунды. Я делаю что-то не так, что делает это так медленно? Есть ли способ ускорить это или альтернативная библиотека для интерполяции сплайнов, которая быстрее, чтобы я мог интерполировать намного больше точек?

Ответ №1:

Если вам нужна просто числовая интерполяция, используйте scipy

https://docs.scipy.org/doc/scipy/reference/tutorial/interpolate.html#spline-interpolation

Sympy предназначен для алгебраических манипуляций.

Ответ №2:

Используйте scipy.interpolate.splrep(). По умолчанию используется k=3 , но поддерживается до k=5 .

РЕДАКТИРОВАТЬ в ответ на комментарий ниже вы также можете использовать interpolate .InterpolatedUnivariateSpline(), который фактически дает вам тот же результат. Код и график обновлены, чтобы показать это..

 import numpy as np
import matplotlib.pyplot as plt
from scipy import interpolate

domain_points = [0.01, 0.01888888888888889, 0.027777777777777776, 0.03666666666666667, 0.04555555555555556, 0.05444444444444445, 0.06333333333333332, 0.07222222222222222, 0.0811111111111111, 0.09, 0.09888888888888889, 0.10777777777777778, 0.11666666666666665, 0.12555555555555556, 0.13444444444444445, 0.14333333333333334, 0.15222222222222223, 0.16111111111111112, 0.17, 0.30833333333333335, 0.44666666666666666, 0.5850000000000001, 0.7233333333333334, 0.8616666666666667, 1.0, 2.5, 4.0, 5.5, 7.0, 8.5]
range_points  = list(map(lambda x: x-1/x, domain_points))

# using splrep
tck           = interpolate.splrep(domain_points, range_points, s=0)
splrep_points = interpolate.splev(domain_points, tck)

tock = interpolate.InterpolatedUnivariateSpline(domain_points, range_points)
xs   = np.linspace(np.min(domain_points), np.max(domain_points), 1000)

plt.figure()
plt.plot(domain_points, range_points, 'x', domain_points, splrep_points, 'b', xs, tock(xs), 'r')
plt.legend(['Data', 'splrep', 'InterpolatedUnivariateSpline'])
plt.show()
  

Что дает…

введите описание изображения здесь

Комментарии:

1. Это странно. После первого ответа, который я использовал scipy.interpolate.UnivariateSpline . Есть ли преимущество для использования splrep в этом случае?

2. @user2640045 Я отредактировал свой ответ, поскольку подумал, что происходит что-то подозрительное, поскольку две функции действительно должны давать одинаковый результат, поскольку они оба являются оболочками для одной и той же реализации FITPACK. Исправлено использование splrep в ответе.