Regresión lineal en Python: predice precios con scikit-learn
Si alguna vez has querido adivinar cuánto va a costar algo a partir de otro dato, sin darte cuenta ya estabas pensando en regresión lineal. Hoy empezamos una serie de artículos sobre algoritmos de inteligencia artificial hechos en Python, y arrancamos por el más sencillo de todos.
Imagina que tienes una libreta donde anotaste los metros cuadrados de varias casas y lo que costó cada una. Si los pones en una gráfica, los puntos suben de izquierda a derecha: a más metros, más caro. La regresión lineal busca la línea que mejor pasa por en medio de todos esos puntos, y con esa línea puedes estimar el precio de una casa que todavía no conoces.
Cómo funciona
La línea se escribe como y = w·x + b. La x es lo que conoces (los metros), la y es lo que quieres adivinar (el precio), w es la pendiente, o sea cuánto sube el precio por cada metro extra, y b es el valor base cuando la casa mide cero.
El modelo prueba valores de w y b hasta quedarse con los que cometen menos error. Ese error es la diferencia entre lo que predice y lo que realmente costó, elevada al cuadrado para que los errores positivos y negativos no se cancelen.
Ejemplo: precio de casas con scikit-learn
Primero instalamos lo necesario con pip install scikit-learn numpy y después escribimos esto:
import numpy as np
from sklearn.linear_model import LinearRegression
from sklearn.metrics import mean_absolute_error, r2_score
# metros cuadrados y precio en miles de pesos
metros = np.array([[45], [60], [75], [90], [110], [130], [150], [180]])
precio = np.array([950, 1250, 1500, 1900, 2250, 2600, 3100, 3600])
modelo = LinearRegression()
modelo.fit(metros, precio)
print("Pendiente (w):", round(modelo.coef_[0], 2))
print("Base (b):", round(modelo.intercept_, 2))
print("Casa de 100 m2:", round(modelo.predict([[100]])[0], 1))
pred = modelo.predict(metros)
print("R2:", round(r2_score(precio, pred), 3))
print("Error promedio:", round(mean_absolute_error(precio, pred), 1))
Al ejecutarlo obtenemos una pendiente de 19.87, es decir, cada metro cuadrado suma casi 20 mil pesos, y para una casa de 100 m² el modelo estima 2,044 miles de pesos. El fit es la parte donde el modelo aprende, y el predict donde lo usamos. El R² sale en 0.998, lo que quiere decir que la línea explica casi toda la variación de los precios, y el error promedio es de unos 31 mil pesos. Ojo, son datos de ejemplo muy ordenados, con datos reales nunca te va a salir tan bonito.
Ejemplo: el gasto del súper
Esto lo hacemos todos sin darnos cuenta. Si en tu casa son 2 y gastan unos 880 pesos a la semana en el súper, y cuando vienen familiares el gasto sube más o menos parejo, ya tienes una regresión lineal en la cabeza. Con Python se ve así, ahora sin scikit-learn, solo con NumPy:
import numpy as np
personas = np.array([1, 2, 3, 4, 5, 6])
gasto = np.array([520, 880, 1260, 1590, 1980, 2300])
w, b = np.polyfit(personas, gasto, 1)
print("Cada persona extra cuesta:", round(w, 1))
print("Gasto estimado con 7 personas:", round(w * 7 + b))
Cada persona extra cuesta unos 358 pesos a la semana, y para 7 personas el modelo calcula 2,675 pesos. Es la misma línea, solo cambia lo que medimos.
Cuándo sí y cuándo no
La regresión lineal funciona bien cuando la relación entre los datos es más o menos recta. Si los puntos forman una curva, o tienes valores muy raros que se salen de todo (una mansión entre puras casitas), la línea se va a desviar y las predicciones van a fallar.
Finalizando
La regresión lineal es el punto de partida ideal porque se entiende a la primera y te sirve de referencia para comparar modelos más complicados. Si un algoritmo sofisticado no le gana a una simple línea, algo está mal.
Ejemplos para practicar: estimar la renta de un departamento según sus metros, calcular cuánta gasolina gasta tu carro según los kilómetros recorridos, o predecir las ventas de tu tienda según lo que inviertes en publicidad. En todos el patrón es el mismo, un número que depende de otro.
Nos leemos en el siguiente artículo, donde vemos qué pasa cuando la respuesta ya no es un número sino un sí o un no.