我不明白interpolate.splrep函数是如何工作的。简单代码不会抛出任何错误,但会返回意外结果。

degree = 4;
arg = np.linspace(0, 2.0 * np.pi, 1000);
val = np.sin(arg);

m = arg.size - degree - 1;
step = (arg[-1] - arg[0]) / (m + 1);
knots = np.linspace(step, m * step, m);

f = interpolate.splrep(arg, val, k=degree, s=0, t=knots, per=0);

x = 0.123456;
print interpolate.splev(x, f) - np.sin(x);

此代码打印interpolate.splev,但如果我更改参数2.81341438303e+118,则代码工作得很好:
...
f = interpolate.splrep(arg, val, k=degree, s=0, t=knots, per=1);
...

结果是per
你能解释一下结果吗?不是虫子吗?

最佳答案

参数per改变周期边界条件(pbc)。似乎在没有pbc的情况下,fit并不收敛,但是在pbc的情况下,它是有效的。在绘制数据和样条曲线拟合结果时也可以看到:它只会在边界处发散,其余的数据集都很好地拟合!
documentation of the function interpolate.splrep表示在组合中拥有一个偶数学位不是一个好主意。你有degree = 4(偶数)和s = 0
看来你已经定义了很多结!B样条曲线是分段拟合的。如果有很多节点,则每个样条函数仅对极少数点有效。你有1000个横坐标点和995节。样条曲线的有效点越少,函数的自由度就越大,所以如果你只有很少的点,样条曲线实际上可以是任何东西。。。
将行m = arg.size - degree - 1;更改为m = arg.size - degree - 20;已经产生

>>> print interpolate.splev(x, f) - np.sin(x);
3.08053624276e-10

没有pbc!
所以,问问你自己,为什么你要用这种方法计算结的数量!要么你坚持并引入pbc,即per=1,要么你减少一点结的数量。两者都将稳定拟合,并使收敛!

07-24 22:30