Regresión Múltiple
Aprende cómo funciona la regresión lineal múltiple, interpreta coeficientes, gestiona la multicolinealidad y construye un modelo en Python con scikit-learn.
La regresión lineal múltiple extiende la regresión lineal simple para usar dos o más variables independientes con el fin de predecir un objetivo continuo. En lugar de trazar una línea en dos dimensiones, el modelo ajusta un hiperplano a través de tantas dimensiones como variables haya. Comprender cómo interactúan los coeficientes — y cuándo pueden inducir a error — es la habilidad fundamental que enseña esta página.
Esta página cubre:
- La ecuación de regresión múltiple y qué significa cada coeficiente
- Cómo construir un pipeline completo con scikit-learn: cargar, preprocesar, entrenar, evaluar
- Por qué es importante el escalado de características y cómo hacerlo correctamente
- Cómo interpretar y comparar coeficientes escalados frente a no escalados
- Diagnóstico de multicolinealidad — el problema más frecuente en la regresión múltiple
- Análisis de residuos para verificar los supuestos del modelo
- Cuándo elegir la regresión múltiple y qué probar cuando no es suficiente
La Ecuación de Regresión Múltiple
La regresión lineal múltiple modela el objetivo y como una combinación lineal de n variables de entrada:
y = β₀ + β₁x₁ + β₂x₂ + ... + βₙxₙ + εβ₀— la intersección: el valor predicho deycuando todas las variables son ceroβ₁ … βₙ— los coeficientes: cuánto cambiayante un incremento de una unidad en cadaxᵢ, manteniendo constantes las demás variablesε— el término de error: la parte deyque el modelo no puede explicar
El algoritmo encuentra los coeficientes minimizando la suma de cuadrados de los residuos (mínimos cuadrados ordinarios):
SSR = Σ(yᵢ - ŷᵢ)²Esto tiene una solución cerrada exacta, por lo que LinearRegression de scikit-learn no necesita descenso de gradiente iterativo — el entrenamiento es casi instantáneo incluso en conjuntos de datos con cientos de miles de filas.
Diferencia con la Regresión Lineal Simple
La regresión lineal simple usa una sola variable. La regresión múltiple agrega más variables para que cada coeficiente capture el efecto parcial de esa variable — su impacto en el objetivo mientras las demás se mantienen constantes. Esto es más potente pero introduce nuevos riesgos, especialmente la multicolinealidad (ver Diagnóstico de Multicolinealidad).
El Conjunto de Datos
Los ejemplos a continuación utilizan el conjunto de datos California Housing incluido en scikit-learn. Registra estadísticas de viviendas a nivel de bloque censal para California en 1990, con 20.640 muestras y 8 variables.
import pandas as pd
from sklearn.datasets import fetch_california_housing
housing = fetch_california_housing()
df = pd.DataFrame(housing.data, columns=housing.feature_names)
df['MedHouseVal'] = housing.target # median house value in $100,000s
print(df.shape) # (20640, 9)
print(df.head())Las 8 variables de entrada son:
| Variable | Descripción |
|---|---|
MedInc | Ingreso mediano en el bloque (en decenas de miles de dólares) |
HouseAge | Edad mediana de las viviendas en el bloque |
AveRooms | Número promedio de habitaciones por hogar |
AveBedrms | Número promedio de dormitorios por hogar |
Population | Población del bloque |
AveOccup | Ocupación promedio por hogar |
Latitude | Latitud del bloque |
Longitude | Longitud del bloque |
El objetivo MedHouseVal es el valor mediano de las viviendas en unidades de $100.000, por lo que un valor de 2.0 representa $200.000.
Construcción del Modelo Paso a Paso
Paso 1 — Dividir los Datos
Siempre divide los datos antes de cualquier preprocesamiento. Ajustar un escalador con el conjunto de datos completo filtraría las estadísticas del conjunto de prueba al entrenamiento, dando una evaluación demasiado optimista. Consulta Train/Test Split para una explicación completa.
from sklearn.model_selection import train_test_split
X = df[housing.feature_names]
y = df['MedHouseVal']
X_train, X_test, y_train, y_test = train_test_split(
X, y, test_size=0.2, random_state=42
)
print(f"Training samples: {len(X_train)}") # 16512
print(f"Test samples: {len(X_test)}") # 4128Paso 2 — Escalar las Variables
Los coeficientes de la regresión múltiple reflejan las unidades de cada variable. MedInc se mide en decenas de miles de dólares; Population es un conteo absoluto que puede llegar a 35.000. Sin escalado, el coeficiente de Population será pequeño no porque la población sea poco importante, sino porque su unidad es pequeña.
StandardScaler transforma cada variable para tener media cero y desviación estándar unitaria, haciendo que las magnitudes de los coeficientes sean directamente comparables. Consulta Feature Scaling para más detalles sobre los escaladores disponibles.
from sklearn.preprocessing import StandardScaler
scaler = StandardScaler()
X_train_scaled = scaler.fit_transform(X_train) # fit ONLY on training data
X_test_scaled = scaler.transform(X_test) # apply the same transformationLa regla fundamental: usa fit_transform con los datos de entrenamiento y transform (sin ajuste) con los datos de prueba. Ajustar con los datos de prueba contaminaría la evaluación.
Paso 3 — Entrenar el Modelo
from sklearn.linear_model import LinearRegression
model = LinearRegression()
model.fit(X_train_scaled, y_train)LinearRegression.fit() resuelve el problema de OLS de forma analítica. No hay hiperparámetros que ajustar en la regresión múltiple estándar — lo que eliges es qué variables incluir.
Paso 4 — Evaluar el Modelo
import numpy as np
from sklearn.metrics import mean_squared_error, r2_score
y_pred = model.predict(X_test_scaled)
mse = mean_squared_error(y_test, y_pred)
rmse = np.sqrt(mse)
r2 = r2_score(y_test, y_pred)
print(f"Mean Squared Error: {mse:.4f}")
print(f"Root Mean Squared Error: {rmse:.4f} (±${rmse * 100_000:,.0f})")
print(f"R-squared: {r2:.4f}")Salida esperada:
Mean Squared Error: 0.5559
Root Mean Squared Error: 0.7456 (±$74,558)
R-squared: 0.5758Qué significan las métricas:
- MSE (Error Cuadrático Medio) — promedio de las diferencias al cuadrado entre predicciones y valores reales. Elevar al cuadrado penaliza los errores grandes más que los pequeños. Las unidades son el cuadrado del objetivo ($100.000s²), por lo que es difícil de interpretar directamente.
- RMSE (Raíz del Error Cuadrático Medio) — la raíz cuadrada del MSE, en las mismas unidades que el objetivo. Un RMSE de 0,75 significa que las predicciones del modelo se desvían aproximadamente $75.000 en promedio.
- R² (coeficiente de determinación) — la fracción de varianza en el objetivo que explica el modelo. Un R² de 0,58 significa que el modelo captura el 58% de la variación en los precios de las viviendas. Los valores van de 0 (no mejor que predecir la media) a 1 (predicciones perfectas). Un R² negativo es posible si el modelo es peor que la media — es una señal clara de que algo está mal.
Un R² de ~0,58 es típico para este conjunto de datos con regresión lineal estándar. La relación entre los precios de las viviendas y estas variables es parcialmente no lineal e implica agrupaciones geográficas que un hiperplano no puede capturar bien. Algoritmos como los árboles con gradient boosting alcanzan habitualmente 0,80 o más en este conjunto de datos.
Paso 5 — Inspeccionar los Coeficientes
Tras el escalado, las magnitudes de los coeficientes son directamente comparables — muestran qué variables influyen más fuertemente en la predicción:
coef_df = pd.DataFrame({
'Feature': housing.feature_names,
'Coefficient': model.coef_
}).sort_values('Coefficient', key=abs, ascending=False)
print(coef_df.to_string(index=False))
print(f"\nIntercept: {model.intercept_:.4f}")Salida esperada:
Feature Coefficient
Latitude -0.8969
Longitude -0.8698
MedInc 0.8544
AveBedrms 0.3393
AveRooms -0.2944
HouseAge 0.1225
AveOccup -0.0408
Population -0.0023
Intercept: 2.0719Lectura de los coeficientes tras el escalado estándar:
MedInc = 0,854— el predictor individual más potente. Un incremento de una desviación estándar en el ingreso mediano predice un aumento de $85.400 en el valor de la vivienda, manteniendo todo lo demás constante.Latitude = -0,897yLongitude = -0,869— el modelo ha aprendido que los bloques censales más al norte y más al este tienden a ser más baratos. Sin embargo, estas dos variables geográficas están muy correlacionadas (r = -0,93), lo que puede hacer que sus coeficientes individuales sean inestables (ver Diagnóstico de Multicolinealidad).AveBedrms = +0,339frente aAveRooms = -0,294— tienen signos opuestos aunque más habitaciones y más dormitorios generalmente implican casas más grandes y caras. Esta es una señal clásica de multicolinealidad:AveRoomsyAveBedrmsestán correlacionadas (r = 0,85), por lo que sus coeficientes se compensan mutuamente. No los interpretes por separado.Population = -0,002— muy cercano a cero tras el escalado. La población del bloque tiene un poder predictivo mínimo una vez que se tienen en cuenta las demás variables.
La intersección (2,07) es el valor predicho de MedHouseVal cuando todas las variables escaladas son cero — es decir, cuando todas las variables están en su media del conjunto de entrenamiento. Es igual a la media de los objetivos de entrenamiento y no tiene un significado directo más allá de eso.
Paso 6 — Realizar Predicciones con Nuevos Datos
# A new census block: high income, older house, San Francisco Bay Area
new_block = pd.DataFrame([[8.0, 41.0, 6.0, 1.0, 322, 2.5, 37.88, -122.23]],
columns=housing.feature_names)
new_block_scaled = scaler.transform(new_block)
prediction = model.predict(new_block_scaled)
print(f"Predicted median house value: ${prediction[0] * 100_000:,.0f}")Salida esperada:
Predicted median house value: $410,895El escalador debe ser el mismo escalador ajustado con los datos de entrenamiento. Nunca vuelvas a ajustar el escalador con los nuevos datos — eso desplazaría las entradas respecto a lo que el modelo aprendió.
Diagnóstico de Multicolinealidad
La multicolinealidad ocurre cuando dos o más variables independientes están muy correlacionadas entre sí. No impide que el modelo haga predicciones precisas, pero hace que los coeficientes individuales sean poco fiables y difíciles de interpretar. Los coeficientes pueden volverse grandes, cambiar de signo o volverse estadísticamente insignificantes incluso para variables genuinamente importantes.
Verificación con una Matriz de Correlación
import matplotlib
matplotlib.use('Agg')
import matplotlib.pyplot as plt
corr = df[housing.feature_names].corr()
print(corr.round(2))Pares clave a considerar:
| Par de variables | Correlación | Preocupación |
|---|---|---|
AveRooms / AveBedrms | 0,85 | Alta — los coeficientes se compensan mutuamente |
Latitude / Longitude | -0,93 | Muy alta — movimiento geográfico conjunto |
MedInc / MedHouseVal (objetivo) | 0,69 | Buen predictor, no es un problema de colinealidad |
Una correlación superior a 0,80 entre dos variables es una señal de advertencia. Cuando la detectes, considera:
- Eliminar una de las variables correlacionadas. Si
AveRoomsyAveBedrmsestán ambas en el modelo, intenta eliminarAveBedrmsy comprueba si el rendimiento predictivo cambia significativamente. - Combinarlas. Crea una variable derivada (p. ej.,
rooms_per_bedroom = AveRooms / AveBedrms) que capture la relación sin redundancia. - Usar un modelo regularizado. La regresión Ridge añade una penalización L2 que acerca los coeficientes correlacionados entre sí, estabilizándolos. Lasso (L1) puede eliminar completamente las variables redundantes.
Análisis de Residuos
Un residuo es la diferencia entre un valor real y la predicción del modelo: residual = y_actual - y_predicted. Graficar los residuos revela si los supuestos del modelo se cumplen.
residuals = y_test - y_pred
print(f"Mean of residuals: {residuals.mean():.4f}") # should be close to 0
print(f"Std of residuals: {residuals.std():.4f}")Salida esperada:
Mean of residuals: 0.0035
Std of residuals: 0.7457La media está cerca de cero — señal de que el modelo es imparcial en promedio. Pero la desviación estándar de 0,75 (±$75.000) muestra una dispersión considerable.
import matplotlib
matplotlib.use('Agg')
import matplotlib.pyplot as plt
fig, axes = plt.subplots(1, 2, figsize=(12, 4))
# Predicted vs Actual
axes[0].scatter(y_test, y_pred, alpha=0.2, s=8)
axes[0].plot([0, 5], [0, 5], 'r--')
axes[0].set_xlabel('Actual')
axes[0].set_ylabel('Predicted')
axes[0].set_title('Predicted vs Actual')
# Residuals vs Predicted
axes[1].scatter(y_pred, residuals, alpha=0.2, s=8)
axes[1].axhline(0, color='r', linestyle='--')
axes[1].set_xlabel('Predicted')
axes[1].set_ylabel('Residual')
axes[1].set_title('Residuals vs Predicted')
plt.tight_layout()
plt.savefig('residuals.png', dpi=120)
print("Saved residuals.png")Qué buscar:
- Predicho vs Real — idealmente, los puntos caen sobre la diagonal. Una desviación sistemática de la diagonal (una curva, o un aplanamiento en valores altos) indica que el supuesto lineal es incorrecto para parte del rango.
- Residuos vs Predicho — idealmente, los residuos se dispersan aleatoriamente alrededor de cero en todos los niveles de predicción. Una forma de embudo (mayor dispersión en predicciones más altas) indica heterocedasticidad — el error del modelo no es constante, lo que puede hacer que las estimaciones de intervalos sean poco fiables.
- Agrupaciones — grupos distintos en el gráfico de residuos pueden revelar que el conjunto de datos contiene subpoblaciones (p. ej., urbano vs rural) que justifican modelos separados o variables adicionales.
Pipeline Completo
A continuación se presenta todo lo anterior como un único script ejecutable:
import numpy as np
import pandas as pd
from sklearn.datasets import fetch_california_housing
from sklearn.linear_model import LinearRegression
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
from sklearn.metrics import mean_squared_error, r2_score
# 1. Load data
housing = fetch_california_housing()
df = pd.DataFrame(housing.data, columns=housing.feature_names)
df['MedHouseVal'] = housing.target
# 2. Split — before any preprocessing
X = df[housing.feature_names]
y = df['MedHouseVal']
X_train, X_test, y_train, y_test = train_test_split(
X, y, test_size=0.2, random_state=42
)
# 3. Scale
scaler = StandardScaler()
X_train_scaled = scaler.fit_transform(X_train)
X_test_scaled = scaler.transform(X_test)
# 4. Train
model = LinearRegression()
model.fit(X_train_scaled, y_train)
# 5. Evaluate
y_pred = model.predict(X_test_scaled)
rmse = np.sqrt(mean_squared_error(y_test, y_pred))
r2 = r2_score(y_test, y_pred)
print(f"RMSE: {rmse:.4f}")
print(f"R²: {r2:.4f}")
# 6. Coefficients (most important first)
coef_df = pd.DataFrame({
'Feature': housing.feature_names,
'Coefficient': model.coef_
}).sort_values('Coefficient', key=abs, ascending=False)
print(coef_df.to_string(index=False))Cuándo Usar la Regresión Múltiple
La regresión múltiple es una buena primera opción cuando:
- La relación entre cada variable y el objetivo es aproximadamente lineal
- La interpretabilidad importa — cada coeficiente tiene un significado claro
- Quieres una línea base rápida antes de probar modelos más complejos
- Tienes suficientes muestras en relación con el número de variables (una regla aproximada: al menos 10–20 observaciones por variable)
Considera alternativas cuando:
| Situación | Alternativa |
|---|---|
| Relaciones no lineales entre variables y objetivo | Polynomial Regression |
| Muchas variables, riesgo de sobreajuste | Ridge o Lasso (modelos lineales regularizados) |
| El objetivo es una categoría, no un número | Logistic Regression |
| Interacciones complejas y no linealidad | Árboles con gradient boosting o bosques aleatorios |
Errores Comunes
Ajustar el escalador con todos los datos antes de dividir. Esto filtra la media y la varianza del conjunto de prueba al entrenamiento. Siempre divide primero, luego ajusta el escalador solo con la porción de entrenamiento.
Creer que agregar más variables siempre ayuda. Agregar variables irrelevantes o redundantes puede reducir la interpretabilidad, introducir multicolinealidad y perjudicar la generalización. Usa el conocimiento del dominio o una técnica de selección de variables para elegirlas deliberadamente.
Confiar en los coeficientes cuando las variables están correlacionadas. Cuando AveRooms y AveBedrms están ambas en el modelo, ninguno de los coeficientes refleja de forma fiable el efecto real de esa variable. Revisa la matriz de correlación antes de interpretar los coeficientes individuales.
Ignorar los gráficos de residuos. Un R² de 0,58 parece razonable en papel, pero los patrones de residuos pueden revelar que el modelo es sistemáticamente incorrecto para propiedades de alto valor o para regiones geográficas específicas.
Extrapolar más allá del rango de entrenamiento. Un modelo lineal entrenado en casas con precios entre $50.000 y $500.000 no debería usarse para predecir propiedades de $5.000.000. Verifica que las nuevas entradas estén dentro del rango observado durante el entrenamiento.
Próximos Pasos
- Linear Regression — la base: la regresión simple (con una variable) y el método OLS explicados en detalle
- Polynomial Regression — extiende el modelo lineal para capturar curvas añadiendo términos polinómicos
- Feature Scaling — análisis profundo de StandardScaler, MinMaxScaler y RobustScaler
- Train/Test Split — por qué la división correcta es fundamental y cómo hacerla sin filtrar datos
- Cross-Validation — una alternativa más robusta a una única división entrenamiento/prueba