Spec-Zone.ru › scikit-learn

Примечание

Перейти в конец, чтобы скачать полный код примера или запустить этот пример в браузере с помощью JupyterLite или Binder.

Полиномиальная интерполяция и интерполяция сплайнами

В этом примере показано, как аппроксимировать функцию полиномами степени до degree с помощью гребневой регрессии. Рассматриваются два способа преобразования заданных n_samples одномерных точек x_i:

  • PolynomialFeatures генерирует все мономы до степени degree. В результате получается так называемая матрица Вандермонда с n_samples строками и degree + 1 столбцами:

    [[1, x_0, x_0 ** 2, x_0 ** 3, ..., x_0 ** degree],
     [1, x_1, x_1 ** 2, x_1 ** 3, ..., x_1 ** degree],
     ...]
    

    Интуитивно эту матрицу можно интерпретировать как матрицу псевдопризнаков (точек, возведённых в некоторую степень). Эта матрица похожа на матрицу, индуцированную полиномиальным ядром, но отличается от неё.

  • SplineTransformer генерирует базисные функции B-сплайнов. Базисная функция B-сплайна — это кусочно-полиномиальная функция степени degree, отличная от нуля только между degree+1 соседними узлами. Для заданного числа узлов n_knots получается матрица с n_samples строками и n_knots + degree - 1 столбцами:

    [[basis_1(x_0), basis_2(x_0), ...],
     [basis_1(x_1), basis_2(x_1), ...],
     ...]
    

Этот пример показывает, что оба преобразователя хорошо подходят для моделирования нелинейных эффектов с помощью линейной модели, добавляя нелинейные признаки при помощи конвейера. Методы ядер развивают эту идею и позволяют создавать пространства признаков очень высокой (даже бесконечной) размерности.

# Authors: The scikit-learn developers
# SPDX-License-Identifier: BSD-3-Clause

import matplotlib.pyplot as plt
import numpy as np

from sklearn.linear_model import Ridge
from sklearn.pipeline import make_pipeline
from sklearn.preprocessing import PolynomialFeatures, SplineTransformer

Сначала определим функцию, которую будем аппроксимировать, и подготовим её график.

def f(x):
    """Function to be approximated by polynomial interpolation."""
    return x * np.sin(x)


# whole range we want to plot
x_plot = np.linspace(-1, 11, 100)

Чтобы усложнить задачу, для обучения мы используем лишь небольшое подмножество точек.

x_train = np.linspace(0, 10, 100)
rng = np.random.RandomState(0)
x_train = np.sort(rng.choice(x_train, size=20, replace=False))
y_train = f(x_train)

# create 2D-array versions of these arrays to feed to transformers
X_train = x_train[:, np.newaxis]
X_plot = x_plot[:, np.newaxis]

Теперь можно создать полиномиальные признаки и сплайны, обучить модели на обучающих точках и посмотреть, насколько хорошо они их интерполируют.

# plot function
lw = 2
fig, ax = plt.subplots()
ax.set_prop_cycle(
    color=["black", "teal", "yellowgreen", "gold", "darkorange", "tomato"]
)
ax.plot(x_plot, f(x_plot), linewidth=lw, label="ground truth")

# plot training points
ax.scatter(x_train, y_train, label="training points")

# polynomial features
for degree in [3, 4, 5]:
    model = make_pipeline(PolynomialFeatures(degree), Ridge(alpha=1e-3))
    model.fit(X_train, y_train)
    y_plot = model.predict(X_plot)
    ax.plot(x_plot, y_plot, label=f"degree {degree}")

# B-spline with 4 + 3 - 1 = 6 basis functions
model = make_pipeline(SplineTransformer(n_knots=4, degree=3), Ridge(alpha=1e-3))
model.fit(X_train, y_train)

y_plot = model.predict(X_plot)
ax.plot(x_plot, y_plot, label="B-spline")
ax.legend(loc="lower center")
ax.set_ylim(-20, 10)
plt.show()
plot polynomial interpolation

На графике хорошо видно, что полиномы более высокой степени лучше соответствуют данным. Однако при слишком высоких степенях могут возникать нежелательные осцилляции, особенно опасные при экстраполяции за пределы диапазона обучающих данных. В этом заключается преимущество B-сплайнов. Обычно они соответствуют данным не хуже полиномов и демонстрируют очень плавное поведение. Кроме того, они позволяют хорошо контролировать экстраполяцию; по умолчанию функция продолжается постоянной. Обратите внимание: чаще всего лучше увеличить число узлов, сохранив degree=3.

Чтобы лучше понять, какие базисы признаков создаются, построим графики всех столбцов обоих преобразователей по отдельности.

fig, axes = plt.subplots(ncols=2, figsize=(16, 5))
pft = PolynomialFeatures(degree=3).fit(X_train)
axes[0].plot(x_plot, pft.transform(X_plot))
axes[0].legend(axes[0].lines, [f"degree {n}" for n in range(4)])
axes[0].set_title("PolynomialFeatures")

splt = SplineTransformer(n_knots=4, degree=3).fit(X_train)
axes[1].plot(x_plot, splt.transform(X_plot))
axes[1].legend(axes[1].lines, [f"spline {n}" for n in range(6)])
axes[1].set_title("SplineTransformer")

# plot knots of spline
knots = splt.bsplines_[0].t
axes[1].vlines(knots[3:-3], ymin=0, ymax=0.8, linestyles="dashed")
plt.show()
PolynomialFeatures, SplineTransformer

На левом графике видны прямые, соответствующие простым мономам от x**0 до x**3. На правом графике показаны шесть базисных функций B-сплайнов для degree=3, а также четыре положения узлов, выбранные во время fit. Обратите внимание, что с каждой стороны от интервала аппроксимации имеется degree дополнительных узлов. Они нужны по техническим причинам, поэтому мы не показываем их. Каждая базисная функция имеет локальную область поддержки и продолжается постоянной за пределами диапазона аппроксимации. Такое поведение при экстраполяции можно изменить с помощью аргумента extrapolation.

Периодические сплайны

В предыдущем примере мы увидели ограничения полиномов и сплайнов при экстраполяции за пределы диапазона обучающих наблюдений. В некоторых случаях, например при наличии сезонных эффектов, мы ожидаем периодического продолжения исходного сигнала. Такие эффекты можно моделировать с помощью периодических сплайнов, у которых значения функции и её производных совпадают в первом и последнем узлах. В следующем примере показано, что с учётом периодичности периодические сплайны обеспечивают более точную аппроксимацию как внутри, так и за пределами диапазона обучающих данных. Период сплайна равен расстоянию между первым и последним узлами; мы задаём его вручную.

Периодические сплайны также могут быть полезны для естественным образом периодических признаков (например, дня года), поскольку гладкость в граничных узлах предотвращает скачок преобразованных значений (например, при переходе от 31 декабря к 1 января). Для таких естественным образом периодических признаков и, в более общем случае, для признаков с известным периодом рекомендуется явно передать эту информацию в SplineTransformer, задав узлы вручную.

def g(x):
    """Function to be approximated by periodic spline interpolation."""
    return np.sin(x) - 0.7 * np.cos(x * 3)


y_train = g(x_train)

# Extend the test data into the future:
x_plot_ext = np.linspace(-1, 21, 200)
X_plot_ext = x_plot_ext[:, np.newaxis]

lw = 2
fig, ax = plt.subplots()
ax.set_prop_cycle(color=["black", "tomato", "teal"])
ax.plot(x_plot_ext, g(x_plot_ext), linewidth=lw, label="ground truth")
ax.scatter(x_train, y_train, label="training points")

for transformer, label in [
    (SplineTransformer(degree=3, n_knots=10), "spline"),
    (
        SplineTransformer(
            degree=3,
            knots=np.linspace(0, 2 * np.pi, 10)[:, None],
            extrapolation="periodic",
        ),
        "periodic spline",
    ),
]:
    model = make_pipeline(transformer, Ridge(alpha=1e-3))
    model.fit(X_train, y_train)
    y_plot_ext = model.predict(X_plot_ext)
    ax.plot(x_plot_ext, y_plot_ext, label=label)

ax.legend()
fig.show()
plot polynomial interpolation
fig, ax = plt.subplots()
knots = np.linspace(0, 2 * np.pi, 4)
splt = SplineTransformer(knots=knots[:, None], degree=3, extrapolation="periodic").fit(
    X_train
)
ax.plot(x_plot_ext, splt.transform(X_plot_ext))
ax.legend(ax.lines, [f"spline {n}" for n in range(3)])
plt.show()
plot polynomial interpolation

Общее время выполнения скрипта: (0 минут 0.410 секунды)

Launch binder
Launch JupyterLite

Download Jupyter notebook: plot_polynomial_interpolation.ipynb

Download Python source code: plot_polynomial_interpolation.py

Download zipped: plot_polynomial_interpolation.zip

Похожие примеры

Сравнение линейных байесовских регрессоров

Визуализация вероятностных предсказаний VotingClassifier

Недообучение и переобучение

Создание признаков, связанных со временем

© 2007–2026 The scikit-learn developers
Licensed under the 3-clause BSD License.
https://scikit-learn.org/1.9/auto_examples/linear_model/plot_polynomial_interpolation.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API