![](/img/trans.png)
[英]scipy.interpolate.make_interp_spline how to retrieve all the coefficients?
[英]How to select good knot sequences for "scipy.interpolate.make_lsq_spline"
我想使用scipy.interpolate.make_lsq_spline
創建一個平滑二維數據序列的 B 樣條曲線。
x = [0., 0.37427465, 0.68290943, 0.83261929, 1. ]
y = [-1.0, 3.0, 4.0, 2.0, 1.0]
但是,我不知道如何 select 正確t
,錯誤消息對我來說沒有意義。
In [1]: import numpy as np
In [2]: from scipy.interpolate import make_lsq_spline
In [3]: x = [0., 0.37427465, 0.68290943, 0.83261929, 1. ]
In [4]: y = [-1.0, 3.0, 4.0, 2.0, 1.0]
In [5]: t = [0.,0.,0.,0.,0.25,0.5,0.75,1.,1.,1.,1 ]
In [6]: spl = make_lsq_spline(x, y, t)
---------------------------------------------------------------------------
LinAlgError Traceback (most recent call last)
<ipython-input-6-4440a73d26f0> in <cell line: 1>()
----> 1 spl = make_lsq_spline(x, y, t)
/Library/Frameworks/Python.framework/Versions/3.10/lib/python3.10/site-packages/scipy/interpolate/_bsplines.py in make_lsq_spline(x, y, t, k, w, axis, check_finite)
1513
1514 # have observation matrix & rhs, can solve the LSQ problem
-> 1515 cho_decomp = cholesky_banded(ab, overwrite_ab=True, lower=lower,
1516 check_finite=check_finite)
1517 c = cho_solve_banded((cho_decomp, lower), rhs, overwrite_b=True,
/Library/Frameworks/Python.framework/Versions/3.10/lib/python3.10/site-packages/scipy/linalg/_decomp_cholesky.py in cholesky_banded(ab, overwrite_ab, lower, check_finite)
280 c, info = pbtrf(ab, lower=lower, overwrite_ab=overwrite_ab)
281 if info > 0:
--> 282 raise LinAlgError("%d-th leading minor not positive definite" % info)
283 if info < 0:
284 raise ValueError('illegal value in %d-th argument of internal pbtrf'
LinAlgError: 5-th leading minor not positive definite
是否有選擇合適的結序列t
的指南?
我有一個類似的問題。 由於你的榜樣,我想我可以知道出了什么問題。 從線性代數的角度來看,您要求解決無法唯一解決的問題。 您提供 11 knots t,這意味着有 11-3-1 = 7 個系數要確定,因為您嘗試擬合 k=3 度的樣條曲線(make_lsq_spline 的默認值)。 對 5 個點 x 進行評估,方程系統的左側由 5 x 7 矩陣 D 給出。D 在示例中具有滿秩,但這無濟於事。 7 x 7 矩陣 N = DT@D 僅為半正定矩陣。 兩個特征值為 0。它不能倒置,因此你的問題不能唯一解決。 一種解決方案是擺脫 2 節,比如 0.25 和 0.75 的節。 在使用 3 階樣條曲線時,邊界處的四折結應該保留,因為您很可能希望插值樣條曲線跳到那里。 總而言之,必須以插值問題唯一可解的方式選擇節點。 我還嘗試添加一些代碼來說明我想說的話。 希望有所幫助。
import numpy as np
import scipy.interpolate as sciint
import matplotlib.pyplot as plt
x = [0., 0.37427465, 0.68290943, 0.83261929, 1.]
y = [-1.0, 3.0, 4.0, 2.0, 1.0]
t = [0.,0.,0.,0.,0.25,0.5,0.75,1.,1.,1.,1 ]
splines = []
for k in range(7):
coeff = np.zeros(7)
coeff[k] = 1.
splines.append(sciint.BSpline(t,coeff,3))
fig,ax = plt.subplots(3,3)
dom = np.linspace(0.,1.,1000)
for count,axes in enumerate(ax.flat):
axes.plot(dom,splines[count](dom))
if count == len(splines)-1:
break
data = []
for spline in splines:
data.append(np.vstack(spline(x)))
D = np.hstack(tuple(data))
N = D.T @ D
sing = np.linalg.eigvalsh(N)
print(sing)
t2 = [0.,0.,0.,0.,0.5,1.,1.,1.,1 ]
bspline = sciint.make_lsq_spline(x,y,t2)
ax[2,1].plot(x,y,'r')
ax[2,2].plot(dom,bspline(dom),'m')
不是我的問題的直接答案,而是scipy.interpolate.make_smoothing_spline
: https://docs.scipy.org/doc/scipy/reference/generated/scipy.interpolate.make_smoothing_spline.html#scipy.interpolate.make_smoothing_spline從樣條中引入scipy 1.10.0 可用於我的用例。
In [1]: import numpy as np
In [2]: from scipy.interpolate import make_smoothing_spline
In [3]: import matplotlib.pyplot as plt
In [4]: x = [0., 0.37427465, 0.68290943, 0.83261929, 1. ]
In [5]: y = [-1.0, 3.0, 4.0, 2.0, 1.0]
In [6]: spl = make_smoothing_spline(x, y)
In [7]: plt.plot(x, y, "rx")
Out[7]: [<matplotlib.lines.Line2D at 0x12f101e70>]
In [8]: x_grid = np.linspace(x[0], x[-1], 400)
In [9]: plt.plot(x_grid, spl(x_grid), label='Smoothing Spline')
Out[9]: [<matplotlib.lines.Line2D at 0x12f102830>]
In [10]: plt.legend(loc="best")
Out[10]: <matplotlib.legend.Legend at 0x12473bc40>
In [11]: plt.show()
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.