Scipy 中的各种样条插值器有什么区别?

问题描述 投票:0回答:1

我的目标是计算通过一组点的平滑轨迹,如下所示。我查看了

scipy.interpolate
的可用方法,以及 scipy 用户指南。然而,我不太清楚选择正确的方法。

有什么区别

BSpline
,
splprep
,
splrep
,
UnivariateSpline
,
interp1d
,
make_interp_spline
CubicSpline

根据文档,所有函数都通过一系列输入点计算一些多项式样条函数。我应该选择哪个功能? A) 三次样条和 3 阶 B 样条有什么区别? B)

splprep()
splrep()
有什么区别? C) 为什么
interp1d()
将被弃用?

我知道我在这里问不同的问题,但我不认为将问题分开有什么意义,因为我认为答案是相关的。

总而言之,我发现 scipy.interpolate 模块的组织有点混乱。我想也许我不是唯一有这种印象的人,这就是我向 SO 伸出援手的原因。


这就是我已经走了多远。下面是一些针对某些测试数据运行不同样条函数的代码。它创建了下图。

  1. 我在某处读到:“所有三次样条都可以表示为 3 阶 B 样条”,并且“这是一个观点问题,哪种表示更方便”。但是,如果我使用
    CublicSpline
    和任何 B 样条方法,为什么最终会得到不同的结果?
  2. 我发现可以从
    BSpline
    splprep
    的输出构造一个
    splrep
    对象,使得
    splev()
    BSpline()
    的结果是等价的。这样,我们就可以将
    splrep
    splprep
    的输出转换为
    scipy.interpolate()
    的面向对象接口。
  3. splrep
    UnivariateSpline
    make_interp_spline
    会产生相同的结果。在我的二维数据中,我需要针对每个有效的数据维度独立应用插值。便利函数
    interp1d
    也能产生相同的结果。相关SO问题:Link
  4. splprep
    splrep
    似乎无关。即使我为每个数据轴独立计算
    splprep
    两次(参见 p0_new),结果看起来也会有所不同。我在文档中看到 splprep 计算 n 维曲线的 B 样条表示。但
    splrep
    splprep
    应该没有关系吗?
  5. splprep
    splrep
    UnivariateSpline
    有平滑参数,而其他插值器没有这样的参数。
  6. splrep
    UnivariateSpline
    配对。但是,我找不到
    splprep
    的匹配的面向对象对应项。有吗

import numpy as np
from scipy.interpolate import *
import matplotlib.pyplot as plt

points = [[0, 0], [4, 4], [-1, 9], [-4, -1], [-1, -9], [4, -4], [0, 0]]
points = np.asarray(points)

n = 50 
ts = np.linspace(0, 1, len(points))
ts_new = np.linspace(0, 1, n)

(t0_0,c0_0,k0_0), u = splprep(points[:,[0]].T, s=0, k=3)
(t0_1,c0_1,k0_1), u = splprep(points[:,[1]].T, s=0, k=3)
p0_new = np.r_[np.asarray(splev(ts_new, (t0_0,c0_0,k0_0))),
               np.asarray(splev(ts_new, (t0_1,c0_1,k0_1))),
                ].T

# splprep/splev
(t1,c1,k1), u = splprep(points.T, s=0, k=3)
p1_new = splev(ts_new, (t1,c1,k1))
# BSpline from splprep
p2_new = BSpline(t1, np.asarray(c1).T, k=k1)(ts_new)
# splrep/splev (per dimension)
(t3_0,c3_0,k3_0) = splrep(ts, points[:,0].T, s=0, k=3)
(t3_1,c3_1,k3_1) = splrep(ts, points[:,1].T, s=0, k=3)
p3_new = np.c_[splev(ts_new, (t3_0,c3_0,k3_0)),
               splev(ts_new, (t3_1,c3_1,k3_1)),
               ]
# Bspline from splrep
p4_new = np.c_[BSpline(t3_0, np.asarray(c3_0), k=k3_0)(ts_new),
               BSpline(t3_1, np.asarray(c3_1), k=k3_1)(ts_new),
               ]
# UnivariateSpline
p5_new = np.c_[UnivariateSpline(ts, points[:,0], s=0, k=3)(ts_new),
               UnivariateSpline(ts, points[:,1], s=0, k=3)(ts_new),]
# make_interp_spline
p6_new = make_interp_spline(ts, points, k=3)(ts_new)
# CubicSpline
p7_new = CubicSpline(ts, points, bc_type="clamped")(ts_new)
# interp1d
p8_new = interp1d(ts, points.T, kind="cubic")(ts_new).T

fig, ax = plt.subplots()
ax.plot(*points.T, "o-", label="Original points")
ax.plot(*p1_new,   "o-", label="1: splprep/splev")
ax.plot(*p2_new.T, "x-", label="1: BSpline from splprep")
ax.plot(*p3_new.T, "o-", label="2: splrep/splev")
ax.plot(*p4_new.T, "x-", label="2: BSpline from splrep")
ax.plot(*p5_new.T, "*-", label="2: UnivariateSpline")
ax.plot(*p6_new.T, "+-", label="2: make_interp_spline")
ax.plot(*p7_new.T, "x-", label="3: CubicSpline")
#ax.plot(*p8_new.T, "k+-", label="3: interp1d")
#ax.plot(*p0_new.T, "k+-", label="3: CubicSpline")
ax.set_aspect("equal")
ax.grid("on")
ax.legend(loc='center left', bbox_to_anchor=(1, 0.5))
plt.show()
python scipy interpolation spline
1个回答
0
投票

BSpline、splprep、splrep、UnivariateSpline、interp1d、make_interp_spline 和 CubicSpline 之间有什么区别?

  • a

    BSpline
    对象表示以节点
    t
    、系数
    c
    和度
    k
    表示的样条函数。它对数据一无所知
    x, y
    。它是一个低级实现对象,与
    PPoly
    同等——将 PPoly 与 BSpline 视为基础的变化。

  • make_interp_spline
    构造一条样条线 (
    BSpline
    ),它穿过数据
    x
    y
    ——它是一个 插值样条线,因此
    spl(x) == y
    。它可以处理批量数据:如果 y 是二维的,并且第二维的长度为
    n
    ,则
    make_interp_spline(x, y)
    表示一堆函数
    y_1(x), y_2(x), ..., y_n(x)

  • CubicSpline
    类似,但更受限制:它只允许三次样条,
    k=3
    。如果您需要从立方体切换到例如立方体线性插值,使用
    make_interp_spline
    ,您只需在调用站点将
    k=3
    更改为
    k=1
    。 OTOH,
    CubicSpline
    具有 BSpline 所没有的一些功能:例如寻根。它是一个 PPoly 实例,而不是 BSpline。

  • interp1d 并未被弃用,它是legacy。 interp1d 的一个有用部分是最近/上一个/下一个模式。其余的只是委托给 make_interp_spline,所以最好直接使用它。

  • splrep
    在给定数据的情况下构造一个 smoothing 样条函数。平滑量由
    s
    参数控制,其中
    s=0
    是插值。它返回的不是 BSpline,而是 tck 元组(结、系数和度)。

  • splprep
    以参数形式构造平滑样条曲线。那是
    (x(u), y(u))
    不是
    y(x)
    。还返回 tck 元组。

  • UnivariateSpline
    相当于
    splrep

请注意,

scipy.interpolate
已经有机增长。近四分之一个世纪以来,至少有四代开发人员。而
splrep
splprep
UnivariateSpline
委托的FITPACK库是从20世纪80年代开始的。
CubicSpline
BSpline
make_interp_spline
未使用 FITPACK。

所以在新代码中我个人会推荐

make_interp_spline
+
BSpline
;如果您只需要立方,
CubicSpline
也可以。

但是,如果我使用 CublicSpline 和任何 B 样条方法,为什么最终会得到不同的结果?

边界条件。

make_interp_spline
CubicSpline
默认为
not-a-knot
,您可以更改它。
splrep
等人仅使用
not-a-knot

© www.soinside.com 2019 - 2024. All rights reserved.