2 - ¿Por qué tidymodels?

Authors
Affiliation

Francisco Cardozo

Universidad de Miami

Edgar Ruiz

1 Motivación

tidymodels resuelve un problema recurrente: cada paquete de machine learning en R trae su propia sintaxis, estructuras de datos e interfaces de evaluación. Cuando combinamos múltiples algoritmos dentro del mismo proyecto, la fricción aumenta y el código se vuelve difícil de mantener.

2 Problemas de los pipelines tradicionales

  1. Interfaces heterogéneas: cada función (lm(), randomForest(), glmnet(), etc.) exige argumentos distintos y produce salidas no compatibles.
  2. Preprocesamiento ad hoc: transformaciones como imputaciones o creación de variables suelen vivir en scripts separados, lo que dificulta reproducir los pasos exactos.
  3. Evaluación inconsistente: las métricas pueden variar entre paquetes.
  4. Acoplamiento fuerte: cambiar de algoritmo implica reescribir gran parte del código.

Estos problemas crecen cuando se combinan múltiples modelos, se repite el proceso para distintos conjuntos de datos o se trabaja en equipo.

3 Principios de tidymodels

El ecosistema propone una gramática coherente basada en:

  • Tidy data: todas las estructuras están bien definidas.
  • Separación de responsabilidades: especificar el modelo (qué) es independiente del motor (cómo).
  • Flujos reproducibles: recetas (recipes) encapsulan el preprocesamiento y workflows lo combinan con el modelo.
  • Remuestreo y tuning integrado: paquetes como rsample, tune y yardstick comparten una API consistente.

El resultado es un código más declarativo, fácil de versionar y portable a distintos motores.

4 Algunos Paquetes del ecosistema tidymodels

Paquete Rol en el workflow
parsnip Define el modelo de forma abstracta.
recipes Describe el preprocesamiento paso a paso.
workflows Combina receta y modelo en un objeto.
rsample Maneja divisiones de datos y esquemas de validación cruzada.
tune Automatiza la búsqueda de hiperparámetros.
yardstick Calcula métricas.

Suma a esto vetiver para despliegue, stacks para ensamblados y tidypredict para puntuación en bases externas.

5 Caso práctico: de código artesanal a workflow

El siguiente ejemplo estima un modelo de regresión y agrega preprocesamiento. Primero, un enfoque manual:

Code
# Enfoque tradicional
library(dplyr)
library(caret)

modelo_lm <- lm(Sepal.Length ~ ., data = iris)
resumen <- summary(modelo_lm)
predicciones <- predict(modelo_lm, iris)
rmse_trad <- sqrt(mean((predicciones - iris$Sepal.Length)^2))

Con tidymodels logramos mayor organización y extensibilidad:

Code
library(tidymodels)
── Attaching packages ────────────────────────────────────── tidymodels 1.4.1 ──
✔ broom        1.0.10         ✔ recipes      1.3.1     
✔ dials        1.4.2          ✔ rsample      1.3.1     
✔ dplyr        1.1.4          ✔ tailor       0.1.0     
✔ ggplot2      4.0.0          ✔ tidyr        1.3.1     
✔ infer        1.0.9          ✔ tune         2.0.0     
✔ modeldata    1.5.1          ✔ workflows    1.3.0     
✔ parsnip      1.3.3.9000     ✔ workflowsets 1.1.1     
✔ purrr        1.2.0          ✔ yardstick    1.3.2     
── Conflicts ───────────────────────────────────────── tidymodels_conflicts() ──
✖ purrr::discard() masks scales::discard()
✖ dplyr::filter()  masks stats::filter()
✖ dplyr::lag()     masks stats::lag()
✖ recipes::step()  masks stats::step()
Code
tidymodels_prefer()

# 1. Dividir datos
datos_split <- initial_split(iris, prop = 0.8, strata = "Species")
datos_train <- training(datos_split)
datos_test <- testing(datos_split)

# 2. Receta de preprocesamiento
receta <- recipe(Sepal.Length ~ ., data = datos_train) |>
    step_dummy(all_nominal_predictors()) |>
    step_normalize(all_numeric_predictors())

# 3. Modelo y motor
modelo <- linear_reg() |>
    set_engine("lm")

# 4. Workflow completo
flujo <- workflow() |>
    add_recipe(receta) |>
    add_model(modelo)

ajuste <- fit(flujo, data = datos_train)

# 5. Evaluación coherente
predicciones <- predict(ajuste, datos_test) |>
    bind_cols(datos_test)

metricas <- metric_set(rmse, rsq)
metricas(predicciones, truth = Sepal.Length, estimate = .pred)
# A tibble: 2 × 3
  .metric .estimator .estimate
  <chr>   <chr>          <dbl>
1 rmse    standard       0.330
2 rsq     standard       0.870

Observa cómo cada paso queda encapsulado y se puede reutilizar en nuevos conjuntos de datos o motores (set_engine("glmnet"), set_engine("stan"), etc.) sin reescribir el resto del pipeline.

6 ¿Qué aporta frente a otras alternativas?

  • Coherencia: una vez que aprendes la sintaxis de parsnip y recipes, puedes aplicarla a cualquier modelo soportado.
  • Extensión: permite integrar motores propios o paquetes externos mediante set_engine().
  • Reproducibilidad: los objetos workflow y last_fit() guardan metadatos, recetas y métricas, lo que facilita auditorías o reportes.
  • Colaboración: el código es declarativo; resulta sencillo compartirlo en notebooks, APIs o pipelines.
Back to top