Regresión Lineal con scikit-learn

La regresión lineal trata de explicar la relación entre dos o más variables continuas. En este artículo, veremos cómo construir una recta de regresión lineal, calcular R² y MSE utilizando la librería scikit-learn.


Bienvenidas/os!!, muchas gracias por visitarnos, si están comenzando en Python y este es el primer artículo al que entran en nuestro sitio, les recomendamos visitar Primeros Pasos.

ℹ️ Les recordamos que todos los ejemplos de códigos en nuestro sitio web van a encontrarlos en nuestro repositorio GitHub. Los códigos de este artículo los encontrarán en Linear-Regression_scikit-learn.ipynb.

En este artículo, vamos a comenzar realizando un simple repaso sobre el concepto de regresión lineal.

Luego explicaremos los pasos utilizando código Python para obtener una recta de regresión lineal con SciPy a partir de un conjunto de datos que nosotros mismos crearemos. Además de la recta, obtendremos parámetros estadísticos, tales como R² y p-value. Para finalizar, crearemos un gráfico con matplotlib para visualizar los resultados.



REGRESIÓN LINEAL

La regresión lineal simple consiste en generar un modelo de regresión, (ecuación de una recta), que permita explicar la relación lineal que existe entre dos variables, una de ellas independiente, y la restante, dependiente.

A la variable independiente o predictora se la conoce como X, mientras que a la variable dependiente o respuesta se la identifica como Y.

El modelo de regresión lineal simple se describe de acuerdo a la ecuación:

$$ Y = \beta_{0} + \beta_{1} x + \epsilon $$

Siendo β0 la ordenada en el origen, β1 la pendiente y ϵ el error aleatorio. Este último representa la diferencia entre el valor ajustado por la recta y el valor real. Recoge el efecto de todas aquellas variables que influyen en Y pero que no se incluyen en el modelo como predictores. Al error aleatorio también se le conoce como residuo.

Una recta de regresión puede emplearse para diferentes propósitos y dependiendo de ellos, es necesario satisfacer distintas condiciones. En caso de querer medir la relación lineal entre dos variables, la recta de regresión lo va a indicar de forma directa. Sin embargo, en caso de querer predecir el valor de una variable en función de la otra, no sólo se necesita calcular la recta, sino que además hay que asegurar que el modelo sea eficiente. Para ello se utilizan diferentes herramientas de las cuales mencionaremos:

  • R² (Coeficiente de Determinación)
  • MSE (Mean Squared Error)

R² (Coeficiente de Determinación)

En los modelos de regresión lineal simple el valor de se corresponde con el cuadrado del coeficiente de correlación de Pearson (r) entre X e Y.

describe la proporción de variabilidad observada en la variable dependiente explicada por el modelo y relativa a la variabilidad total.

Su valor está acotado entre 0 y 1. (Un valor de R²=1 significa un ajuste lineal perfecto, mientras que un valor de R²=0 indica la no representatividad del modelo lineal). En general, se toman valores de R² entre 0.7-1.0 , (- 0.7 and -1.0), como indicador de una fuerte relación lineal.

MSE (Mean Squared Error) - ECM (Error Cuadrático Medio)

El Error Cuadrático Medio (ECM) mide la cantidad de error en modelos estadísticos. A su vez, evalúa la diferencia cuadrática promedio entre los valores reales (Yi), y los predichos i) por el modelo.

Cuando MSE=0, el modelo no tiene error. A medida que aumenta el error del modelo, MSE aumenta su valor. El error cuadrático medio también se conoce como Mean Squared Deviation (MSD), Desviación Cuadrática Media (DCM) en español.

$$ MSE = \dfrac{\textstyle\sum_{i=1}^n (Y_{i} - \hat{Y}_{i})^{2}}{n} $$ donde:

  • Yi: valor observado.
  • Ŷi: valor pronosticado por el modelo.
  • n: número de muestras.

Elevar al cuadrado las diferencias elimina los valores negativos de las diferencias y asegura que el error cuadrático medio sea siempre mayor o igual a cero. Sólo un modelo perfecto sin error produce un MSE=0, lo que no ocurre en la práctica.

A su vez, elevar al cuadrado aumenta el impacto de valores muy alejados de la recta de regresión. El MSE penaliza desproporcionadamente los errores grandes con respecto a los errores más pequeños. Esta propiedad es importante cuando deseamos obtener un modelo con errores pequeños.



REGRESION LINEAL CON SCIKIT-LEARN

Luego de este breve repaso, vamos a continuar con nuestro objetivo, el cual consiste en obtener una recta de regresión lineal con scikit-learn.

Con scikit-learn, además de calcular m (β1) y b (β0), tenemos la opción de obtener y MSE, cosa que haremos.


IMPORTAR LIBRERIAS

import numpy as np
import pandas as pd

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

import matplotlib.pyplot as plt
import seaborn as sns
%matplotlib inline

Como siempre, lo primero que haremos es importar todas las librerías que utilizaremos en el notebook.


CREACIÓN Y VISUALIZACIÓN DE LOS DATOS

Para conseguir una recta de regresión lineal, vamos a necesitar un conjunto de datos. Con este fin, vamos a crear con Numpy 500 pares de puntos (x,y) que sigan una tendencia. Para ello, construiremos una recta con pendiente y ordenada al origen, pero también agregaremos valores aleatorios a cada par de puntos de dicha recta. (Es exactamente el mismo conjunto de datos que creamos en los artículos Regresión Lineal con NumPy y Regresión Lineal con SciPy).

En este caso, utilizaremos pandas y seaborn para poder elegir la cantidad de muestras, (pares x,y), que queremos graficar (Recordemos que los datos cuentan con 500 muestras en total). Para elegir este número, deberemos buscar en ##INPUTS y allí modificaremos la variable samples. Además, creamos las variables x e y para poder nombrar las columnas del dataframe como deseemos, y que aparezcan dichos nombres en el gráfico.

# Creamos el conjunto de datos para trabajar
x_data = np.linspace(0.0,10.0,500)      # Creamos 500 valores de x equidistantes entre 0 y 10.

np.random.seed(652)                     # seed obtiene números al azar, pero siempre elegirá los mismos en el mismo orden.
noise = np.random.randn(len(x_data))    # obtengo 500 números aleatorios ya predeterminados por seed.

y_data =  (0.5 * x_data ) + 5 + noise   # Obtenemos 500 valores de y que seguirán la tendencia de y=0.5x+5

#### INPUTS para pandas y grafico
x = 'x'
y = 'y'
samples = 200      # numero de muestras (pares x,y) a graficar

#### Lo convertimos en Pandas Dataframe para agregar versatilidad al gráfico 
x_df = pd.DataFrame(x_data,columns=[x])
y_df = pd.DataFrame(y_data,columns=[y])
my_df = pd.concat([x_df,y_df],axis=1)


#### Grafico
my_df.sample(n=samples).plot(kind='scatter',x=x,y=y)    

plt.xlabel(x, fontsize=14,fontweight="bold")
plt.ylabel(y, fontsize=14,fontweight="bold")
plt.title(f'DATOS ({samples} muestras)',fontsize=14,fontweight="bold")
plt.show()

OBTENCIÓN Y VISUALIZACIÓN DE LA RECTA DE REGRESIÓN LINEAL

sklearn.linear_model.LinearRegression().

LinearRegression() es una clase de la librería scikit-learn que ajusta un modelo lineal con coeficientes w = (w1, …, wp) para minimizar la suma residual de cuadrados entre los objetivos observados en el conjunto de datos y los objetivos predichos por la aproximación lineal.

ℹ️ Para más información sobre la clase LinearRegression() visiten https://scikit-learn.org/stable/modules/generated/sklearn.linear_model.LinearRegression.html .


Entrenamos el modelo y obtenemos m,b

Con esta clase, primero vamos a correr LinearRegression().fit(x,y) para ajustar el modelo y calcular:

  • m: llamado LinearRegression().coef_ en scikit-learn.
  • b: denominado LinearRegression().intercept_.
X = my_df[['x']]    
Y = my_df[['y']]
linreg = LinearRegression()

### Entreno el modelo
linreg.fit(X,Y)
print(f'm={float(linreg.coef_):.3f}\nb={float(linreg.intercept_):.5f}')
print(f'y = {float(linreg.coef_):.3f}x + {float(linreg.intercept_):2.3f}')

Calculamos R² y MSE

Luego de tener el modelo, utilizamos LinearRegression().predict(x) para predecir su comportamiento. (Lo que haremos es comparar el modelo vs. los datos reales, y así podremos calcular funciones métricas)

En esta oportunidad, calcularemos las funciones métricas y MSE.

ℹ️ Para mayor información sobre funciones métricas visiten https://scikit-learn.org/stable/modules/model_evaluation.html#regression-metrics .

my_df['Y_pred'] = linreg.predict(my_df[['x']])
mse = mean_squared_error(my_df['y'], my_df['Y_pred'])
r2 = r2_score(my_df['y'], my_df['Y_pred'])
print(f"MSE = {mse:.3f}")
print(f"R\u00b2 = {r2:.3f}")

Graficamos los datos originales junto con la recta de regresión lineal

Para finalizar, graficaremos en un mismo plot los datos originales y la recta de regresión lineal obtenida con scikit-learn.

Además, agregaremos un cuadro de texto o bbox dentro del área del gráfico con los valores de la recta, R² y MSE.

x=x_data

plt.figure(figsize=(9, 6))
plt.plot(x_data,y_data,'.')

plt.plot(x, float(linreg.coef_) * x + float(linreg.intercept_),
         'r', linewidth= 2)
#          label=f'y = {float(linreg.coef_):.3f}x + {float(linreg.intercept_):2.3f}')
plt.xlabel('x', fontsize=14,fontweight="bold")
plt.ylabel('y', fontsize=14,fontweight="bold")
plt.title(f'DATOS y RECTA DE REGRESIÓN LINEAL',fontsize=18,fontweight="bold")
plt.text(0, 10.9,f'y = {float(linreg.coef_):.3f}x + {float(linreg.intercept_):2.3f}\nMSE = {mse:.3f}\nR\u00b2 ={r2:.3f}',
         fontsize=14,
         bbox=dict(boxstyle="round",
                   ec=('#1F618D'),
                   fc=('#EBF5FB'),
                   ))
plt.show()

En resumen, creamos un conjunto de datos relacionados entre sí linealmente. Luego calculamos la recta de regresión lineal que mejor los representa utilizando scikit-learn. También calculamos y MSE. Para finalizar, graficamos los datos originales junto con dicha recta y sus métricas con matplotlib.

Les agradecemos su tiempo y esperamos fervientemente que hayan disfrutado este artículo. Si tienen alguna consulta, desean hacer algún comentario o sugerencia para mejorar el contenido, o simplemente indicarles qué les pareció este artículo, debajo pueden hacerlo.

Esperamos reencontrarlos en algún otro artículo del sitio. Hasta luego!


comments powered by Disqus