Interpolación polinómica y con splines

Beginner

This tutorial is from open-source community. Access the source code

Introducción

En este laboratorio, aprenderemos cómo aproximar una función con polinomios de un cierto grado utilizando regresión con regularización L2. Mostraremos dos maneras diferentes de hacer esto dados n_samples de puntos unidimensionales x_i:

  1. PolynomialFeatures: genera todos los monomios hasta un grado especificado. Esto nos da la matriz de Vandermonde con n_samples filas y degree + 1 columnas.
  2. SplineTransformer: genera funciones de base B-spline. Una función de base de una B-spline es una función polinómica por tramos de grado degree que es no nula solo entre degree+1 nudos consecutivos.

Usaremos la función make_pipeline para agregar características no lineales y mostraremos cómo estos transformadores son adecuados para modelar efectos no lineales con un modelo lineal. Graficaremos la función, los puntos de entrenamiento y la interpolación utilizando características polinómicas y B-splines. También graficaremos todas las columnas de ambos transformadores por separado y mostraremos los nudos de la spline. Finalmente, demostraremos el uso de splines periódicas.

Consejos sobre la VM

Después de que se complete la inicialización de la VM, haga clic en la esquina superior izquierda para cambiar a la pestaña Notebook para acceder a Jupyter Notebook y practicar.

A veces, es posible que tenga que esperar unos segundos para que Jupyter Notebook termine de cargar. La validación de operaciones no puede automatizarse debido a las limitaciones de Jupyter Notebook.

Si tiene problemas durante el aprendizaje, no dude en preguntar a Labby. Deje sus comentarios después de la sesión y lo resolveremos rápidamente para usted.

Preparar los datos

Comenzamos definiendo una función que pretendemos aproximar y preparando para graficarla.

def f(x):
    """Función a aproximar por interpolación polinómica."""
    return x * np.sin(x)

## rango completo que queremos graficar
x_plot = np.linspace(-1, 11, 100)

## Para hacerlo interesante, solo damos un subconjunto pequeño de puntos para entrenar.
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)

## crear versiones de 2D-array de estas matrices para alimentar a los transformadores
X_train = x_train[:, np.newaxis]
X_plot = x_plot[:, np.newaxis]

Interpolación con Características Polinómicas

Usaremos PolynomialFeatures para generar características polinómicas y ajustar un modelo de regresión con regularización L2 a los datos de entrenamiento. Luego graficaremos la función, los puntos de entrenamiento y la interpolación utilizando características polinómicas.

## graficar función
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="verdadero valor")

## graficar puntos de entrenamiento
ax.scatter(x_train, y_train, label="puntos de entrenamiento")

## características polinómicas
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"grado {degree}")

ax.legend(loc="lower center")
ax.set_ylim(-20, 10)
plt.show()

Interpolación con B-Spline

Usaremos SplineTransformer para generar funciones de base B-spline y ajustar un modelo de regresión con regularización L2 a los datos de entrenamiento. Luego graficaremos la función, los puntos de entrenamiento y la interpolación utilizando B-splines.

## B-spline con 4 + 3 - 1 = 6 funciones de base
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()

Graficando los Transformadores

Graficamos todas las columnas de ambos transformadores por separado para obtener más información sobre las bases de características generadas.

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"grado {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")

## graficar nudos de la spline
knots = splt.bsplines_[0].t
axes[1].vlines(knots[3:-3], ymin=0, ymax=0.8, linestyles="dashed")
plt.show()

Splines Periódicas

Demostramos el uso de splines periódicas utilizando el SplineTransformer y especificando manualmente los nudos. Ajustamos un modelo de regresión con regularización L2 a los datos de entrenamiento y graficamos la función, los puntos de entrenamiento y la interpolación utilizando splines periódicas.

def g(x):
    """Función a aproximar por interpolación con spline periódica."""
    return np.sin(x) - 0.7 * np.cos(x * 3)


y_train = g(x_train)

## Extender los datos de prueba hacia el futuro:
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="verdadero valor")
ax.scatter(x_train, y_train, label="puntos de entrenamiento")

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",
        ),
        "spline periódica",
    ),
]:
    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()

Resumen

En este laboratorio, aprendimos cómo aproximar una función con polinomios de un cierto grado utilizando regresión con regularización L2. Mostramos dos maneras diferentes de hacer esto dados n_samples de puntos unidimensionales x_i. Utilizamos la función make_pipeline para agregar características no lineales y demostramos cómo estos transformadores son adecuados para modelar efectos no lineales con un modelo lineal. Graficamos la función, los puntos de entrenamiento y la interpolación utilizando características polinómicas y B-splines. También graficamos todas las columnas de ambos transformadores por separado y mostramos los nudos de la spline. Finalmente, demostramos el uso de splines periódicas.