无法重建 scipy 的样条

问题描述

我正在构建一个可以很好地插入我拥有的一些数据的脊椎,我想将其存储在数据库中。我认为这很简单,因为我可以只获取节点和系数,然后用它们创建一个新的样条。然而,这是非常错误的。这是一个最小(非)工作示例。

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

xs = np.linspace(0,2,101)
ys = xs*np.cos(2*np.pi*xs)

knotNumber = 9
knots = np.linspace(0,knotNumber)[1:-1]
spline = interpolate.LSQUnivariateSpline(xs,ys,knots,k=3)
re_spline = interpolate.BSpline(spline.get_knots(),spline.get_coeffs(),3)

sp_ys = spline(xs)
re_ys = re_spline(xs)

plt.plot(xs,'-',color='black');
plt.plot(xs,sp_ys,color='blue');
plt.plot(xs,re_ys,color='red');

结果如下图:

splines

如您所见,LSQUnivariateSpline 蓝色曲线完全覆盖了黑色。来自我创建的样条曲线的红色曲线似乎完全无关。

在这里遗漏了什么明显的东西吗?如何重建样条曲线?

解决方法

BSpline 在起点和终点(固定点)需要 k 个额外的结;不同于 (LSQ)`UnivariateSpline。

我通过查看

的结果发现了这一点
interpolate.splrep(xs,ys,k=3,task=-1,t=knots)

在输出结的开头显示 3 个额外的零,在结尾显示 3 个额外的 2:

[0. 0. 0. 0. 0.25 0.5 0.75 1. 1.25 1.5 1.75 2. 2. 2. 2. ]

(额外端点的数量显然取决于程度。)

有了这个,以下应该可以工作:

xs = np.linspace(0,2,101)
ys = xs*np.cos(2*np.pi*xs)

k = 3
knotNumber = 9
knots = np.linspace(0,knotNumber)
spline = interpolate.LSQUnivariateSpline(xs,knots[1:-1],k=k)
bknots = np.array(k * [knots[0]] + spline.get_knots().tolist() + k * [knots[-1]])
re_spline = interpolate.BSpline(bknots,spline.get_coeffs(),k)

sp_ys = spline(xs)
re_ys = re_spline(xs)

(或使用任何其他更漂亮的方式将额外的结添加到 spline.get_knots()。)