Regresión Lineal: teoría y ejemplos en Python

La regresión lineal es una de las técnicas más usadas en Machine Learning. Su fortaleza estriba en su simplicidad e interpretabilidad. La regresión polinómica, como ya veremos, es una extensión de la regresión lineal.

Regresión Lineal – Teoría

La regresión lineal es una técnica paramétrica de machine learning. Con «paramétrica» queremos decir que incluso antes de mirar a los datos, ya sabemos cuántos parámetros (o coeficientes) vamos a necesitar.

En el caso que estemos usando una sola variable, x, sabemos que una línea necesita 2 parámetros. La fórmula para la regresión lineal con una sola variable x es:

y = wx + b

El aprendizaje consiste en encontrar cuáles son los mejores parámetros (coeficientes) para los datos que tengamos. Los mejores coeficientes serán los que minimicen alguna medida de error. Para la regresión lineal usaremos el error cuadrático medio.

Ejemplo de Regresión Lineal

Hemos usado una regresión lineal para encontrar los parámetros de la línea que minimiza el error de los datos que tenemos. El proceso de aprendizaje consiste en estimar los parámetros wb. Así nos queda que para estos datos, los mejores valores son: 

w= 0.0918 \\
b = 1.2859

así que nos queda:

y = 0.0918x + 1.2859

Podemos usar este modelo de regresión lineal para estimar cuáles serán los resultados para otros valores de x. Por ejemplo, si queremos saber el resultado para x = 5, usaremos el modelo anterior y veremos que el resultado es 1.7449:

y = 0.0918 \cdotp 5 + 1.2859 = 1.7449

Este es un ejemplo muy simple. En realidad, los problemas de machine learning tienen muchas más variables. Sin embargo, he escogido este ejemplo porque es muy fácil de visualizar, explicar y entender. Espero que la intuición de este ejemplo sirva para entender lo que está pasando cuando haya más variables.

Notación

Antes de explicar el método de los mínimos cuadrados para resolver regresiones lineales, tenemos que expandir la notación. Debemos tener en cuenta que normalmente, tendremos muchas variables.

Con una variable, la ecuación para la regresión lineal es:

y = wx + b

Por conveniencia, vamos a reescribir la ecuación anterior:

y = b + wx

Cuando tengamos un dato con N variables, llamaremos al dato X. También tenemos que expandir los parámetros W para que cada parámetro vaya con una variable:

X = [x_0, x_1, x_2, ..., x_N] \\
W = [w_0, w_1, w_2, ..., w_N]

Si hacemos que

x_0 = 1, w_0 = b

nos queda una expresión equivalente a la original. Podemos ver que:

y = b + wx = w_0 x_0 + w_1 x_1

Para el caso general, la ecuación lineal quedaría:

y = WX

usando el producto matricial. Si tienes la multiplicación de matrices un poco oxidada, la versión intuitiva sería:

y = w_0 x_0 + w_1 x_1 + w_2 x_2 + ... + w_N x_N

Formato de los datos

Para que la técnica de regresión lineal pueda aprender de nuestros datos, tenemos que proporcionar los resultados y en forma de vector de M elementos, y los datos de entrada X en forma de matrix. El convenio para la matriz es el siguiente:

  • M filas: cada fila es un dato (por ejemplo, un inmueble, si queremos predecir su valor de venta)
  • N columnas: cada columna es un atributo relevante (por ejemplo, cuántas habitaciones tiene, metros cuadrados, etc).

Aprendizaje: El método de los mínimos cuadrados

El proceso de aprendizaje consiste en averiguar qué parámetros W minimizan el error cuadrático medio entre los resultados reales y los estimados.

El método de los mínimos cuadrados proporciona una solución analítica. Es decir, nos da una fórmula para obtener la mejor estimación posible de W para los datos de entrada y resultados que hemos proporcionado. La fórmula es la siguiente:

\hat{W} = (X^T X)^{-1} X^T y

En la práctica hay librerías numéricas que calculan automáticamente la mejor estimación de W por nosotros. Ya veremos algún ejemplo práctico del cálculo de regresión lineal.

De momento, sólo quería indicar que dependiendo de la cantidad de datos y atributos, puede ser una operación costosa computacionalmente hablando. Fíjate que hay que transponer matrices, multiplicar matrices e invertir matrices. Todo ello muy costoso computacionalmente para grandes cantidades de datos.

Otras formas de resolver el problema de la regresión lineal

El método de los mínimos cuadrados no es la única forma de estimar los mejores parámetros W. También podemos utilizar métodos de optimización numérica tales como el gradiente descendiente.

El gradiente descendiente va a servir no sólo para resolver regresiones lineales y polinómicas sino que es también fundamental para el aprendizaje automático de redes neuronales y aprendizaje profundo.

Ejemplo del uso del método de los mínimos cuadrados

Carl Friedrich Gauss

Carl Friedrich Gauss

Carl Friedrich Gauss es famoso, entre otras muchas contribuciones, por la distribución Gaussiana o el método de los mínimos cuadrados para resolver regresiones lineales.

Cuentan que la primera aplicación del método de los mínimos cuadrados fue la determinación de la posición de Ceres. Ceres es un asteroide que se «perdió» a los 40 días de descubrirse. Realmente no se perdió, sino que al acercarse a la claridad del Sol, dejó de verse.

Varios científicos y astrónomos intentaron localizar Ceres. La única información que tenían eran los datos de su observación durante 40 días. Gauss fue el único capaz de predecir dónde se encontraría el asteroide Ceres cuando abandonó la parte del firmamento tan iluminada por el Sol. Para ello, Gauss usó el método de los mínimos cuadrados.

A finales de 1801 los astrónomos encontraron el asteroide Ceres exactamente donde Gauss predijo que estaría.

Regresión Lineal en Python 

Para hacer una regresión lineal en python, vamos a usar scikit-learn, que es una librería de python para aprendizaje automático. En particular, la clase LinearRegression implementa la funcionalidad descrita en la parte teórica de este artículo. Vamos a explicarlo con un ejemplo.

Datos de ejemplo

Primero vamos a generar unos datos que siguen una línea, y le añadimos ruido gaussiano. Para ello usaremos la librería de python NumPy. La fórmula que he usado para generar los datos es:

y = 0.1x + 1.25 + N(0, 0.2)

El código en python quedaría así:

import numpy as np #Librería numérica
import matplotlib.pyplot as plt # Para crear gráficos con matplotlib
%matplotlib inline # Si quieres hacer estos gráficos dentro de un jupyter notebook

from sklearn.linear_model import LinearRegression #Regresión Lineal con scikit-learn

def f(x):  # función f(x) = 0.1*x + 1.25 + 0.2*Ruido_Gaussiano
    np.random.seed(42) # para poder reproducirlo
    y = 0.1*x + 1.25 + 0.2*np.random.randn(x.shape[0])
    return y

x = np.arange(0, 20, 0.5) # generamos valores x de 0 a 20 en intervalos de 0.5
y = f(x) # calculamos y a partir de la función que hemos generado

# hacemos un gráfico de los datos que hemos generado
plt.scatter(x,y,label='data', color='blue')
plt.title('Datos');

Este código genera los datos que se ven en la siguiente imagen:

Datos de ejemplo para hacer una regresión lineal

Datos de ejemplo para hacer una regresión lineal: y = 0.1*x + 1.25 + N(0, 0.2)

Entrenando un modelo de Regresión Lineal en python

Para entrenar el modelo, simplemente tendremos que hacer uso de scikit-learn. El método fit se encarga de ajustar los parámetros de regresión lineal a los datos.

# Importamos la clase de Regresión Lineal de scikit-learn
from sklearn.linear_model import LinearRegression 

regresion_lineal = LinearRegression() # creamos una instancia de LinearRegression

# instruimos a la regresión lineal que aprenda de los datos (x,y)
regresion_lineal.fit(x.reshape(-1,1), y) 

# vemos los parámetros que ha estimado la regresión lineal
print('w = ' + str(regresion_lineal.coef_) + ', b = ' + str(regresion_lineal.intercept_))

# resultado: w = [0.09183522], b = 1.2858792525736682

Como vemos, la regresión lineal casi ha averiguado cómo hemos generado los datos:

  • Estima 0.092 en lugar de 0.1 para w 
  • Estima 1.286 en vez de 1.25 para b

Este pequeño error es normal debido a la cantidad de ruido gaussiano que hemos introducido y al hecho de que hay muy pocos datos. 

Prediciendo con Regresión Lineal en python

Una vez que tenemos entrenado el modelo de regresión lineal, podemos hacer predicciones usando el método predict de la clase LinearRegression. Por ejemplo, si quisiéramos saber qué valor de y corresponde para x=5 usamos este código.

# vamos a predicir y = regresion_lineal(5)
nuevo_x = np.array([5]) 
prediccion = regresion_lineal.predict(nuevo_x.reshape(-1,1))

print(prediccion)

# resultado: [1.7449]

Así vemos, que la estimación de la regresión lineal del modelo que acabamos de entrenar para x = 5 es y = 1.7449.

Evaluando la calidad de la regresión lineal

Vamos a evaluar la calidad del modelo aprendido usando solamente los datos de entrenamiento. Recuerda que en un problema real, hay que evaluar también la capacidad de generalización del modelo. Podemos evaluar la calidad del modelo midiendo el error cuadrático medio y el coeficiente de determinación R2.

Error Cuadrático Medio

# importamos el cálculo del error cuadrático medio (MSE)
from sklearn.metrics import mean_squared_error

# Predecimos los valores y para los datos usados en el entrenamiento
prediccion_entrenamiento = regresion_lineal.predict(x.reshape(-1,1))

# Calculamos el Error Cuadrático Medio (MSE = Mean Squared Error)
mse = mean_squared_error(y_true = y, y_pred = prediccion_entrenamiento)

# La raíz cuadrada del MSE es el RMSE
rmse = np.sqrt(mse)

print('Error Cuadrático Medio (MSE) = ' + str(mse))
print('Raíz del Error Cuadrático Medio (RMSE) = ' + str(rmse))

Nos da el siguiente resultado:

Error Cuadrático Medio (MSE) = 0.033
Raíz del Error Cuadrático Medio (RMSE) = 0.182

Coeficiente de determinación R2

El coeficiente de determinación R2 determina la calidad del modelo para replicar los resultados, y la proporción de variación de los resultados que puede explicarse por el modelo

Fuente: wikipedia

El rango de R2 está entre 0 y 1, siendo 1 lo mejor. Para medir el coeficiente de determinación R2 de la regresión lineal usaremos el método score.

# calculamos el coeficiente de determinación R2
r2 = regresion_lineal.score(x.reshape(-1,1), y)

print('Coeficiente de Determinación R2 = ' + str(r2))

Nos da el siguiente resultado, que es bastante bueno:

Coeficiente de Determinación R2 = 0.894359363768311

Visualización

Siempre que podamos, es bueno visualizar los resultados, para saber cómo se está comportando el modelo. Este ejemplo que estamos haciendo es muy simple, y por tanto, muy fácil de visualizar. La línea que el modelo ha aprendido siguiendo el método de los mínimos cuadrados aparece en el siguiente gráfico en rojo.

Resumen

En este artículo hemos hablado de la regresión lineal. Esta es la lista de los puntos que hemos cubierto:

  • matemáticas de regresión lineal con una variable
  • extensión de la notación para varias variables
  • el método de los mínimos cuadrados que Gauss nos proporcionó
  • cómo entrenar una regresión lineal en python
  • cómo hacer predicciones con una regresión lineal ya entrenada
  • evaluación con el error cuadrático medio, el coeficiente de determinación R2 y visualizando datos

Recursos

Suscríbete

19 comentarios en «Regresión Lineal: teoría y ejemplos en Python»

  1. Por favor me puede indicar como consigue los valores de w=0.0918 b=1.2859.
    Se que es con el programa, pero cual es su formulacion. Usted comenta: «En la práctica hay librerías numéricas que calculan automáticamente la mejor estimación de W por nosotros».

    Responder
  2. Como podría predecir la disponibilidad de una playa de estacionamiento teniendo en cuenta los ingresos y salidas? o se necesitarían mas datos?o no es posible?

    Responder
    • Si tienes los datos de ingresos y salidas de un parking … creo que podrías decir cuántas plazas de aparcamiento libre directamente. No necesitarías machine learning … o no te he entendido bien?

      Responder
      • Claro teniendo ambos datos ya podria tener el dato,pero queria realizar predicciones sobre la disponibilidad de las playas por fecha, hora teniendo los ingresos y salidas en base a un historico, no se si asi queda mas claro

        Responder
        • ahh, creo que ahora lo entiendo … lo que quieres hacer es predecir el futuro. Por ejemplo, cuántas plazas de aparcamiento estarán disponibles el martes de la semana que viene a las 18:30, no?

          Creo que con los datos que tienes tendrías lo que quieres predecir. También necesitarías en qué vas a basar tus predicciones. Algunas ideas pueden ser:

          • día del año
          • día del mes
          • hora
          • es ese día festivo?
          • previsión meteorológica para ese día
          • algún evento importante en esa fecha (competición deportiva, rebajas, vacaciones escolares)

          Seguramente puedas tener más cosas en cuenta si sabes qué tipo de aparcamiento es (centro comercial, playa, instalaciones deportivas, vía pública …)

          Espero que te ayude

          Responder
  3. Gracias Jose Martinez Heras, excelente tu articulo, quiero preguntarte como hago para estimar datos hidrológicos faltantes en una sola estación, he escuchado de modelos de Autorregresión (AR) y en Python con el paquete statsmodels pero no se como aplicarlo. de nuevo Gracias

    Responder
  4. No logro terminar de entender para que se utiliza la regresión lineal.
    Digamos que tengo los registros de varios años de las ventas de una tienda, viene la fecha, total de venta y total de venta de cada producto, qué datos podría utilizar para la regresión y que puedo predecir con estos datos? podría predecir que producto se venderá mas el próximo mes por ejemplo?

    Responder
    • Puedes usar regresión lineal cuando tu problema pueda ser explicado por una función. Por ejemplo, en los termómetros de antes, sabiendo cuánto se ha expandido el mercurio, podemos saber la temperatura. Las relaciones no son siempre tan simples, y la regresión linear sólo puede predecir relaciones que sean lineales.

      Para predecir qué producto se venderá más el próximo mes podrías tener en cuenta cómo ha ido evolucionando las ventas con respecto a lo normal, qué productos se compran a la vez, estacionalidad (por ejemplo, los helados son más de verano), etc. Puedes calcular características (features) que tengan esto en cuenta y también puedes combinarlo modelos basados en series temporales (ARIMA por ejemplo).

      Puede ser que la relación entre los datos de entrada y la predicción de ventas para cada producto no sea lineal y necesites probar con modelos de machine learning más potentes.

      Responder
  5. José Martínez un saludo!!

    ¿Me podrías por favor darme a conocer en este ejercicio de regresión lineal la parte del código que usas para obtener las línea roja?

    Muchas gracias

    Responder
    • Hola Jorge,

      La línea roja es una función lineal. Los parámetros los consigo de la regresión lineal después de que haya modelado los datos.

      La función lineal tiene la forma f(x) = wx + b

      En el código del ejemplo:
      – w = regresion_lineal.coef_
      – b = regresion_lineal.intercept_

      Responder
      • José un saludo!!

        Mira tu código para el ejercicio de regresión lineal lo veo fácil de interpretar, el código relacionado a los datos (puntos azules) me funcionó muy bien para un ejercicio de la universidad que estoy haciendo, donde nos piden; ajustar los datos a una línea recta empleando el método de los mínimos cuadrados, calcular la pendiente y la intersección, así como el error estándar y el coeficiente de correlación. Realizar una gráfica en donde se muestren los datos originales y la recta que ajusta. Esto según:
        x = [6] [7] [11] [15] [18] [21] [23] [29] [31] [37] [39]
        y = [29] [23] [29] [14] [21] [25] [7] [7] [13] [0] [3]
        Los datos (puntos azules) relacionados a estas dos listas salen muy bien.
        Con el código:
        w = regresion_lineal.coef_
        b = regresion_lineal.intercept_
        Lo datos salen muy bien:
        w = [-0.78832016], b = 32.530170620058264
        Coeficiente de Determinación R2 = 0.7467950396597056
        ¿Pero cómo hago para que la línea roja se imprima en forma recta en medio de los puntos azules, como si lo hace usted?
        Si esta solicitud le parece inapropiada para sus muy interesantes aportes, le pido disculpas y por favor olvídelo. Es sólo que veo que su aporte se acerca bastante a lo que debo dar solución a través de google colab, y no he podido con esa parte.

        Muchas gracias

        Responder
        • Hola Jorge,

          Para hacer la línea roja sólo tienes que usar matplotlib y pintar la predicción

          x = [-5, -4, …., 4, 5]
          pred = regresion_lineal.predict(x)
          plt.plot(x, pred)

          Responder
  6. Que tal Amigo.
    Muy buen articulo. Tengo una pregunta. En la función
    # función f(x) = 0.1*x + 1.25 + 0.2*Ruido_Gaussiano
    y = 0.1*x + 1.25 + 0.2*np.random.randn(x.shape[0])

    De donde obtienes el 0.2 ?
    Segun el codigo el 0.2 se multiplica por el numero aleatorio usando(40) que es el numero de valores.
    De donde obtienes esta definición del ruido_gaussiano?
    Gracias

    Responder
    • Hola Andrea,

      – el 0.2 no sale de ningún sitio, me lo he inventado para hacer el ejemplo

      – el ruido Gaussiano lo obtengo al obtener números aleatorios de una distribución normal. En numpy, random.randn produce números aleatorios de una distribución normal (o Gaussiana) con media 0 y desviación típica 1. Al multiplicarlo por 0.2 lo que hago a efectos prácticos es conseguir números aleatorios de una distribución Gaussiana con media 0 y desviación típica 0.2

      Puedes obtener más información aquí:
      https://es.wikipedia.org/wiki/Distribuci%C3%B3n_normal
      -https://numpy.org/devdocs/reference/random/generated/numpy.random.randn.html

      Responder

Deja un comentario