BSpline
如果您知道其系数,则允许您构造b 样条。如果要拟合这些系数,则必须使用类似splrep
. 另一种方法是对BSpline.basis_elemement
s 进行线性回归,但它几乎肯定会更好地splrep
用于您的用例。
通常需要打结,但幸运的是它并不太复杂。接受的答案(与 精确拟合s=0
)本质上将节点设置为输入坐标的内部点,但是对于嘈杂的数据,它会过度拟合并且仍然非常“不稳定”:
import numpy as np
import matplotlib.pyplot as plt
from scipy.interpolate import BSpline, splrep, splev
# Generate
np.random.seed(0)
n = 300
ts = np.sort(np.random.uniform(0, 5, size=n))
ys = np.sin(ts) + 0.1*np.random.randn(n)
# Fit
tck = splrep(ts, ys, t=ts[2:-2], k=3)
# Alternative:
# tck = splrep(ts, ys, s=0, k=3)
ys_interp = splev(ts, tck)
# Display
plt.figure(figsize=(12, 6))
plt.plot(ts, ys, '.c')
plt.plot(ts, ys_interp, '-m')
plt.show()

通常更好的方法是将结定义为输入坐标的分位数,选择一个合理的数字(我发现 5-10 适用于简单的形状):
# Fit
n_interior_knots = 5
qs = np.linspace(0, 1, n_interior_knots+2)[1:-1]
knots = np.quantile(ts, qs)
tck = splrep(ts, ys, t=knots, k=3)
ys_smooth = splev(ts, tck)
# Alternative if one really wants to use BSpline:
# ys_smooth = BSpline(*tck)(ts)
# Display
plt.figure(figsize=(12, 6))
plt.plot(ts, ys, '.c')
plt.plot(ts, ys_smooth, '-m')
plt.show()
