我不明白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
,要么你减少一点结的数量。两者都将稳定拟合,并使收敛!