不同的python函数适合三次样条,找到系数

时间:2017-05-05 16:19:04

标签: scipy spline smoothing cubic-spline

我想在Python中使用三维样条拟合噪声x,y数据并提取每个区间的样条系数(即我希望每个区间获得四个样条系数)

到目前为止,我已尝试过(全部来自scipy.interpolate):

1)CubicSpline,但这种方法不允许我平滑样条曲线,导致不切实际的跳跃系数数据。

2)组合splrep和splev,例如

tck = splrep(x, y, k=3, s=1e25)

我使用

提取系数/节点
F = PPoly.from_spline(tck)
coeffs = F.c
knots = F.x

然而,我无法在整个x范围内找到平滑系数(在接近零和1e23的值之间跳转,这是非物理的),即使我将平滑参数s增加到非常大的数字,最终会导致数字太小结节数随着节数的减少而减少。似乎我无法同时找到合适的参数s和结数。

3)我用过     单变量样条(x,y,k = 3,s = 0.03) 在这里,我发现更改s的灵敏度更高,但相应的get_coeffs()方法不为每个区间提供4个系数,但只提供一个,我不明白。

4)我还尝试了使用三阶多项式的分段脊状线性回归,但是这种方法为拟合提供了太大的百分比误差,因此使其中一种标准样条方法起作用会很棒。

我错过了什么?有人可以帮忙吗?

1 个答案:

答案 0 :(得分:2)

我在这里看到的具体问题是UnivariateSpline不会在插值样条中产生x的各种幂的代数系数。这是因为它保留在私有_data属性中的系数(也是get_coeffs方法返回的属性)是B-spline coefficients的一种。这些系数描述了没有任何冗余的样条曲线(对于具有N个自由度的样条曲线,你需要它们的N个),但是它们附加到的样条的基础样条有些复杂。

但是,您可以使用样条线对象的derivatives方法获得所需的系数。它返回给定点x处的所有四个导数,从中可以很容易地找到Taylor coefficients。使用这种方法很自然,x是插值的结,排除最右边的结;获得的系数从该结到下一个结是有效的。这是一个例子,完整的"花式"格式化输出。

import numpy as np
from scipy.interpolate import UnivariateSpline
spl = UnivariateSpline(np.arange(6), np.array([3, 1, 4, 1, 5, 9]), s=0)
kn = spl.get_knots()
for i in range(len(kn)-1):
    cf = [1, 1, 1/2, 1/6] * spl.derivatives(kn[i])
    print("For {0} <= x <= {1}, p(x) = {5}*(x-{0})^3 + {4}*(x-{0})^2 + {3}*(x-{0}) + {2}".format(kn[i], kn[i+1], *cf))

在这个例子中,结是0,2,3,5。输出是:

For 0.0 <= x <= 2.0, p(x) = -3.1222222222222222*(x-0.0)^3 + 11.866666666666667*(x-0.0)^2 + -10.744444444444445*(x-0.0) + 3.000000000000001
For 2.0 <= x <= 3.0, p(x) = 4.611111111111111*(x-2.0)^3 + -6.866666666666667*(x-2.0)^2 + -0.7444444444444436*(x-2.0) + 4.000000000000001
For 3.0 <= x <= 5.0, p(x) = -2.322222222222221*(x-3.0)^3 + 6.966666666666665*(x-3.0)^2 + -0.6444444444444457*(x-3.0) + 1.0000000000000016

请注意,对于每个片段,cf保持从最低度开始的系数,因此在格式化字符串时顺序相反。

(当然,你可能想用这些系数做其他事情)

要检查公式是否正确,我将其复制粘贴以进行绘图:

spline