Python interp1d 与 UnivariateSpline

发布于 2024-11-11 14:15:42 字数 712 浏览 8 评论 0原文

我正在尝试将一些 MatLab 代码移植到 Scipy,并且我尝试了 scipy.interpolate 中的两个不同的函数,interp1dUnivariateSpline。 interp1d 结果与 interp1d 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 值间隔不均匀,尽管我不确定为什么这很重要。

I'm trying to port some MatLab code over to Scipy, and I've tried two different functions from scipy.interpolate, interp1d and UnivariateSpline. The interp1d results match the interp1d MatLab function, but the UnivariateSpline numbers come out different - and in some cases very different.

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)

Could anyone offer any insight? My x vals aren't equally spaced, although I'm not sure why that would matter.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

伤痕我心 2024-11-18 14:15:42

我刚刚遇到了同样的问题。

简短回答

使用 InterpolatedUnivariateSpline< /a> 相反:

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

长答案

UnivariateSpline 是“适合给定数据点集的一维平滑样条曲线”,而 InterpolatedUnivariateSpline 是“给定数据点集的一维插值样条”。前者平滑数据,而后者是更传统的插值方法,并重现 interp1d。下图说明了其中的差异。

插值函数比较

重现该图的代码如下所示。

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

I just ran into the same issue.

Short answer

Use InterpolatedUnivariateSpline instead:

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

Long answer

UnivariateSpline is a 'one-dimensional smoothing spline fit to a given set of data points' whereas InterpolatedUnivariateSpline is a 'one-dimensional interpolating spline for a given set of data points'. The former smoothes the data whereas the latter is a more conventional interpolation method and reproduces the results expected from interp1d. The figure below illustrates the difference.

Comparison of interpolation functions

The code to reproduce the figure is shown below.

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()
红颜悴 2024-11-18 14:15:42

结果不同(但可能都是正确的)的原因是 UnivariateSplineinterp1d 使用的插值例程不同。

  • interp1d 使用您提供给它的 x 点作为结构建平滑的 B 样条

  • UnivariateSpline 基于 FITPACK,它也构造了平滑的 B 样条线。然而,FITPACK 尝试为样条线选择结,以更好地拟合数据(可能是为了最小化 chi^2 加上一些曲率惩罚或类似的东西)。您可以通过g.get_knots()找出它使用了哪些节点。

所以得到不同结果的原因是插值算法不同。如果您想要在数据点处带有结的 B 样条线,请使用 interp1dsplmake。如果您想要 FITPACK 的功能,请使用 UnivariateSpline。在数据密集的情况下,两种方法都会给出相同的结果,但是当数据稀疏时,可能会得到不同的结果。

(我怎么知道这一切:我读过代码:-)

The reason why the results are different (but both likely correct) is that the interpolation routines used by UnivariateSpline and interp1d are different.

  • interp1d constructs a smooth B-spline using the x-points you gave to it as knots

  • UnivariateSpline is based on FITPACK, which also constructs a smooth B-spline. However, FITPACK tries to choose new knots for the spline, to fit the data better (probably to minimize chi^2 plus some penalty for curvature, or something similar). You can find out what knot points it used via g.get_knots().

So the reason why you get different results is that the interpolation algorithm is different. If you want B-splines with knots at data points, use interp1d or splmake. If you want what FITPACK does, use UnivariateSpline. In the limit of dense data, both methods give same results, but when data is sparse, you may get different results.

(How do I know all this: I read the code :-)

弱骨蛰伏 2024-11-18 14:15:42

对我有用,

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

这给了我,

在此处输入图像描述

Works for me,

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

This gives me,

enter image description here

筱武穆 2024-11-18 14:15:42

UnivariateSpline:更新
FITPACK 例程的包装器。

这可以解释略有不同的值吗? (我还体验到 UnivariateSpline 比 interp1d 快得多。)

UnivariateSpline: A more recent
wrapper of the FITPACK routines.

this might explain the slightly different values? (I also experienced that UnivariateSpline is much faster than interp1d.)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文