Python interp1d против UnivariateSpline

Я пытаюсь передать некоторый код MatLab на Scipy, и я пробовал две разные функции из scipy.interpolate, interp1d и UnivariateSpline. Результаты interp1d соответствуют функции interpld MatLab, но числа UnivariateSpline отличаются друг от друга - и в некоторых случаях очень разные.

f = interp1d(row1,row2,kind='cubic',bounds_error=False,fill_value=numpy.max(row2))
return  f(interp)

f = UnivariateSpline(row1,row2,k=3,s=0)
return f(interp)

Может ли кто-нибудь предложить какое-либо понимание? Мои x vals не одинаково распределены, хотя я не уверен, почему это имеет значение.

Ответ 1

Я просто столкнулся с той же проблемой.

Короткий ответ

Используйте InterpolatedUnivariateSpline вместо:

f = InterpolatedUnivariateSpline(row1, row2)
return f(interp)

Длинный ответ

UnivariateSpline - это сглаживающий сглаживание one-, соответствующий данному набору точек данных, тогда как InterpolatedUnivariateSpline является "one- мерным интерполяционным сплайном для заданного набора точек данных". Первый разглаживает данные, тогда как последний является более обычным методом интерполяции и воспроизводит ожидаемые результаты от interp1d. На рисунке ниже показана разница.

Comparison of interpolation functions

Код для воспроизведения рисунка показан ниже.

import scipy.interpolate as ip

#Define independent variable
sparse = linspace(0, 2 * pi, num = 20)
dense = linspace(0, 2 * pi, num = 200)

#Define function and calculate dependent variable
f = lambda x: sin(x) + 2
fsparse = f(sparse)
fdense = f(dense)

ax = subplot(2, 1, 1)

#Plot the sparse samples and the true function
plot(sparse, fsparse, label = 'Sparse samples', linestyle = 'None', marker = 'o')
plot(dense, fdense, label = 'True function')

#Plot the different interpolation results
interpolate = ip.InterpolatedUnivariateSpline(sparse, fsparse)
plot(dense, interpolate(dense), label = 'InterpolatedUnivariateSpline', linewidth = 2)

smoothing = ip.UnivariateSpline(sparse, fsparse)
plot(dense, smoothing(dense), label = 'UnivariateSpline', color = 'k', linewidth = 2)

ip1d = ip.interp1d(sparse, fsparse, kind = 'cubic')
plot(dense, ip1d(dense), label = 'interp1d')

ylim(.9, 3.3)

legend(loc = 'upper right', frameon = False)

ylabel('f(x)')

#Plot the fractional error
subplot(2, 1, 2, sharex = ax)

plot(dense, smoothing(dense) / fdense - 1, label = 'UnivariateSpline')
plot(dense, interpolate(dense) / fdense - 1, label = 'InterpolatedUnivariateSpline')
plot(dense, ip1d(dense) / fdense - 1, label = 'interp1d')

ylabel('Fractional error')
xlabel('x')
ylim(-.1,.15)

legend(loc = 'upper left', frameon = False)

tight_layout()

Ответ 2

Причина, по которой результаты различны (но, вероятно, и правильные), заключается в том, что подпрограммы интерполяции, используемые UnivariateSpline и interp1d, различны.

  • interp1d строит гладкий сплайн B-, используя x -points, который вы указали ему как узлы

  • UnivariateSpline основан на FITPACK, который также создает гладкий сплайн B-. Тем не менее, FITPACK пытается выбрать новые узлы для сплайна, чтобы лучше соответствовать данным (возможно, чтобы минимизировать chi ^ 2 плюс штраф за кривизну или что-то подобное). Вы можете узнать, какие узлы он использует с помощью g.get_knots().

Поэтому причина, по которой вы получаете разные результаты, заключается в том, что алгоритм интерполяции отличается. Если вы хотите, чтобы B- сплайны с узлами в точках данных, используйте interp1d или splmake. Если вы хотите, что делает FITPACK, используйте UnivariateSpline. В пределе плотных данных оба метода дают одинаковые результаты, но когда данные разрежены, вы можете получить разные результаты.

(Как узнать все это: прочитал код: -)

Ответ 3

Работает для меня,

from scipy import allclose, linspace
from scipy.interpolate import interp1d, UnivariateSpline

from numpy.random import normal

from pylab import plot, show

n = 2**5

x = linspace(0,3,n)
y = (2*x**2 + 3*x + 1) + normal(0.0,2.0,n)

i = interp1d(x,y,kind=3)
u = UnivariateSpline(x,y,k=3,s=0)

m = 2**4

t = linspace(1,2,m)

plot(x,y,'r,')
plot(t,i(t),'b')
plot(t,u(t),'g')

print allclose(i(t),u(t)) # evaluates to True

show()

Это дает мне,

enter image description here

Ответ 4

UnivariateSpline: более поздняяобертка подпрограмм FITPACK.

это может объяснить несколько разные значения? (Я также испытал, что UnivariateSpline намного быстрее, чем interp1d.)