| Title: | Linear SVM-Based Recursive Decision Trees |
|---|---|
| Description: | Implements Support Vector Machine Oblique Decision Trees (SVMODT). Recursively builds classification trees using linear Support Vector Machines (SVM) hyperplanes at each node instead of axis-parallel splits, creating oblique decision boundaries. Features include multiple feature selection methods, dynamic feature subset strategies, class weight support for imbalanced datasets, pruning and feature penalization. |
| Authors: | Aneesh Agarwal [aut, cre, cph], Jack Jewson [aut, ths], Erik Sverdrup [aut, ths] |
| Maintainer: | Aneesh Agarwal <[email protected]> |
| License: | GPL (>= 3) |
| Version: | 0.1.0 |
| Built: | 2026-06-30 16:51:37 UTC |
| Source: | https://github.com/cran/svmodt |
Thin S3 wrapper that dispatches to plot_boundary or
plot_surface depending on plot.type.
## S3 method for class 'svmodt_node' plot( x, y = NULL, ..., data = NULL, response = NULL, plot.type = c("surface", "boundary"), features = NULL, max_depth = NULL, check_accuracy = TRUE, resolution = NULL )## S3 method for class 'svmodt_node' plot( x, y = NULL, ..., data = NULL, response = NULL, plot.type = c("surface", "boundary"), features = NULL, max_depth = NULL, check_accuracy = TRUE, resolution = NULL )
x |
An |
y |
Ignored; present only to satisfy the |
... |
Currently unused. |
data |
The original training data frame (required). |
response |
Character string naming the response column (required). |
plot.type |
One of |
features |
Length-2 character vector of axis features
( |
max_depth |
Maximum depth to visualize
( |
check_accuracy |
Logical; show per-node accuracy
( |
resolution |
Grid resolution per axis.
Default |
"boundary": invisibly returns the list from
plot_boundary.
"surface": invisibly returns the ggplot2 object from
plot_surface.
tree <- svm_split(wdbc, response = "diagnosis", max_depth = 3) # All-node boundary panels - prints first, returns list viz <- plot(tree, data = wdbc, response = "diagnosis", plot.type = "boundary" ) viz$plots[[2]] # second node # Global decision surface plot(tree, data = wdbc, response = "diagnosis", plot.type = "surface" ) # Surface with explicit feature axes plot(tree, data = wdbc, response = "diagnosis", plot.type = "surface", features = c("radius_mean", "concavity_mean") )tree <- svm_split(wdbc, response = "diagnosis", max_depth = 3) # All-node boundary panels - prints first, returns list viz <- plot(tree, data = wdbc, response = "diagnosis", plot.type = "boundary" ) viz$plots[[2]] # second node # Global decision surface plot(tree, data = wdbc, response = "diagnosis", plot.type = "surface" ) # Surface with explicit feature axes plot(tree, data = wdbc, response = "diagnosis", plot.type = "surface", features = c("radius_mean", "concavity_mean") )
Predict method for svmodt_node objects
## S3 method for class 'svmodt_node' predict(object, newdata, return_probs = FALSE, calibrate_probs = TRUE, ...)## S3 method for class 'svmodt_node' predict(object, newdata, return_probs = FALSE, calibrate_probs = TRUE, ...)
object |
An object of class |
newdata |
A data frame of new predictor values. |
return_probs |
Logical; if |
calibrate_probs |
Logical; if |
... |
Currently unused. |
If return_probs = FALSE (the default), a character vector of predicted
class labels, one element per row of newdata.
If return_probs = TRUE, a named list with two elements:
Character vector of predicted class labels (length =
nrow(newdata)).
Numeric matrix of class probabilities with
nrow(newdata) rows and one column per class. Column names are the
class labels; each row sums to 1. When calibrate_probs = TRUE,
probabilities are derived from the SVM decision value via logistic
calibration; otherwise empirical class frequencies at the leaf node are
used.
# Train DTSVM tree tree <- svm_split( data = wdbc, response = "diagnosis", max_depth = 3, max_features = 2, feature_method = "cor" ) # Predict on WDBC data (returns a character vector of class labels) preds <- predict(tree, newdata = wdbc) # Predict with probabilities and logistic calibration result <- predict(tree, newdata = wdbc, return_probs = TRUE, calibrate_probs = TRUE ) head(result$predictions) head(result$probabilities)# Train DTSVM tree tree <- svm_split( data = wdbc, response = "diagnosis", max_depth = 3, max_features = 2, feature_method = "cor" ) # Predict on WDBC data (returns a character vector of class labels) preds <- predict(tree, newdata = wdbc) # Predict with probabilities and logistic calibration result <- predict(tree, newdata = wdbc, return_probs = TRUE, calibrate_probs = TRUE ) head(result$predictions) head(result$probabilities)
' Print method for svmodt_node objects
## S3 method for class 'svmodt_node' print(x, ...)## S3 method for class 'svmodt_node' print(x, ...)
x |
An object of class |
... |
Further arguments passed to |
Invisibly returns x (the svmodt_node object), called
for its side effect of printing a human-readable summary of the tree
structure to the console.
tree <- svm_split( data = wdbc, response = "diagnosis", max_features = 2, max_depth = 3, min_samples = 5, feature_method = "random", verbose = TRUE ) print(tree)tree <- svm_split( data = wdbc, response = "diagnosis", max_features = 2, max_depth = 3, min_samples = 5, feature_method = "random", verbose = TRUE ) print(tree)
Constructs a decision tree where each internal node uses a Support Vector Machine (SVM) to determine the split. Supports dynamic feature selection, feature penalization, scaling, and class weighting.
svm_split( data, response, depth = 1, max_depth = 10, min_samples = 5, max_features = NULL, feature_method = c("random", "mutual", "cor"), impurity_measure = c("entropy", "gini"), max_features_strategy = c("constant", "random", "decrease"), max_features_decrease_rate = 0.8, max_features_random_range = c(0.3, 1), penalize_used_features = FALSE, feature_penalty_weight = 0.5, n_subsets = 1, used_features = character(0), class_weights = c("none", "balanced", "custom"), custom_class_weights = NULL, min_impurity_decrease = 0.001, verbose = FALSE, all_classes = NULL, ... )svm_split( data, response, depth = 1, max_depth = 10, min_samples = 5, max_features = NULL, feature_method = c("random", "mutual", "cor"), impurity_measure = c("entropy", "gini"), max_features_strategy = c("constant", "random", "decrease"), max_features_decrease_rate = 0.8, max_features_random_range = c(0.3, 1), penalize_used_features = FALSE, feature_penalty_weight = 0.5, n_subsets = 1, used_features = character(0), class_weights = c("none", "balanced", "custom"), custom_class_weights = NULL, min_impurity_decrease = 0.001, verbose = FALSE, all_classes = NULL, ... )
data |
A data frame containing predictors and the response variable. |
response |
Character string specifying the response column in 'data'. All other columns are treated as predictors. |
depth |
Integer indicating the current recursion depth (used internally; default is 1). |
max_depth |
Maximum depth of the tree. |
min_samples |
Minimum number of samples required to attempt a split. |
max_features |
Maximum number of features to consider at each split. |
feature_method |
Feature selection method at each node. One of:
|
impurity_measure |
Information Gain evaluation criteria
|
max_features_strategy |
Strategy to adjust the number of features per node:
|
max_features_decrease_rate |
Numeric fraction for decreasing features if 'max_features_strategy = "decrease"'. |
max_features_random_range |
Numeric vector of length 2 specifying min and max fraction of features if 'max_features_strategy = "random"'. |
penalize_used_features |
Logical; if TRUE, features used in ancestor nodes are penalized to encourage diversity. |
feature_penalty_weight |
Numeric (0<U+2013>1) weight for penalizing previously used features. |
n_subsets |
Number of Evaluated Random Feature combinations at each node when 'feature_method = "random' |
used_features |
Character vector of features already used in ancestor nodes (used internally). |
class_weights |
Character string specifying how to handle class imbalance. One of:
|
custom_class_weights |
Optional named numeric vector specifying custom weights per class. |
min_impurity_decrease |
Required decrease in impurity by a split to be considered valid |
verbose |
Logical; if TRUE, prints information about each node during tree construction. |
all_classes |
Optional character vector of all possible response classes (used internally). |
... |
Additional arguments passed to the underlying SVM fitting function. |
This function recursively splits the dataset using an SVM at each node. Splitting stops when maximum depth is reached, the node contains fewer than 'min_samples', or all samples belong to the same class. Features are scaled and selected dynamically at each node, and previously used features can be penalized to promote diversity. Class weighting schemes support handling imbalanced datasets. This approach allows construction of an **oblique decision tree**, where splits are linear hyperplanes rather than axis-aligned.
A nested list representing the decision tree. Each node contains:
Logical; TRUE if the node is a leaf.
Fitted SVM model at this node (for internal nodes).
Vector of features selected for this node.
Scaling information used at this node.
Left child node (decision value > 0).
Right child node (decision value <U+2264> 0).
Depth of this node in the tree.
Number of samples at this node.
Number of features considered at this node.
Logical; TRUE if feature penalization was applied.
Class weights applied at this node.
data(wdbc) tree <- svm_split( data = wdbc, response = "diagnosis", max_depth = 3, min_samples = 5, feature_method = "random", verbose = TRUE )data(wdbc) tree <- svm_split( data = wdbc, response = "diagnosis", max_depth = 3, min_samples = 5, feature_method = "random", verbose = TRUE )
Generic function that walks the tree for a single row of new data, printing the SVM decision value and chosen branch at every internal node and the final predicted class at the leaf.
trace_path(object, ...) ## S3 method for class 'svmodt_node' trace_path(object, sample_data, sample_idx = 1, ...)trace_path(object, ...) ## S3 method for class 'svmodt_node' trace_path(object, sample_data, sample_idx = 1, ...)
object |
An |
... |
Currently unused. |
sample_data |
A data frame of new predictor values (one or more rows). |
sample_idx |
Integer; which row to trace (default |
Invisibly returns the predicted class label (character string).
trace_path(svmodt_node): Method for svmodt_node objects.
tree <- svm_split(wdbc, response = "diagnosis", max_depth = 3) trace_path(tree, wdbc, sample_idx = 5)tree <- svm_split(wdbc, response = "diagnosis", max_depth = 3) trace_path(tree, wdbc, sample_idx = 5)
The WDBC dataset contains quantitative measurements from digitized images of fine needle aspirates (FNA) of breast masses. It is commonly used for classification tasks to distinguish between benign and malignant tumors.
wdbcwdbc
A data frame with 569 rows and 32 columns:
Mean of radius
Standard error of radius
Worst (largest) radius
Mean of texture
Standard error of texture
Worst texture
Mean of perimeter
Standard error of perimeter
Worst perimeter
Mean area
Standard error of area
Worst area
Mean smoothness
Standard error of smoothness
Worst smoothness
Mean compactness
Standard error of compactness
Worst compactness
Mean concavity
Standard error of concavity
Worst concavity
Mean concave points
Standard error of concave points
Worst concave points
Mean symmetry
Standard error of symmetry
Worst symmetry
Mean fractal dimension
Standard error of fractal dimension
Worst fractal dimension
Factor with levels 'B' and 'M'
Dr. William H. Wolberg, W. Nick Street, and Olvi L. Mangasarian, University of Wisconsin<U+2013>Madison. Original dataset available at: <https://archive.ics.uci.edu/dataset/17/breast+cancer+wisconsin+diagnostic>
The Wine dataset contains the results of a chemical analysis of wines derived from three different cultivars grown in the same region of Italy. The dataset is commonly used for multiclass classification tasks, where the objective is to identify the cultivar of origin based on physicochemical properties.
winewine
A data frame with 178 rows and 14 columns:
Factor with levels 1, 2, and 3 indicating cultivar
Alcohol content
Malic acid concentration
Ash content
Alcalinity of ash
Magnesium content
Total phenols
Flavonoid content
Nonflavanoid phenols
Proanthocyanin content
Color intensity
Hue
OD280/OD315 of diluted wines
Proline concentration
Aeberhard, S. & Forina, M. (1992). Wine Dataset. UCI Machine Learning Repository. Original dataset available at: <https://archive.ics.uci.edu/dataset/109/wine>