我无法理解interpolate.splrep
函数的工作原理。简单的代码不会抛出任何错误,但interpolate.splev
会返回意外的结果。
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);
此代码打印2.81341438303e+118
,但如果我更改参数per
,则代码效果非常好:
...
f = interpolate.splrep(arg, val, k=degree, s=0, t=knots, per=1);
...
结果是-1.80411241502e-16
。
你能解释一下结果吗?不是一个错误吗?
答案 0 :(得分:0)
参数per
切换周期性边界条件(pbc)。似乎没有pbc,拟合不会收敛,但是对于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
,要么减少结点数。两者都能稳定合身并实现融合!