scipy B样条拟合 python
scipy BSpline fitting in python
这是我第一次使用 BSpline,我想为我的数据点拟合一条曲线。我试过使用单变量样条曲线并尝试使用 splev 和 splrep 但我真的很想学习如何使用 BSpline 来做到这一点。
看来我的试穿真的很不稳定,连线都没有穿过点。
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 我认为表示立方拟合?我试过这个值,但它似乎并没有使它变得更好。
它产生这个:
我怎样才能让它变得更好、更一致?
我想我可能必须定义断点,但我也不知道该怎么做。
splrep returns 一个元组 (t,c,k)
包含节点向量、B 样条系数和样条的阶数。这些可以被馈送到 interpolate.BSpline
以创建 BSpline 对象:
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()
请注意,要使用 interpolate.BSpline
,您需要 scipy 版本 0.19 或更高版本(参见:https://docs.scipy.org/doc/scipy/reference/release.0.19.0.html#scipy-interpolate-improvements)。
如果您知道系数,BSpline
允许您构造 一个 b 样条曲线。如果你想拟合这些系数,你将不得不使用类似splrep
的东西。另一种方法是对 BSpline.basis_elemement
进行线性回归,但对于您的用例,使用 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()
这是我第一次使用 BSpline,我想为我的数据点拟合一条曲线。我试过使用单变量样条曲线并尝试使用 splev 和 splrep 但我真的很想学习如何使用 BSpline 来做到这一点。
看来我的试穿真的很不稳定,连线都没有穿过点。
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 我认为表示立方拟合?我试过这个值,但它似乎并没有使它变得更好。
它产生这个:
我怎样才能让它变得更好、更一致? 我想我可能必须定义断点,但我也不知道该怎么做。
splrep returns 一个元组 (t,c,k)
包含节点向量、B 样条系数和样条的阶数。这些可以被馈送到 interpolate.BSpline
以创建 BSpline 对象:
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()
请注意,要使用 interpolate.BSpline
,您需要 scipy 版本 0.19 或更高版本(参见:https://docs.scipy.org/doc/scipy/reference/release.0.19.0.html#scipy-interpolate-improvements)。
BSpline
允许您构造 一个 b 样条曲线。如果你想拟合这些系数,你将不得不使用类似splrep
的东西。另一种方法是对 BSpline.basis_elemement
进行线性回归,但对于您的用例,使用 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()