--- title: "Getting Started with tidylearn" output: rmarkdown::html_vignette vignette: > %\VignetteIndexEntry{Getting Started with tidylearn} %\VignetteEngine{knitr::rmarkdown} %\VignetteEncoding{UTF-8} --- ```{r, include = FALSE} knitr::opts_chunk$set( collapse = TRUE, comment = "#>", fig.width = 7, fig.height = 5 ) ``` ## Introduction Every machine learning package in R has its own API and its own output format. tidylearn puts one signature over 20 of them: `tl_model()` picks the underlying package from the `method` you name, and whatever comes back is a tibble or a ggplot2 object. The algorithms are untouched. glmnet, randomForest, xgboost, e1071, cluster and dbscan do the fitting, and `model$fit` hands you the object they returned — `model$fit$model` for an unsupervised method, whose `$fit` is the list of tidied components — so nothing here closes off the package underneath. This vignette covers the shape of a workflow end to end. The articles listed at the bottom go deeper on each step. ## Installation ```{r, eval = FALSE} # From CRAN install.packages("tidylearn") # Development version # devtools::install_github("ces0491/tidylearn") # nolint ``` ```{r setup} library(tidylearn) library(dplyr) ``` ## The Unified Interface The core of tidylearn is the `tl_model()` function, which dispatches to the appropriate underlying package based on the method you specify. The wrapped packages include stats, glmnet, randomForest, xgboost, gbm, e1071, nnet, rpart, cluster, and dbscan. ### Supervised Learning #### Classification Logistic regression handles two-class problems, so we take a binary subset of iris here. For three or more classes use `"tree"`, `"forest"`, `"svm"` or `"nn"`. ```{r} # versicolor and virginica overlap, so this is a real classification # problem -- setosa is linearly separable from the other two, which makes # logistic regression fail to converge iris_binary <- iris %>% filter(Species %in% c("versicolor", "virginica")) %>% mutate(Species = droplevels(Species)) model_logistic <- tl_model(iris_binary, Species ~ ., method = "logistic") print(model_logistic) ``` Predictions come back as a tibble with a `.pred` column. What `.pred` contains depends on `type`: `"class"` gives the predicted label, `"prob"` gives one column per class. ```{r} # Predicted class labels predictions <- predict(model_logistic, type = "class") head(predictions) ``` ```{r} # Class probabilities head(predict(model_logistic, type = "prob")) ``` Note that the default `type = "response"` means different things across methods — probabilities for logistic regression, class labels for trees and forests. Ask for `type = "class"` explicitly when you want labels, or let `tl_evaluate()` handle it: ```{r} tl_evaluate(model_logistic, metrics = c("accuracy", "f1")) ``` #### Regression ```{r} # Regression with linear model model_linear <- tl_model(mtcars, mpg ~ wt + hp, method = "linear") print(model_linear) ``` ```{r} # Predictions predictions_reg <- predict(model_linear) head(predictions_reg) ``` ### Unsupervised Learning #### Dimensionality Reduction ```{r} # Principal Component Analysis model_pca <- tl_model(iris[, 1:4], method = "pca") print(model_pca) ``` ```{r} # Transform data transformed <- predict(model_pca) head(transformed) ``` #### Clustering ```{r} # K-means clustering model_kmeans <- tl_model(iris[, 1:4], method = "kmeans", k = 3) print(model_kmeans) ``` ```{r} # Get cluster assignments clusters <- model_kmeans$fit$clusters head(clusters) ``` ```{r} # Compare with actual species table(clusters$cluster, iris$Species) ``` ## Data Preprocessing `tl_prepare_data()` handles imputation, scaling and encoding in one call, and records what it did so the same transformation can be replayed on new data: ```{r} # Prepare data with multiple preprocessing steps processed <- tl_prepare_data( iris, Species ~ ., impute_method = "mean", scale_method = "standardize", encode_categorical = FALSE ) ``` ```{r} # Check preprocessing steps applied names(processed$preprocessing_steps) ``` ```{r} # Use processed data for modeling model_processed <- tl_model(processed$data, Species ~ ., method = "forest") ``` ## Train-Test Splitting ```{r} # Simple random split split <- tl_split(iris, prop = 0.7, seed = 123) # Train model (three species, so a multiclass-capable method) model_train <- tl_model(split$train, Species ~ ., method = "forest") # Test predictions predictions_test <- predict(model_train, new_data = split$test) head(predictions_test) ``` ```{r} # Stratified split (maintains class proportions) split_strat <- tl_split(iris, prop = 0.7, stratify = "Species", seed = 123) # Check proportions are maintained prop.table(table(split_strat$train$Species)) prop.table(table(split_strat$test$Species)) prop.table(table(iris$Species)) ``` ## Wrapped Packages tidylearn provides a unified interface to these established R packages: ### Supervised Methods | Method | Underlying Package | Function Called | |--------|-------------------|-----------------| | `"linear"` | stats | `lm()` | | `"polynomial"` | stats | `lm()` with `poly()` | | `"logistic"` | stats | `glm(..., family = binomial)` | | `"ridge"`, `"lasso"`, `"elastic_net"` | glmnet | `glmnet()` | | `"tree"` | rpart | `rpart()` | | `"forest"` | randomForest | `randomForest()` | | `"boost"` | gbm | `gbm()` | | `"xgboost"` | xgboost | `xgb.train()` | | `"svm"` | e1071 | `svm()` | | `"nn"` | nnet | `nnet()` | | `"deep"` | keras | `keras_model_sequential()` | ### Unsupervised Methods | Method | Underlying Package | Function Called | |--------|-------------------|-----------------| | `"pca"` | stats | `prcomp()` | | `"mds"` | stats, MASS, smacof | `cmdscale()`, `isoMDS()`, etc. | | `"kmeans"` | stats | `kmeans()` | | `"pam"` | cluster | `pam()` | | `"clara"` | cluster | `clara()` | | `"hclust"` | stats | `hclust()` | | `"dbscan"` | dbscan | `dbscan()` | ### Accessing the Underlying Model The raw model from the underlying package is reachable through `$fit`: ```{r} # Example: Access the raw randomForest object model_forest <- tl_model(iris, Species ~ ., method = "forest") class(model_forest$fit) # This is the randomForest object # Use package-specific functions if needed # randomForest::varImpPlot(model_forest$fit) # nolint ``` An unsupervised method returns tidied components as well, so its `$fit` is the list holding them and the wrapped object sits at `$fit$model`: ```{r} model_pca <- tl_model(iris, ~ ., method = "pca") names(model_pca$fit) class(model_pca$fit$model) # This is the prcomp object ``` ## The Whole Workflow Split, fit, predict, score — the four steps this vignette covered, in the order they run: ```{r} # Quick example combining everything data_split <- tl_split(iris, prop = 0.7, stratify = "Species", seed = 42) # Random forests are scale-invariant, so no scaling is needed here. When a # method does need scaled inputs, the same transformation has to be applied # to the test set -- see the Supervised Learning vignette. model_final <- tl_model(data_split$train, Species ~ ., method = "forest") test_preds <- predict(model_final, new_data = data_split$test) accuracy <- mean(test_preds$.pred == data_split$test$Species) cat("Test accuracy:", round(accuracy * 100, 1), "%\n") ``` ## Next Steps - `vignette("data-ingestion")` — reading from files, databases and cloud sources - `vignette("supervised-learning")` — classification and regression in depth, and how to replay preprocessing on a test set - `vignette("unsupervised-learning")` — clustering, ordination, and choosing the number of clusters - `vignette("market-basket")` — association rules - `vignette("tuning-and-pipelines")` — hyperparameter search, and bundling a workflow you can save - `vignette("automl")` — searching across methods under a time budget - `vignette("diagnostics")` — assumptions, influence and model comparison - `vignette("reporting")` — plots and formatted `gt` tables - `vignette("integration-workflows")` — combining supervised and unsupervised steps - `vignette("compute-backends")` — when a fit is too slow or too large for this machine: GPU routing, cost estimates, and the cloud safety model