library(tidyverse)
censo <- read_csv("data/census.csv") |> select(-1) Tema 07 - Modelización con tidymodels
Ejercicio Práctico 2
Introducción
Datos
Usamos datos del Censo de EE.UU. con la siguiente información
| age | edad |
| workclass | tipo de trabajo del individuo |
| fnlwgt | peso en el censo (no relevante) |
| education | nivel educativo |
| education_1 | años de educación |
| marital_status | estado civil |
| occupation | profesión de la persona |
| relationship | relación con el principal miembro del hogar |
| race | origen racial de la persona |
| sex | género |
| capital_gain | ganancias de capital |
| capital_loss | pérdidas de capital |
| hours_per_week | horas trabajadas a la semana |
| native_country | país de origen |
| Income | renta mayor o menor de 50 mil dólares |
Análisis exploratorio de los datos
Aquí NO vamos a desarrollar explícitamente el análisis exploratorio de datos. Pero siempre debemos conocer las características de nuestros datos, incluidas la distribución de valores de las variables y las relaciones entre ellas. Además, deberíamos haber realizado un proceso de limpieza y transformación de los datos, en parte sugerido por este análisis exploratorio.
En este caso, convertimos las variables categóricas a factores y eliminamos las variables redundantes.
censo <- censo |>
mutate(across(where(is.character),~as.factor(.x)))Como única muestra menor del análisis exploratorio, mostramos aquí (como que no haríamos en un informe) la salida de datasummary_skim():
library(modelsummary)
datasummary_skim(censo)Notad que prodríamos agrupar algunas categorías aquí o hacerlo luego para considerar distintas especificaciones de los modelos o hacer ambas cosas, según el caso. También podéis apreciar que algunas variables tienen valores ausentes “implícitos”: están marcados como “?” y deberíamos como NA. Vamos a cambiarlos a valores ausentes explícitos; esto se consigue de forma sencilla para todas las variables con el siguiente código:
censo <- censo |>
mutate(across(everything(), ~ if_else(. == "?", NA, .)))Modelización
Paso 0: Partición en Entrenamiento y Prueba
- Usamos
initial_split()para generar el objeto que almacena las dos particiones
library(tidymodels)
set.seed(8697)
censoPart <- censo |> initial_split(prop = .8)Paso 1: Preparar los datos y Especificación
En este ejercicio, vamos a considerar modelos de regresión logística y de regresión logística regularizada mediante LASSO. Usaremos la misma especificación inicial en todos los casos: la categoría de renta va a depender de la raza, la edad (un polinomio de grado 6), horas de trabajo (un polinomio de grado 6), el género, la educación (education_1), ganancias de capital, pérdidas de capital, ocupación y estado civil; además, incluiremos interacciones de la raza y el género entre ellas y con el resto de variables.
En general, debería justificarse las variables incluidas (p.e., por los resultados del análisis exploratorio) y considerar variantes de las especificaciones (variables incluidas) para el caso de la regresión logística al menos. En el caso de LASSO, esto no es importante porque siempre podemos incluir la especificación más general y el propio algoritmo selecciona las variables a incluir.
Preparamos las recetas con la especificación para estos modelos. Nota: agrupamos las categorías minoritarias de estado civil, raza y ocupación en una categoría de “Otros” con un umbral (threshold) del 6%.
- Para regresión logística:
receta <- censoPart |> training() |>
recipe(income ~ race + age + hours_per_week +
sex + education_1 + capital_gain + capital_loss +
occupation + marital_status ) |>
step_naomit() |>
step_poly(age, degree = 6) |>
step_poly(hours_per_week, degree = 6) |>
step_other(marital_status, race, occupation, threshold = 0.06) |>
step_dummy(all_nominal(), -all_outcomes()) |>
step_interact(~ starts_with("race"):(starts_with("age") + starts_with("hours_per_week") +
starts_with("sex") + education_1 + capital_gain + capital_loss +
starts_with("occupation") + starts_with("marital_status"))) |>
step_interact(~ starts_with("sex"):(starts_with("age") + starts_with("hours_per_week")+
education_1 + capital_gain + capital_loss +
starts_with("occupation") + starts_with("marital_status")))- Para regresión logística regularizada mediante LASSO:
recetaReg <- censoPart |> training() |>
recipe(income ~ race + age + hours_per_week +
sex + education_1 + capital_gain + capital_loss +
occupation + marital_status ) |>
step_naomit() |>
step_scale(all_predictors(), -all_nominal()) |>
step_poly(age, degree = 6) |>
step_poly(hours_per_week, degree = 6) |>
step_other(marital_status, race, occupation, threshold = 0.06) |>
step_dummy(all_nominal(), -all_outcomes()) |>
step_interact(~ starts_with("race"):(starts_with("age") + starts_with("hours_per_week") +
starts_with("sex") + education_1 + capital_gain + capital_loss +
starts_with("occupation") + starts_with("marital_status"))) |>
step_interact(~ starts_with("sex"):(starts_with("age") + starts_with("hours_per_week")+
education_1 + capital_gain + capital_loss +
starts_with("occupation") + starts_with("marital_status")))- Podéis comprobar que nuestro modelo tiene muchas variables, es decir, muchos parámetros:
receta |> prep() |> bake(censoPart |> training()) |> dim()Vuestro ejercicio
- Definir los modelos y estimarlos, eligiendo adecuadamente los hiperparámetros en el caso de los modelos regularizados. Presentar los resultados de todos los modelos en una tabla. Nota: usad el ROC-AUC como para elegir los hiperparámetros.
- Evaluar los modelos y compararlos, considerando las métricas adecuadas (“accuracy”, ROC-AUC, “recall” y “specificity”).
- Usando todos los modelos, determinar si un individuo puede clasificarse como de renta alta (>50K) si es de raza blanca, tiene 49 años, trabaja 40 horas, es hombre, tiene 16 años de educación, no tiene ganancias ni pérdidas de capital, trabaja en ventas (“Sales”) y está separado. ¿Y si fuera una mujer de 32 años con el resto de características iguales? En ambos casos, ofrecer tanto la predicción de la clase como de la probabilidad de ser de renta alta. Comentar brevemente.
- Repetir los apartados anteriores imputando los valores ausentes con
step_impute_knn(). Comentar brevemente los resultados.
Entrega
Rellenad este FORMULARIO con vuestros datos y subid
vuestro archivo de .qmd
el resultado de renderizarlo: bien un archivo autocontenido .html (o .pdf o .docx) o bien un archivo .html y el directorio relacionado con el mismo nombre; en ambos casos, se recomienda comprimir todo para enviarlo.
IMPORTANTE: el nombre de los ficheros que subáis DEBE seguir el siguiente formato que incluye vuestro número de DNI: ej.,
Tema07ej2_123456789.qmd
Tema07ej2_123456789.zip