classbound is an R package for exploring and comparing
classification decision boundaries. It provides a unified interface for
fitting classifiers, computing 2D boundary grids, and visualizing how
different models partition the feature space.
What you can do with classbound:
explorapp())tidymodels workflowsFull documentation: https://natydasilva.github.io/classbound/
devtools::install_github("natydasilva/classbound")classbound() fits a model, computes its decision
boundary, and plots the result in a single call.
library(classbound)
library(palmerpenguins)
penguins <- na.omit(palmerpenguins::penguins[
,
c("species", "bill_length_mm", "bill_depth_mm")
])
classbound(
data = penguins,
formula = species ~ bill_length_mm + bill_depth_mm,
classifier = rpart::rpart
)
For full control, use the three-step pipeline:
# 1. Fit
model <- fit_model(penguins, species ~ bill_length_mm + bill_depth_mm, rpart::rpart)
# 2. Compute boundary
model <- boundary_compute(model)
# 3. Plot
plot_boundary(
model,
obs_data = penguins,
x_col = "bill_length_mm",
y_col = "bill_depth_mm",
true_label = "species"
)
boundary_compute() returns the model with the grid
attached, so you can replot with different settings without
refitting.
Launch the built-in Shiny application for point-and-click exploration:
# Start with your own dataset
explorapp(data = penguins, target_col = "species")
# Or start empty and simulate/draw data
explorapp()In explorapp() you can: - Import real data or simulate
synthetic datasets - Draw classification data by hand - Fit and compare
multiple classifiers simultaneously - Switch between 2D Slice and
Projection views for high-dimensional data - Inject outliers and observe
how boundaries shift - Inspect probability surfaces (for supported
classifiers) - Export data, models, plots, and a reproduce script
Use explorapp() to:
Use the core Classbound functions directly:
fit_model()
boundary_compute()
plot_boundary()When a model is trained on more than two features,
boundary_compute() supports:
penguins3 <- na.omit(palmerpenguins::penguins[
,
c("species", "bill_length_mm", "bill_depth_mm", "flipper_length_mm")
])
m3 <- fit_model(penguins3, species ~ ., rpart::rpart)
m3_slice <- boundary_compute(m3,
feature_range = list(bill_length_mm = c(30, 60), bill_depth_mm = c(10, 25)),
resolution = 60
)
plot_boundary(m3_slice,
obs_data = penguins3,
x_col = "bill_length_mm", y_col = "bill_depth_mm",
true_label = "species"
)
feat_cols <- c("bill_length_mm", "bill_depth_mm", "flipper_length_mm")
pca <- prcomp(penguins3[, feat_cols], scale. = TRUE)
basis <- pca$rotation[, 1:2]
x_std <- scale(penguins3[, feat_cols], center = pca$center, scale = pca$scale)
z_mat <- x_std %*% basis
m3_proj <- boundary_compute(m3,
feature_range = list(
PC1 = range(z_mat[, 1]) + c(-0.5, 0.5),
PC2 = range(z_mat[, 2]) + c(-0.5, 0.5)
),
resolution = 60,
projection = list(basis = basis, center = pca$center, scale = pca$scale)
)
plot_boundary(m3_proj,
obs_data = penguins3,
x_col = "PC1", y_col = "PC2", true_label = "species"
)
See the high-dimensional guide for a full explanation.
library(parsnip)
library(workflowsets)
spec_tree <- decision_tree(mode = "classification") |> set_engine("rpart")
spec_rf <- rand_forest(mode = "classification") |> set_engine("randomForest")
wf_set <- workflow_set(
preproc = list(base = species ~ bill_length_mm + bill_depth_mm),
models = list(tree = spec_tree, forest = spec_rf)
)
bounds <- boundary_workflow_set(wf_set,
data = penguins,
response = "species", resolution = 60
)
plot_boundary(bounds,
obs_data = penguins,
x_col = "bill_length_mm", y_col = "bill_depth_mm",
true_label = "species"
)
| Resource | Link |
|---|---|
| Getting Started | getting-started |
| High-Dimensional | high-dimensional |
| tidymodels | tidymodels-workflow |
| tourr | tourr-workflow |
| Explorapp Guide | explorapp-guide |
| Custom Adapters | custom_adapters |
| Reference | Function Reference |