Sesión 2.2: Regresión y predicción
Primera parte
Segunda parte
Ejemplos
| Pregunta | Tipo |
|---|---|
| ¿Las becas aumentaron la asistencia escolar? | Explicación |
| ¿Qué estudiantes van a desertar? | Predicción |
| ¿La vacunación redujo la mortalidad? | Explicación |
| ¿Qué pacientes necesitan cuidados intensivos? | Predicción |
Ambos son valiosos! El ML aporta herramientas de predicción que complementan los métodos causales.
\[\min \sum_{i=1}^{n} (y_i - \hat{y}_i)^2\]
\[\min \sum_{i=1}^{n} (y_i - \hat{y}_i)^2 + \lambda \cdot \text{penalización}(\beta)\]
La intuición: un presupuesto para coeficientes
OLS puede asignar coeficientes tan grandes como quiera. Con muchas variables, esto genera sobreajuste.
Regularización impone un presupuesto: la suma total de los coeficientes no puede ser ilimitada. El modelo debe repartir un presupuesto finito entre todas las variables.
Presupuesto generoso (\(\lambda\) bajo): el modelo usa muchas variables, similar a OLS
Presupuesto ajustado (\(\lambda\) alto): el modelo solo gasta en las variables que más ayudan
\[\min \sum (y_i - \hat{y}_i)^2 + \lambda \sum |\beta_j|\]
LASSO en acción
Con 8 variables, λ = 0.1:
edad: 0.023
educacion_anios: 0.085
ingreso_hogar: 0.041
zona: 0.000 ← eliminada
genero: 0.000 ← eliminada
confianza_gobierno: 0.019
satisf_democracia: 0.052
percepcion_economia: 0.000 ← eliminada
LASSO seleccionó 5 de 8 variables.
Las demás fueron eliminadas
automáticamente.
\[\min \sum (y_i - \hat{y}_i)^2 + \lambda \sum \beta_j^2\]
Ridge en acción
Con 8 variables, λ = 0.1:
edad: 0.018
educacion_anios: 0.072
ingreso_hogar: 0.035
zona: 0.008 ← reducida, no eliminada
genero: 0.003 ← reducida, no eliminada
confianza_gobierno: 0.015
satisf_democracia: 0.044
percepcion_economia: 0.009 ← reducida, no eliminada
Ridge mantiene todas las variables
pero con coeficientes más pequeños.
\[\min \sum (y_i - \hat{y}_i)^2 + \lambda \left[ \alpha \sum |\beta_j| + (1-\alpha) \sum \beta_j^2 \right]\]
| LASSO | Ridge | Elastic Net | |
|---|---|---|---|
| Penalización | L1 (\(|\beta|\)) | L2 (\(\beta^2\)) | L1 + L2 |
| Selección | Sí | No | Sí |
| Correlación | Problemas | Bien | Bien |
| Hiperparámetros | \(\lambda\) | \(\lambda\) | \(\lambda\), \(\alpha\) |
Regla general:
Con tidymodels + glmnet:
# LASSO (mixture = 1)
modelo_lasso <- linear_reg(penalty = 0.1, mixture = 1) |>
set_engine("glmnet") |>
set_mode("regression")
# Ridge (mixture = 0)
modelo_ridge <- linear_reg(penalty = 0.1, mixture = 0) |>
set_engine("glmnet") |>
set_mode("regression")
# Elastic Net (mixture entre 0 y 1)
modelo_enet <- linear_reg(penalty = 0.1, mixture = 0.5) |>
set_engine("glmnet") |>
set_mode("regression")
# Ajustar cualquiera de ellos (misma sintaxis)
ajuste <- fit(modelo_lasso, satisfaccion_vida ~ ., data = datos_train)penalty = \(\lambda\) (fuerza de la penalización)mixture = \(\alpha\) (1 = LASSO, 0 = Ridge, entre 0 y 1 = Elastic Net)penalty y mixturezona = "urbana" → zona_urbana = 1, zona_rural = 0edad * educacion: el efecto de la educación cambia con la edad?log(ingreso) para relaciones no linealesedad^2 para capturar efectos cuadráticos (ej: participación política en forma de U por edad)Con recipes de tidymodels:
receta <- recipe(voto ~ ., data = datos_train) |>
# Convertir categóricas a dummies
step_dummy(all_nominal_predictors()) |>
# Normalizar numéricas (media = 0, sd = 1)
step_normalize(all_numeric_predictors()) |>
# Eliminar variables con varianza cero (constantes)
step_zv(all_predictors()) |>
# Crear interacciones
step_interact(terms = ~ edad:educacion_anios) |>
# Imputar valores faltantes con la mediana
step_impute_median(all_numeric_predictors()) |>
# Agrupar categorías poco frecuentes en "other"
step_other(religion, threshold = 0.05) |>
# Eliminar predictores altamente correlacionados (r > 0.9)
step_corr(all_numeric_predictors(), threshold = 0.9) |>
# Transformación logarítmica
step_log(ingreso, offset = 1) |>
# Términos polinómicos (ej: edad + edad²)
step_poly(edad, degree = 2)workflow()recipe y model se combinan en un workflow()Evaluación final con last_fit():
last_fit() ajusta con todo el train set y evalúa con el test set en un solo paso. Es la forma recomendada de obtener las métricas finales del modelo.
Estrategia práctica (3 pasos):
Consejo: tidymodels genera la grilla automáticamente con grid_regular(penalty(), levels = 30). No hace falta adivinar los valores 😉
# 1. Modelo con penalty a ajustar
# tune() = marcador: "no fijes este valor, búscalo con CV"
# mixture = 1 → LASSO puro (L1). Si fuera 0 → Ridge (L2)
modelo_lasso_tune <- linear_reg(penalty = tune(), mixture = 1) |>
set_engine("glmnet") |> # glmnet: paquete que implementa LASSO/Ridge
# 2. Grilla de valores candidatos de penalty (λ)
# range = c(-4, 0) → en escala log10: de 10^-4 = 0.0001 a 10^0 = 1
# levels = 30 → probar 30 valores espaciados uniformemente en ese rango
grilla_lambda <- grid_regular(penalty(range = c(-4, 0)), levels = 30)
# 3. Validación cruzada: dividir datos en 5 partes
folds <- vfold_cv(datos_train, v = 5)
# 4. Probar cada valor de λ con CV
resultados <- tune_grid(
modelo_lasso_tune, # modelo con tune()
satisfaccion_vida ~ ., # fórmula: predecir con todas las variables
resamples = folds, # usar los 5 folds
grid = grilla_lambda, # los 30 valores de λ a probar
metrics = metric_set(rmse, rsq) # métricas: error y R²
)
# 5. Visualizar: gráfico de RMSE vs. λ (curva en U)
autoplot(resultados)
# 6. Seleccionar el λ con menor RMSE promedio
mejor_lambda <- select_best(resultados, metric = "rmse")
modelo_final <- finalize_model(modelo_lasso_tune, mejor_lambda)λ mínimo (lambda.min)
En ciencias sociales, el λ 1SE suele preferirse por producir modelos más interpretables.
Elastic Net tiene dos hiperparámetros: penalty (λ) y mixture (α)
# Modelo con ambos a ajustar
modelo_enet_tune <- linear_reg(penalty = tune(), mixture = tune()) |>
set_engine("glmnet") |>
set_mode("regression")
# Grilla de combinaciones
grilla_enet <- grid_regular(
penalty(range = c(-4, 0)),
mixture(range = c(0, 1)), # 0 = Ridge, 1 = LASSO
levels = c(20, 5) # 20 valores de λ, 5 de α
)
# Ajustar (igual que antes)
resultados_enet <- tune_grid(
modelo_enet_tune,
satisfaccion_vida ~ .,
resamples = folds,
grid = grilla_enet,
metrics = metric_set(rmse)
)
# Ver mejores combinaciones
show_best(resultados_enet, metric = "rmse", n = 5)El problema:
Enfoque con LASSO:
Variables típicas seleccionadas:
Variable Coef LASSO
─────────────────────────────────
años_educacion_jefe 0.42 ***
material_piso 0.28 ***
acceso_agua_potable 0.22 ***
num_habitaciones 0.18 **
tiene_refrigerador 0.15 **
material_techo 0.11 *
tiene_vehiculo 0.09
zona_urbana 0.00 ← eliminada
genero_jefe 0.00 ← eliminada
LASSO identifica automáticamente qué variables realmente predicen la pobreza.
Pregunta de investigación:
¿Qué factores predicen la satisfacción con la democracia en América Latina? (datos simulados)
Enfoque:
Hallazgos típicos:
Comparación de modelos:
Modelo RMSE R²
──────────────────────────
OLS 1.82 0.31
LASSO 1.78 0.33
Ridge 1.80 0.32
Elastic Net 1.77 0.34
Random Forest 1.62 0.42
RF tiene mejor R², pero...
¿podemos interpretar el efecto
de cada variable?
El trade-off interpretabilidad-rendimiento es real. La elección depende del objetivo.
¿Cuándo es especialmente útil la regularización?
Ejemplos en ciencias sociales:
La regla del pulgar:
| Situación | Significado | Recomendación |
|---|---|---|
| \(n \gg p\) | Muchos datos, pocas variables | OLS probablemente está bien |
| \(n \approx p\) | Datos y variables similares | Regularización ayuda |
| \(n \ll p\) | Pocas observaciones, muchas variables | Regularización es necesaria (OLS no funciona) |
LASSO funciona incluso cuando \(p > n\), lo cual es imposible con OLS clásico.
| Criterio | LASSO/Ridge | Random Forest |
|---|---|---|
| Interpretabilidad | Alta (coeficientes) | Baja (importancia) |
| Relaciones no lineales | No | Sí |
| Interacciones | Manual | Automáticas |
| Selección de variables | Sí (LASSO) | No (pero da importancia) |
| Velocidad | Muy rápido | Moderado |
| Ajuste de hiperparámetros | 1-2 parámetros | Varios parámetros |
| Extrapolación | Lineal | No extrapola bien |
En la práctica, es útil probar ambos enfoques y comparar. La regularización es mejor cuando las relaciones son aproximadamente lineales y queremos interpretabilidad. RF es mejor cuando hay no linealidades e interacciones complejas.
¿Cómo leerlos?
step_normalize()), los coeficientes son directamente comparablesAtención: LASSO elige una variable entre un grupo correlacionado y descarta las demás. No significa que las eliminadas no importen, sino que son redundantes con la que quedó.
Extraer coeficientes en tidymodels:
# Resultado (ejemplo):
term estimate
─────────────────────────────
confianza_gobierno 0.38
percepcion_economia 0.31
educacion_anios 0.22
edad -0.14
desempleo_regional -0.09
Las variables con coeficiente = 0 (no mostradas) fueron descartadas por LASSO.
linear_reg() por logistic_reg():Ejemplo: predecir voto
¿Qué variables predicen si alguien vota o no? Con 40 predictores de una encuesta, LASSO logístico selecciona los que realmente importan:
Variable Coef
─────────────────────────────
edad 0.52
educacion_anios 0.34
interes_politica 0.41
confianza_partidos 0.28
ingreso_hogar 0.00 ← eliminada
genero 0.00 ← eliminada
satisf_servicios 0.00 ← eliminada
Misma lógica que antes: LASSO descarta las variables redundantes.
vfold_cv(datos, v = 5) en tidymodels hace esto automáticamentePasos de k-fold CV:
¿Por qué \(k\) = 5 o 10? Es un compromiso práctico: suficientes folds para una buena estimación sin gastar demasiado tiempo de cómputo.
5-fold CV ilustrado:
Fold 1: [VAL] [Train] [Train] [Train] [Train]
Fold 2: [Train] [VAL] [Train] [Train] [Train]
Fold 3: [Train] [Train] [VAL] [Train] [Train]
Fold 4: [Train] [Train] [Train] [VAL] [Train]
Fold 5: [Train] [Train] [Train] [Train] [VAL]
→ 5 estimaciones de error → promedio
En tidymodels:
Conceptos clave:
Cuándo usar cada método:
Nos vemos en el laboratorio! 🤓