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)\]
Elegir λ es moverse por el equilibrio sesgo-varianza
LASSO (L1, Tibshirani, 1996): suma de valores absolutos
\[\min \sum (y_i - \hat{y}_i)^2 + \lambda \sum |\beta_j|\]
Ridge (L2): suma de cuadrados
\[\min \sum (y_i - \hat{y}_i)^2 + \lambda \sum \beta_j^2\]
LASSO vs Ridge con λ = 0.1
LASSO Ridge
edad 0.023 0.018
educacion 0.085 0.072
ingreso 0.041 0.035
zona 0.000 0.008
genero 0.000 0.003
confianza_gob 0.019 0.015
satisf_democ 0.052 0.044
percepcion_econ 0.000 0.009
LASSO eliminó 3 variables;
Ridge mantuvo todas con
coeficientes pequeños
Con los coeficientes anteriores:
penalización(β): el tamaño de los coeficientes (sin λ)
LASSO: Σ|βⱼ| = |0.023|+|0.085|+...+0 = 0.220
Ridge: Σβⱼ² = 0.018²+0.072²+...+0.009² = 0.009
término que se suma al error = λ · penalización
(el mismo λ = 0.1, una sola vez)
LASSO: 0.1 · 0.220 = 0.022
Ridge: 0.1 · 0.009 = 0.0009
\[\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:
| Objetivo | Herramienta | Coeficientes |
|---|---|---|
| Explicar | OLS (MCO) | Insesgados, interpretables |
| Predecir | LASSO, Ridge, Elastic Net | Sesgados, no causales |
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 mixtureCrear, transformar o seleccionar variables para mejorar el modelo:
edad * educacion)log(ingreso), edad^2 para no linealidadesCon recipes de tidymodels:
# Los pasos más comunes (hay muchos más step_*: ver el enlace de arriba)
receta <- recipe(voto ~ ., data = datos_train) |>
step_impute_median(all_numeric_predictors()) |> # imputar faltantes
step_dummy(all_nominal_predictors()) |> # categóricas → dummies
step_normalize(all_numeric_predictors()) |> # media=0, sd=1
step_zv(all_predictors()) |> # quitar varianza cero
step_interact(terms = ~ edad:educacion_anios) # interacción edad×educaciónrecipe() no transforma nada todavía: guarda la lista de pasos para ejecutarla despuésprep() calcula con los datos de entrenamiento los valores que cada paso necesita: medianas para imputar, medias y desvíos para normalizarjuice() devuelve el conjunto de entrenamiento ya transformadobake() aplica esa misma receta a datos nuevos, con los valores aprendidos del entrenamientoworkflow()recipe y model se combinan en un workflow()# Combinar receta + modelo en un workflow
# (en los labs lo verán como wf_<modelo>:
# wf_lasso, wf_rf, etc.)
wf_lasso <- workflow() |>
add_recipe(receta) |>
add_model(modelo_lasso)
# Ajustar todo junto
ajuste <- fit(wf_lasso, data = datos_train)
# Predecir con datos nuevos
predicciones <- predict(ajuste,
new_data = datos_test)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
Es el fit() y el predict() de la izquierda en una sola llamada, pero sobre el split, no sobre un data frame: por eso el test se toca una sola vez
workflow() por dentro?workflow() empaqueta la receta y el modelo en un solo objetofit() o predict(), aplica la receta y después el modelo en el orden correcto, por sí soloUn objeto, todo el flujo:
receta + modelo
│
▼
workflow()
│
┌────┴─────┐
fit() last_fit()
│ │
▼ ▼
ajuste métricas
│ en test
▼
predict(datos nuevos)
add_recipe() y add_model() son las dos piezas; el workflow sabe aplicarlas en orden
Estrategia práctica (3 pasos):
Consejo: tidymodels genera la grilla automáticamente con grid_regular(penalty(), levels = 30). No hace falta adivinar los valores 😉
folds <- vfold_cv(datos_train, v = 5); después tune_grid() la usa por dentro# 1. Modelo con penalty a ajustar (tune() = "búscalo con CV")
# mixture = 1 → LASSO. Para Elastic Net: mixture = tune() también
modelo_lasso_tune <- linear_reg(penalty = tune(), mixture = 1) |> set_engine("glmnet") |> set_mode("regression")
# 2. Workflow (mismo patrón que antes, ahora con penalty pendiente)
wf_lasso <- workflow() |> add_recipe(receta) |> add_model(modelo_lasso_tune)
# 3. Grilla de valores candidatos de penalty (λ) en escala log10
grilla_lambda <- grid_regular(penalty(range = c(-4, 0)), levels = 30)
# 4. Validación cruzada con 5 folds
folds <- vfold_cv(datos_train, v = 5)
# 5. Probar cada λ con CV (ahora le pasamos el workflow)
resultados <- tune_grid(wf_lasso,
resamples = folds,
grid = grilla_lambda,
metrics = metric_set(rmse, rsq))
# 6. Seleccionar el mejor λ
mejor_lambda <- select_best(resultados, metric = "rmse")
# 7. Finalizar y evaluar en test (last_fit = fit en train + métricas en test)
resultado_final <- wf_lasso |>
finalize_workflow(mejor_lambda) |>
last_fit(split = datos_split,
metrics = metric_set(rmse, rsq))
collect_metrics(resultado_final)select_best() da el λ con menor RMSE. Veremos una alternativa más parsimoniosa más adelantemixture = tune() y agrega mixture(range = c(0, 1)) a la grilla con levels = c(20, 5) (20 de λ × 5 de α)tune_grid(): prueba los 30 valores de λ de la grillaselect_best(): mira esa tabla y elige el λ con el menor RMSE promedio entre foldsfinalize_workflow() + last_fit(): hasta acá el workflow tenía un hueco (penalty = tune()) y no se podía ajustarfinalize_workflow() escribe el λ ganador en ese hueco; recién ahí last_fit() puede reajustar con todo el train y evaluar una sola vez en el testEl λ se elige sin tocar el test:
resultados (rendimiento de
│ cada λ, vía CV)
│ select_best()
▼
mejor_lambda (un solo valor)
│ finalize_workflow()
│ + last_fit()
▼
resultado_final (métricas en test)
La grilla y la CV eligen λ; el test set entra recién en el paso 7, una sola vez, para la métrica final
λ mínimo (select_best)
En ciencias sociales, el λ 1SE suele preferirse por producir modelos más interpretables
Una regla práctica:
| 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) |
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
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
| Criterio | LASSO/Ridge/Elastic Net | Random Forest/Gradient Boosting |
|---|---|---|
| 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
Conceptos clave:
Cuándo usar cada método:
¡Nos vemos en el laboratorio! 🤓