簡體   English   中英

python中的scipy BSpline擬合

[英]scipy BSpline fitting in python

這是我第一次使用 BSpline,我想為我的數據點擬合一條曲線。 我嘗試過使用 Univariate Spline 並嘗試使用 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返回一個元組(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()

在此處輸入圖片說明

如果您知道BSpline的系數,則BSpline允許您構建b 樣條。 如果要擬合這些系數,則必須使用splrep類的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()

平滑圖

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM