make_smoothing_spline#
- scipy.interpolate.make_smoothing_spline(x, y, w=None, lam=None, *, ось=0)[источник]#
Создать сглаживающий B-сплайн, удовлетворяющий критерию обобщённой перекрёстной проверки (GCV).
Вычислить (коэффициенты) функции сглаживающего кубического сплайна, используя
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, форма (n,)
Абсциссы. n должно быть не менее 5.
- yarray_like, форма (n, …)
Ординаты. n должно быть не менее 5.
- warray_like, shape (n,), optional
Вектор весов. По умолчанию
np.ones_like(x).- lamfloat, (\(\lambda \geq 0\)), optional
Параметр регуляризации. Если
lamравно None, тогда оно находится из критерия GCV. По умолчанию None.- осьint, необязательный
Ось данных. По умолчанию ноль. Предполагается, что
y.shape[axis] == n, и все остальные осиyявляются осями пакетной обработки.
- Возвращает:
- функция
BSplineobject Объект, представляющий сплайн в базисе B-сплайнов как решение задачи сглаживающих сплайнов с использованием критерия GCV [1] в случае
lamis None, в противном случае используется заданный параметрlam.
- функция
Примечания
Этот алгоритм является чистой переработкой алгоритма, представленного Вольтрингом на FORTRAN [2]. Оригинальная версия не может быть использована в исходном коде SciPy из-за проблем с лицензией. Детали переработки обсуждаются здесь (доступно только на русском) [4].
Если вектор весов
wравен None, мы предполагаем, что все точки равны по весам, и вектор весов является вектором единиц.Обратите внимание, что во взвешенной сумме квадратов остатков веса не возводятся в квадрат: \(\sum\limits_{i=1}^n w_i\lvert y_i - f(x_i) \rvert^2\) в то время как в
splrepсумма строится из квадратов весов.В случаях, когда исходная задача плохо обусловлена (например, произведение \(X^T W X\) где \(X\) является матрицей плана, не является положительно определенной матрицей) возникает ValueError.
Ссылки
[1]Г. Вабба, «Оценка параметра сглаживания» в Spline models for observational data, Филадельфия, Пенсильвания: Общество промышленной и прикладной математики, 1990, стр. 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]Т. Хасти, Дж. Фридман и Р. Тибширани, «Сглаживающие сплайны» в Элементы статистического обучения: интеллектуальный анализ данных, вывод и прогнозирование, Нью-Йорк: Springer, 2017, стр. 241-249. DOI:10.1007/978-0-387-84858-7
[4]E. Земляной, «Обобщенные сглаживающие сплайны с перекрестной проверкой», дипломная работа бакалавра, 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(x, y, '.') >>> plt.plot(grid, spl(grid), label='Spline') >>> plt.plot(grid, func(grid), label='Original function') >>> plt.legend(loc='best') >>> plt.show()