首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >python中的scipy BSpline拟合

python中的scipy BSpline拟合
EN

Stack Overflow用户
提问于 2017-07-19 08:15:58
回答 3查看 17.2K关注 0票数 6

这是我第一次使用BSpline,我想要将曲线拟合到我的数据点。我已经尝试过使用单变量样条线,并尝试使用splev和splrep,但我真的很想学习如何使用BSpline来做到这一点。

看起来我的拟合真的很不稳定,这条线甚至没有通过这些点。

代码语言:javascript
复制
arraymagU = linspace(U_timeband.min(),U_timeband.max(),300) #array for my x data points
UfunctionBS = BSpline(U_timeband,U_magband,k=4,extrapolate=False)
arraymagU2 = UfunctionBS(arraymagU)

plt.plot(arraymagU,arraymagU2)

U_timeband是我的x坐标,U_magband是我的y,我想k=4表示三次拟合?我一直在玩弄这种价值,但它似乎并没有让它变得更好。

它会产生这样的结果:

我怎样才能让它变得更好、更一致呢?我想我可能不得不定义断点,但我也不确定如何定义断点。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2017-07-19 10:00:33

splrep返回一个包含节点向量、B样条系数和样条线阶数的元组(t,c,k)。可以将这些内容提供给interpolate.BSpline以创建BSpline对象:

代码语言:javascript
复制
import numpy as np
import scipy.interpolate as interpolate
import matplotlib.pyplot as plt

x = np.array([ 0. ,  1.2,  1.9,  3.2,  4. ,  6.5])
y = np.array([ 0. ,  2.3,  3. ,  4.3,  2.9,  3.1])

t, c, k = interpolate.splrep(x, y, s=0, k=4)
print('''\
t: {}
c: {}
k: {}
'''.format(t, c, k))
N = 100
xmin, xmax = x.min(), x.max()
xx = np.linspace(xmin, xmax, N)
spline = interpolate.BSpline(t, c, k, extrapolate=False)

plt.plot(x, y, 'bo', label='Original points')
plt.plot(xx, spline(xx), 'r', label='BSpline')
plt.grid()
plt.legend(loc='best')
plt.show()

票数 15
EN

Stack Overflow用户

发布于 2021-07-09 18:18:50

如果你知道b样条的系数,BSpline允许你构造b样条。如果你想拟合这些系数,你必须使用像splrep这样的东西。另一种选择是在BSpline.basis_elemement上进行线性回归,但几乎可以肯定的是,在您的用例中使用splrep更好。

这通常是必要的,但谢天谢地,这并不是太复杂。公认的答案(与s=0精确拟合)本质上是将节点设置为输入坐标的内点,但对于噪声数据,它将过度拟合,并且仍然非常“起伏”:

代码语言:javascript
复制
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对于简单的形状很好):

代码语言:javascript
复制
# 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()

票数 2
EN

Stack Overflow用户

发布于 2020-03-05 00:14:07

请注意,要使用interpolate.BSpline,您将需要scipy版本0.19或更高版本(请参阅:https://docs.scipy.org/doc/scipy/reference/release.0.19.0.html#scipy-interpolate-improvements)。

票数 -1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/45179024

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档