scipy.interpolate.

make_lsq_spline#

scipy.interpolate.make_lsq_spline(x, y, t, k=3, w=None, axis=0, check_finite=True, *, method='qr')[source]#

创建满足最小二乘 (LSQ) 准则的光滑 B 样条。

结果是一个线性组合

\[S(x) = \sum_j c_j B_j(x; t)\]

B 样条基元素 \(B_j(x; t)\) 的线性组合,它最小化以下表达式:

\[\sum_{j} \left( w_j \times (S(x_j) - y_j) \right)^2\]
参数:
xarray_like, shape (m,)

横坐标。

yarray_like, shape (m, …)

纵坐标。

tarray_like, shape (n + k + 1,).

节点。节点和数据点必须满足 Schoenberg-Whitney 条件。

kint, optional

B 样条次数。默认值为三次,k = 3

warray_like, shape (m,), optional

样条拟合的权重。必须为正。如果为 None,则所有权重相等。默认值为 None

axisint, optional

插值轴。默认值为零。

check_finitebool, optional

是否检查输入数组仅包含有限数字。禁用此项可能会提高性能,但如果输入包含无穷大或 NaN,可能会导致问题(崩溃、无法终止)。默认值为 True。

methodstr, optional

解决线性 LSQ 问题的 G方法。允许的值为“norm-eq”(显式构建和求解法线方程组),以及“qr”(使用设计矩阵的 QR 分解)。默认值为“qr”。

返回:
bBSpline 对象

一个次数为 k 且节点为 tBSpline 对象。

另请参阅

BSpline

表示 B 样条对象的基类

make_interp_spline

一个用于插值样条的类似工厂函数

LSQUnivariateSpline

一个基于 FITPACK 的样条拟合例程

splrep

一个基于 FITPACK 的拟合例程

注释

数据点的数量必须大于样条次数 k

节点 t 必须满足 Schoenberg-Whitney 条件,即必须存在数据点 x[j] 的一个子集,使得对于 j=0, 1,...,n-k-2,有 t[j] < x[j] < t[j+k+1]

示例

生成一些带噪声的数据

>>> import numpy as np
>>> import matplotlib.pyplot as plt
>>> rng = np.random.default_rng()
>>> x = np.linspace(-3, 3, 50)
>>> y = np.exp(-x**2) + 0.1 * rng.standard_normal(50)

现在使用预定义的内部节点拟合光滑三次样条。这里我们通过添加边界节点使节点向量 (k+1) 规则化。

>>> from scipy.interpolate import make_lsq_spline, BSpline
>>> t = [-1, 0, 1]
>>> k = 3
>>> t = np.r_[(x[0],)*(k+1),
...           t,
...           (x[-1],)*(k+1)]
>>> spl = make_lsq_spline(x, y, t, k)

为了进行比较,我们还为同一组数据构建了一个插值样条。

>>> from scipy.interpolate import make_interp_spline
>>> spl_i = make_interp_spline(x, y)

绘制两者

>>> xs = np.linspace(-3, 3, 100)
>>> plt.plot(x, y, 'ro', ms=5)
>>> plt.plot(xs, spl(xs), 'g-', lw=3, label='LSQ spline')
>>> plt.plot(xs, spl_i(xs), 'b-', lw=3, alpha=0.7, label='interp spline')
>>> plt.legend(loc='best')
>>> plt.show()
../../_images/scipy-interpolate-make_lsq_spline-1_00_00.png

NaN 处理:如果输入数组包含 nan 值,则结果将无用,因为底层的样条拟合例程无法处理 nan。一个解决方法是使用零权重来处理非数字数据点。

>>> y[8] = np.nan
>>> w = np.isnan(y)
>>> y[w] = 0.
>>> tck = make_lsq_spline(x, y, t, w=~w)

请注意,需要将 nan 替换为一个数值(只要对应的权重为零,精确值无关紧要)。