themis provides a large family of steps for dealing with imbalanced
data. This article organizes them into a taxonomy, borrowed from imbalanced-learn, so you can
see how the methods relate to each other and choose between them. Every
method is a recipe step, and most also have a direct-implementation
function of the same name without the step_ prefix.
Over-sampling
Over-sampling grows the minority classes, either by replicating existing observations or by synthesizing new ones.
-
Random replication.
step_upsample()samples minority observations with replacement. It adds no new information but is fast and model-agnostic. -
SMOTE family. These synthesize new observations by
interpolating between a minority observation and its nearest neighbors.
-
step_smote()is the original SMOTE for numeric predictors. -
step_bsmote()(borderline-SMOTE) synthesizes only near the class boundary, where errors are most likely. -
step_svmsmote()uses a support vector machine to locate the boundary before synthesizing. -
step_kmeans_smote()clusters the predictor space first and synthesizes only inside the clusters where the minority class is dominant, giving sparser clusters more of the new observations. -
step_smotenc()handles a mix of numeric and nominal predictors. -
step_smoten()handles data sets where every predictor is nominal.
-
-
Adaptive.
step_adasyn()is like SMOTE but generates more synthetic points for the minority observations that are harder to learn (those surrounded by majority neighbors). -
Smoothed bootstrap.
step_rose()generates a fully synthetic data set by drawing from smoothed kernels around the observations.
Under-sampling
Under-sampling shrinks the majority classes. Most under-samplers in
themis perform prototype selection, keeping a subset of the
real rows. One, step_cluster_centroids(), performs
prototype generation, creating new representative rows
instead.
-
Random.
step_downsample()drops majority observations at random. -
Distance / near-boundary. These target observations
by their position relative to the class boundary.
-
step_nearmiss()keeps the majority observations closest to the minority class. -
step_tomek()removes the majority member of each Tomek link (a mutually-nearest pair from different classes). -
step_cnn()(condensed nearest neighbors) keeps a subset that still classifies the data with a 1-nearest-neighbor rule. -
step_oss()(one-sided selection) combines condensed nearest neighbors with Tomek links.
-
-
Neighborhood cleaning. These remove observations
that disagree with their neighborhood.
-
step_enn()(edited nearest neighbors) removes observations whose class differs from the majority of their neighbors. Withtimesorall_kit becomes RENN or AllKNN. -
step_ncl()(neighborhood cleaning rule) is a variant focused on cleaning the neighborhoods of minority observations.
-
-
Hardness.
step_instance_hardness()removes the majority observations that are hardest to classify, measured by how often their neighbors disagree. -
Prototype generation.
step_cluster_centroids()summarizes each majority class with k-means cluster representatives: the centroids themselves withvoting = "soft", or the observation nearest each centroid withvoting = "hard".
Combination
imbalanced-learn ships combination samplers (SMOTEENN,
SMOTETomek) that over-sample and then clean the result.
scikit-learn needs these as single objects because a pipeline cannot
chain two samplers around one estimator. recipes has no such limitation,
so the equivalents are ordinary step compositions.
# SMOTEENN: over-sample, then clean with edited nearest neighbors
recipe(class ~ ., data = train) |>
step_smote(class) |>
step_enn(class)
# SMOTETomek: over-sample, then remove Tomek links
recipe(class ~ ., data = train) |>
step_smote(class) |>
step_tomek(class)Two things are worth knowing:
- Order matters. Over-sample first, then clean, so the cleaning step can remove the ambiguous synthetic points SMOTE tends to create near the boundary.
-
step_enn()cleans every class. It flags any observation, including freshly synthesized minority points, whose class differs from its neighborhood. This matches imbalanced-learn’sSMOTEENN, which configures its ENN stage withsampling_strategy = "all". Standalone imbalanced-learnEditedNearestNeighboursinstead defaults to cleaning “not minority”, so themis’sstep_enn()is already oriented toward this combined use.
Regression
Imbalance is not limited to classification. step_smogn()
resamples an imbalanced numeric outcome, over-sampling rare
regions of the response and under-sampling common ones, so themis
applies to imbalanced regression as well.
Choosing a method
- Start with
step_downsample()orstep_upsample()as fast baselines. - Reach for the SMOTE family when synthesizing plausible minority
observations helps, and pick the member that matches your predictor
types (
step_smotenc()/step_smoten()for nominal data). - Use a cleaning under-sampler (
step_enn(),step_tomek(),step_ncl()) when the majority class is noisy or overlaps the minority class, on its own or composed after SMOTE. - Use
step_smogn()for imbalanced regression.
