--- title: "sparsediscrim models" output: rmarkdown::html_vignette vignette: > %\VignetteIndexEntry{sparsediscrim models} %\VignetteEngine{knitr::rmarkdown} %\VignetteEncoding{UTF-8} --- ```{r setup, include = FALSE} if (requireNamespace("sparsediscrim", quietly = TRUE)) { library(tidypredict) library(dplyr) eval_code <- TRUE } else { eval_code <- FALSE } knitr::opts_chunk$set( collapse = TRUE, comment = "#>", eval = eval_code ) ``` | Function |Works| |---------------------------------------------------------------|-----| |`tidypredict_fit()`, `tidypredict_sql()`, `parse_model()` | ✔ | |`tidypredict_to_column()` | ✗ | |`tidypredict_test()` | ✗ | |`tidypredict_interval()`, `tidypredict_sql_interval()` | ✗ | |`parsnip` | ✔ | `sparsediscrim` fits regularized linear discriminant analysis models. The four supported functions are `lda_diag()`, `lda_shrink_mean()`, `lda_shrink_cov()`, and `lda_emp_bayes_eigen()`, which are the models behind the `"sparsediscrim"` engine of `discrim_linear()` (`regularization_method` values `"diagonal"`, `"shrink_mean"`, `"shrink_cov"`, and `"min_distance"`). All four share the same structure: one mean vector and prior per outcome class, plus a single pooled covariance shared by every class, and they only differ in how that covariance is regularized. The class posterior probabilities are therefore a softmax over one linear predictor per class, so `tidypredict_fit()` returns a *named list* of expressions, one for each class, rather than a single expression. Since the output is a list, `tidypredict_to_column()` and `tidypredict_test()` are not supported. ## `tidypredict_` functions ```{r} model <- sparsediscrim::lda_diag(Species ~ ., data = iris) ``` - Create the R formulas, one per class ```{r} fit <- tidypredict_fit(model) names(fit) fit[["setosa"]] ``` - Add the predictions to the original table ```{r} library(dplyr) iris %>% mutate(!!!tidypredict_fit(model)) %>% glimpse() ``` - Confirm that the results match the model's `predict()` results ```{r} probs <- sapply(fit, \(f) rlang::eval_tidy(f, iris)) posterior <- predict(model, iris, type = "prob") all.equal(unname(probs), unname(as.matrix(posterior))) ``` Note that `predict()` with `type = "prob"` is not usable for `lda_emp_bayes_eigen()` (`regularization_method = "min_distance"`) models: `sparsediscrim` builds a rank-deficient covariance for them and returns `NaN` for every row. The expressions that `tidypredict_fit()` generates use the model's own pseudo-inverse of that covariance, so they agree with the model's `type = "class"` predictions. ## parsnip `parsnip` fitted models are also supported by `tidypredict`: ```{r} library(parsnip) library(discrim) p_model <- discrim_linear(regularization_method = "shrink_mean") %>% set_engine("sparsediscrim") %>% fit(Species ~ ., data = iris) ``` ```{r} tidypredict_fit(p_model)[["virginica"]] ``` These models are fit from a numeric matrix, so a model fit with the `x`/`y` interface can only refer to the matrix columns it was given. Categorical predictors work through the formula interface and through `parsnip`, both of which keep the formula around and let the dummy columns be written in terms of the original factors: ```{r} cars <- transform(mtcars, vs = factor(vs), gear = factor(gear)) c_model <- discrim_linear() %>% set_engine("sparsediscrim") %>% fit(vs ~ mpg + gear + disp, data = cars) tidypredict_fit(c_model)[["1"]] ``` ## Parse model spec Here is an example of the model spec: ```{r} pm <- parse_model(model) str(pm, 2) ```