Salta el contingut
 

Regressió polinòmica

Autor: Joan Puigcerver Ibáñez

Correu electrònic: j.puigcerveribanez@edu.gva.es

Llicència: CC BY-NC-SA 4.0

(Reconeixement - NoComercial - CompartirIgual) 🅭

Regressió polinòmica

La regressió polinòmica és un model de regressió que intenta ajustar les dades que no segueixen una relació lineal mitjançant un polinomi.

Un pàmetre important en la regressió polinòmica és el grau del polinomi, que determina el nombre de coeficients per cada variable independent que tindrà el model.

La fórmula general d'un polinomi de grau \(n\) per a una variable independent \(X_1\) és:

\[ Y = w_0 + w_1 X_1 + w_2 X_1^2 + \ldots + w_n X_1^n \]

on:

  • \(Y\) és la variable dependent (objectiu o target),
  • \(X_1\) és la variable independent (característica o feature),
  • \(w_0, w_1, w_2, \ldots, w_n\) són els coeficients o pesos del model.

Exemple de formula de grau 2

La fórmula d'un polinomi de grau 2 és amb una variable independent \(X_1\) és:

\[ Y = w_0 + w_1 X_1 + w_2 X_1^2 \]

En cas de tindre dues variables independents \(X_1\) i \(X_2\), la fórmula general d'un polinomi de grau \(n\) és:

\[ Y = w_0 + w_1 X_1 + w_2 X_2 + w_3 X_1^2 + w_4 X_1X_2 + w_5 X_2^2 + \ldots + w_n X_1^n + w_{n+1} X_1^{n-1}X_2 + \ldots + w_{2n} X_2^n \]

Exemple de formula de grau 2 amb dues variables

La fórmula d'un polinomi de grau 2 amb dues variables independents \(X_1\) i \(X_2\) és:

\[ Y = w_0 + w_1 X_1 + w_2 X_2 + w_3 X_1^2 + w_4 X_1X_2 + w_5 X_2^2 \]

L'objectiu de la regressió polinòmica és trobar els valors dels coeficients que millor s'ajusten a les dades.

Preparació de les dades

A partir del polinomi:

\[ Y = -100 - 5X + 5X^2 + 0.1X^3 \]

Anem a generar un conjunt de dades que s'ajusten a aquest polinomi amb una lleugera desviació.

import numpy as np
from sklearn.model_selection import train_test_split

def f(x):
    return -100 - 5*x + 5*np.power(x, 2) + 0.1*np.power(x, 3)

np.random.seed(42)
n_samples = 100

X = np.random.uniform(-50, 50, n_samples)
Y = f(X) + np.random.randn(n_samples)*1000
X = X.reshape(-1, 1) # Convertim X en una matriu de 1 columna

X_train, X_test, Y_train, Y_test = train_test_split(X, Y, test_size=0.2, random_state=42)
X_test, Y_test = zip(*sorted(zip(X_test, Y_test))) # Ordenem les dades de test per visualitzar-les correctament

Dades generades a partir del polinomi

Figura 1. Dades generades a partir del polinomi

Regressió lineal

Si intentem ajustar les dades amb un model de regressió lineal, obtenim un model incapaç de generalitzar les dades de manera correcta.

from sklearn.linear_model import LinearRegression
from sklearn.metrics import mean_squared_error
from sklearn.metrics import r2_score

model = LinearRegression()
model.fit(X_train, Y_train)

pred_Y = model.predict(X_test)

rmse = mean_squared_error(Y_test, pred_Y)
r2 = r2_score(Y_test, pred_Y)
print(f'RMSE linear: {rmse:.2f}')
print(f'R^2 linear: {r2:.2f}')
RMSE linear: 12671123.84
R^2 linear: 0.50

Regressió lineal

Figura 2. Regressió lineal

Model de regressió polinòmica

Els models de regressió polinòmica són capaços de trobar la relació no lineal entre les variables mitjançant un polinomi.

Utilitzant la llibreria scikit-learn podem crear un model de regressió polinòmica de manera senzilla.

Creació del model

Per crear un model de regressió polinòmica amb scikit-learn podem utilitzarem les següents classes i mètodes:

  • PolynomialFeatures: Classe que genera noves característiques polinòmiques donat un grau.
  • LinearRegression: Classe que implementa la regressió lineal.
  • make_pipeline: Funció que crea una seqüència de transformacions a un estimador.
from sklearn.preprocessing import PolynomialFeatures
from sklearn.pipeline import make_pipeline

degree = 3
polynomial_features = PolynomialFeatures(degree=degree, include_bias=False)
model = make_pipeline(polynomial_features, LinearRegression())

Entrenament del model

Per entrenar el model amb les dades, utilitzem el mètode fit de la classe LinearRegression.

model.fit(X_train, Y_train)

Coeficients del model

Una vegada s'ha entrenat el model, podem obtenir els coeficients del polinomi obtingut.

  • coef_: coeficients de les variables independents.
  • intercept_: terme independent de la recta.
print(f'Coeficients: {model.named_steps["linearregression"].coef_}')
print(f'Intercept: {model.named_steps["linearregression"].intercept_}')
Coeficients: [-1.63821771  5.24145621  0.09552926]
Intercept: -362.88402429981306
\[ Y = -100 - 5X + 5X^2 + 0.1X^3 \]
\[ Y = -93.54 - 5.88X + 5.00X^2 + 0.10X^3 \]

Predicció i avaluació amb el model

Una vegada entrenat, podem fer prediccions amb el model i avaluar-lo.

pred_Y = model.predict(X_test)

rmse = mean_squared_error(Y_test, pred_Y)
r2 = r2_score(Y_test, pred_Y)
print(f'RMSE polinòmica: {rmse:.2f}')
print(f'R^2 polinòmica: {r2:.2f}')
RMSE polinòmica: 642049.3
R2 polinòmica: 0.97

Visualització del model

Podem visualitzar el model de regressió lineal amb una gràfica.

plt.scatter(X_train, Y_train, color='blue')
plt.scatter(X_test, Y_test, color='orange')
plt.plot(X_test, pred_Y, color='red')
plt.show()

Model de regressió polinòmica

Figura 3. Model de regressió polinòmica

Codi font

regressio_polinomica.py
#!/usr/bin/env python

# --8<-- [start:dades]
import numpy as np
from sklearn.model_selection import train_test_split

def f(x):
    return -100 - 5*x + 5*np.power(x, 2) + 0.1*np.power(x, 3)

np.random.seed(42)
n_samples = 100

X = np.random.uniform(-50, 50, n_samples)
Y = f(X) + np.random.randn(n_samples)*1000
X = X.reshape(-1, 1) # Convertim X en una matriu de 1 columna

X_train, X_test, Y_train, Y_test = train_test_split(X, Y, test_size=0.2, random_state=42)
X_test, Y_test = zip(*sorted(zip(X_test, Y_test))) # Ordenem les dades de test per visualitzar-les correctament
# --8<-- [end:dades]

# --8<-- [start:plot_lineal]
import matplotlib.pyplot as plt

plt.scatter(X_train, Y_train, color='blue')
plt.scatter(X_test, Y_test, color='orange')
plt.show()
# --8<-- [end:plot_lineal]

# --8<-- [start:regressio_lineal]
from sklearn.linear_model import LinearRegression
from sklearn.metrics import mean_squared_error
from sklearn.metrics import r2_score

model = LinearRegression()
model.fit(X_train, Y_train)

pred_Y = model.predict(X_test)

rmse = mean_squared_error(Y_test, pred_Y)
r2 = r2_score(Y_test, pred_Y)
print(f'RMSE linear: {rmse:.2f}')
print(f'R^2 linear: {r2:.2f}')
# --8<-- [end:regressio_lineal]

# --8<-- [start:plot_lineal]
plt.scatter(X_train, Y_train, color='blue')
plt.scatter(X_test, Y_test, color='orange')
plt.plot(X_test, pred_Y, color='red')
plt.show()
# --8<-- [end:plot_lineal]

# --8<-- [start:model]
from sklearn.preprocessing import PolynomialFeatures
from sklearn.pipeline import make_pipeline

degree = 3
polynomial_features = PolynomialFeatures(degree=degree, include_bias=False)
model = make_pipeline(polynomial_features, LinearRegression())
# --8<-- [end:model]

# --8<-- [start:fit]
model.fit(X_train, Y_train)
# --8<-- [end:fit]


# --8<-- [start:params]
print(f'Coeficients: {model.named_steps["linearregression"].coef_}')
print(f'Intercept: {model.named_steps["linearregression"].intercept_}')
# --8<-- [end:params]

# --8<-- [start:predict]
pred_Y = model.predict(X_test)

rmse = mean_squared_error(Y_test, pred_Y)
r2 = r2_score(Y_test, pred_Y)
print(f'RMSE polinòmica: {rmse:.2f}')
print(f'R^2 polinòmica: {r2:.2f}')
# --8<-- [end:predict]

# --8<-- [start:plot_polinomica], pred_Y)
plt.scatter(X_train, Y_train, color='blue')
plt.scatter(X_test, Y_test, color='orange')
plt.plot(X_test, pred_Y, color='red')
plt.show()
# --8<-- [end:plot_polinomica]

Comentaris