scipy.interpolate.

make_smoothing_spline#

scipy.interpolate.make_smoothing_spline(x, y, w=None, lam=None)[source]#

使用 lam 計算平滑三次樣條函數的(係數),以控制曲線的平滑程度及其與資料的接近程度之間的權衡。如果 lam 為 None,則使用 GCV 準則 [1] 尋找它。

平滑樣條是作為正則化加權線性迴歸問題的解而找到的

\[\sum\limits_{i=1}^n w_i\lvert y_i - f(x_i) \rvert^2 + \lambda\int\limits_{x_1}^{x_n} (f^{(2)}(u))^2 d u\]

其中 \(f\) 是樣條函數,\(w\) 是權重向量,而 \(\lambda\) 是正則化參數。

如果 lam 為 None,我們使用 GCV 準則來尋找最佳正則化參數,否則我們使用給定的參數解決正則化加權線性迴歸問題。該參數以下列方式控制權衡:參數越大,函數變得越平滑。

參數:
xarray_like, shape (n,)

橫座標。n 必須至少為 5。

yarray_like, shape (n,)

縱座標。n 必須至少為 5。

warray_like, shape (n,), optional

權重向量。預設值為 np.ones_like(x)

lamfloat, (\(\lambda \geq 0\)), optional

正則化參數。如果 lam 為 None,則從 GCV 準則中找到它。預設值為 None。

回傳值:
funcBSpline 物件。

一個可呼叫物件,表示 B-spline 基底中的樣條,作為使用 GCV 準則 [1] 平滑樣條問題的解(如果 lam 為 None),否則使用給定的參數 lam

註解

此演算法是對 Woltring 在 FORTRAN [2] 中引入的演算法的淨室重新實作。由於授權問題,原始版本無法在 SciPy 原始碼中使用。重新實作的細節在此處討論(僅提供俄文版本)[4]。

如果權重向量 w 為 None,我們假設所有點在權重方面是相等的,並且權重向量是 1 的向量。

請注意,在加權殘差平方和中,權重未平方:\(\sum\limits_{i=1}^n w_i\lvert y_i - f(x_i) \rvert^2\),而在 splrep 中,總和是從平方權重建立的。

在初始問題不適定的情況下(例如,乘積 \(X^T W X\),其中 \(X\) 是設計矩陣不是正定矩陣),將引發 ValueError。

參考文獻

[1]

G. Wahba, “Estimating the smoothing parameter” in Spline models for observational data, Philadelphia, Pennsylvania: Society for Industrial and Applied Mathematics, 1990, pp. 45-65. DOI:10.1137/1.9781611970128

[2]

H. J. Woltring, A Fortran package for generalized, cross-validatory spline smoothing and differentiation, Advances in Engineering Software, vol. 8, no. 2, pp. 104-113, 1986. DOI:10.1016/0141-1195(86)90098-7

[3]

T. Hastie, J. Friedman, and R. Tisbshirani, “Smoothing Splines” in The elements of Statistical Learning: Data Mining, Inference, and prediction, New York: Springer, 2017, pp. 241-249. DOI:10.1007/978-0-387-84858-7

[4]

E. Zemlyanoy,“廣義交叉驗證平滑樣條”,理學士論文,2022 年。https://www.hse.ru/ba/am/students/diplomas/620910604(俄文)

範例

產生一些雜訊資料

>>> import numpy as np
>>> np.random.seed(1234)
>>> n = 200
>>> def func(x):
...    return x**3 + x**2 * np.sin(4 * x)
>>> x = np.sort(np.random.random_sample(n) * 4 - 2)
>>> y = func(x) + np.random.normal(scale=1.5, size=n)

建立平滑樣條函數

>>> from scipy.interpolate import make_smoothing_spline
>>> spl = make_smoothing_spline(x, y)

繪製兩者

>>> import matplotlib.pyplot as plt
>>> grid = np.linspace(x[0], x[-1], 400)
>>> plt.plot(grid, spl(grid), label='Spline')
>>> plt.plot(grid, func(grid), label='Original function')
>>> plt.scatter(x, y, marker='.')
>>> plt.legend(loc='best')
>>> plt.show()
../../_images/scipy-interpolate-make_smoothing_spline-1.png