Interpolação Polinomial e por Splines

Beginner

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

Introdução

Neste laboratório, aprenderemos a aproximar uma função com polinómios até um determinado grau utilizando regressão de ridge. Apresentaremos duas formas diferentes de o fazer, dados n_samples de pontos 1D x_i:

  1. PolynomialFeatures: gera todos os monómios até um grau especificado. Isto fornece-nos a matriz de Vandermonde com n_samples linhas e degree + 1 colunas.
  2. SplineTransformer: gera funções de base B-spline. Uma função de base de uma B-spline é uma função polinomial por partes de grau degree que é não nula apenas entre degree+1 nós consecutivos.

Utilizaremos a função make_pipeline para adicionar características não lineares e mostrar como estes transformadores são adequados para modelar efeitos não lineares com um modelo linear. Desenvolveremos o gráfico da função, dos pontos de treino e da interpolação utilizando características polinomiais e B-splines. Também representaremos separadamente todas as colunas de ambos os transformadores e demonstraremos os nós da spline. Finalmente, demonstraremos o uso de splines periódicas.

Dicas de Máquina Virtual

Após o arranque da máquina virtual, clique no canto superior esquerdo para mudar para a aba Notebook para aceder ao Jupyter Notebook para a prática.

Por vezes, pode ser necessário esperar alguns segundos para o Jupyter Notebook terminar de carregar. A validação das operações não pode ser automatizada devido a limitações no Jupyter Notebook.

Se tiver problemas durante o aprendizado, não hesite em contactar o Labby. Forneça feedback após a sessão e resolveremos o problema rapidamente para si.

Preparar os Dados

Começamos por definir uma função que pretendemos aproximar e preparar o seu gráfico.

def f(x):
    """Função a ser aproximada por interpolação polinomial."""
    return x * np.sin(x)

## Intervalo completo que queremos representar graficamente
x_plot = np.linspace(-1, 11, 100)

## Para tornar mais interessante, apenas fornecemos um pequeno subconjunto de pontos para treino.
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)

## Criar versões de matrizes 2D destes arrays para alimentar os transformadores
X_train = x_train[:, np.newaxis]
X_plot = x_plot[:, np.newaxis]

Interpolação com Características Polinomiais

Utilizaremos PolynomialFeatures para gerar características polinomiais e ajustar um modelo de regressão de ridge aos dados de treino. Em seguida, representaremos graficamente a função, os pontos de treino e a interpolação utilizando características polinomiais.

## representar graficamente a função
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")

## representar graficamente os pontos de treino
ax.scatter(x_train, y_train, label="pontos de treino")

## características polinomiais
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"grau {degree}")

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

Interpolação com B-Splines

Usaremos SplineTransformer para gerar funções de base B-spline e ajustar um modelo de regressão de ridge aos dados de treino. Em seguida, representaremos graficamente a função, os pontos de treino e a interpolação usando B-splines.

## B-spline com 4 + 3 - 1 = 6 funções 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()

Representando os Transformadores

Representamos todas as colunas de ambos os transformadores separadamente para fornecer mais informações sobre as bases de características geradas.

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

## representar os nós do spline
knots = splt.bsplines_[0].t
axes[1].vlines(knots[3:-3], ymin=0, ymax=0.8, linestyles="dashed")
plt.show()

Splines Periódicas

Demonstramos o uso de splines periódicas utilizando o SplineTransformer e especificando manualmente os nós. Ajustamos um modelo de regressão de ridge aos dados de treino e representamos graficamente a função, os pontos de treino e a interpolação usando splines periódicas.

def g(x):
    """Função a ser aproximada por interpolação spline periódica."""
    return np.sin(x) - 0.7 * np.cos(x * 3)


y_train = g(x_train)

## Estender os dados de teste para o 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="verdade fundamental")
ax.scatter(x_train, y_train, label="pontos de treino")

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()

Resumo

Neste laboratório, aprendemos como aproximar uma função com polinómios até um determinado grau utilizando regressão de ridge. Mostramos duas formas diferentes de fazer isto, dados n_samples de pontos 1D x_i. Usámos a função make_pipeline para adicionar características não lineares e demonstramos como estes transformadores são adequados para modelar efeitos não lineares com um modelo linear. Representámos graficamente a função, os pontos de treino e a interpolação utilizando características polinomiais e B-splines. Também representámos separadamente todas as colunas de ambos os transformadores e mostramos os nós da spline. Finalmente, demonstramos o uso de splines periódicas.