scipy splrep(),权重不符合给定的曲线

时间:2016-02-07 22:27:58

标签: python scipy interpolation bspline

使用scipy的splrep我可以很容易地拟合测试正弦波:

import numpy as np
from scipy.interpolate import splrep, splev
import matplotlib.pyplot as plt
plt.style.use("ggplot")

# Generate test sinewave
x = np.arange(0, 20, .1)
y = np.sin(x)

# Interpolate
tck = splrep(x, y)
x_spl = x + 0.05 # Just to show it wors
y_spl = splev(x_spl, tck)
plt.plot(x_spl, y_spl)

Spline sinewave plot

splrep documentation states,权重参数的默认值为np.ones(len(x))。但是,绘制这个图会产生完全不同的情节:

tck = splrep(x, y, w=np.ones(len(x_spl)))
y_spl = splev(x_spl, tck)
plt.plot(x_spl, y_spl)

Plot with splev and weights

文档还指出,当给出权重数组时,平滑条件s是不同的 - 但即使设置s=len(x_spl) - np.sqrt(2*len(x_spl))(没有权重数组的默认值),结果也不严格对应于原始曲线如图所示。

为了使用权重数组(如上所列)进行插值输出与没有权重的插值相同的结果,我需要在上面列出的代码中进行哪些更改? 我用scipy 0.17.0对此进行了测试。 Gist with a test IPython notebook

1 个答案:

答案 0 :(得分:2)

您只需更改代码的一行即可获得相同的输出:

tck = splrep(x, y, w=np.ones(len(x_spl)))

应该成为

tck = splrep(x, y, w=np.ones(len(x_spl)), s=0)

因此,唯一的区别是您必须指定s而不是使用默认值。

当您查看splrep的{​​{3}}时,您会看到为什么这是必要的:

if w is None:
    w = ones(m, float)
    if s is None:
        s = 0.0

else:
    w = atleast_1d(w)
    if s is None:
        s = m - sqrt(2*m)

这意味着,如果既未提供权重也未提供s,则s设置为0,如果您提供权重但不提供s,则s = m - sqrt(2*m)其中m = len(x) }}

因此,在上面的示例中,您比较具有相同权重但具有不同s的输出(分别为0m - sqrt(2*m))。