| Type: | Package |
| Title: | Semi-Supervised Learning with Mixed Missingness in Finite Mixture Models |
| Version: | 0.2.0 |
| Depends: | R (≥ 3.6.0) |
| Description: | Semi-supervised Gaussian finite mixture models for partially labelled data under complete-case, missing completely at random (MCAR), entropy-dependent missing at random (MAR), and mixed MCAR/MAR label-missingness formulations. For the mixed formulation, the source of a missing label may be observed or latent. The package supports equal and component-specific covariance matrices, model fitting, simulation, initialization, prediction, classification performance assessment, and entropy-based diagnostics. A semi-synthetic Blood Transfusion data set is included to illustrate the applied workflow. |
| License: | GPL-3 |
| Encoding: | UTF-8 |
| LazyData: | true |
| Imports: | graphics, stats |
| Suggests: | testthat (≥ 3.0.0) |
| Config/testthat/edition: | 3 |
| Config/roxygen2/version: | 8.0.0 |
| NeedsCompilation: | no |
| Packaged: | 2026-08-19 01:22:01 UTC; uqjwu15 |
| Author: | Geoffrey J. McLachlan
|
| Maintainer: | Jinran Wu <jinran.wu@uq.edu.au> |
| Repository: | CRAN |
| Date/Publication: | 2026-08-20 12:02:04 UTC |
SSLfmm: Semi-Supervised Finite Mixture Models with Mixed Label Missingness
Description
Semi-supervised Gaussian finite mixture models for partially observed class labels under complete-case, MCAR, entropy-dependent MAR, and mixed MCAR/MAR formulations. The mixed formulation allows the missingness source to be observed or latent. The package supports equal or component-specific covariance matrices, simulation, prediction, classification performance assessment, and entropy-based diagnostics.
Details
The intended user-facing functions are fit_sslfmm(), initialize_sslfmm(), rmix(), simulate_sslfmm(), simulate_mixed_missingness(), classification_performance(), and plot_entropy_labels(), together with standard S3 predict(), print(), and summary() methods for fitted objects. The package also includes the semi-synthetic blood_transfusion data used in the software-paper application. Low-level likelihood, parameter-packing, Cholesky, and entropy helper functions are internal and are not exported.
Semi-Synthetic Blood Transfusion Data
Description
A semi-synthetic partially observed version of the Blood Transfusion classification data used to illustrate the missing-label models in SSLfmm.
Usage
data("blood_transfusion")
Format
A data frame with 748 observations and 7 variables:
idObservation identifier.
truthComplete reference class label, coded 1 or 2.
observedClass label supplied during fitting;
NAdenotes a missing label.missing_indicatorLabel status/source:
observed,mar, ormcar.RecencyStandardized recency measurement.
FrequencyStandardized donation-frequency measurement.
TimeStandardized time measurement.
Details
The complete labels in truth are retained only for evaluation in the
semi-synthetic case study. The response supplied to fit_sslfmm() is
observed.
Examples
data("blood_transfusion")
table(blood_transfusion$missing_indicator)
Classification Performance Metrics
Description
Computes overall and per-class classification performance after removing observations for which truth or predicted is missing. Macro averages are taken over classes represented in the retained truth labels. If a represented true class is never predicted, its precision and F1 score are defined as zero and remain in the macro average.
Usage
classification_performance(truth, predicted, posterior = NULL)
Arguments
truth |
True class labels. |
predicted |
Predicted class labels; must have the same length as |
posterior |
Optional numeric matrix with one row per observation and nonnegative finite class probabilities. If columns are named, names must be unique and include every true class used in the calculation. |
Value
A list with:
-
metrics: named numeric vector containing accuracy, error rate, balanced accuracy, macro precision, macro recall, and macro F1; whenposterioris supplied, log loss and multiclass Brier score are added; -
per_class: data.frame with class support, precision, recall, and F1; -
confusion_matrix: truth-by-predicted contingency table.
Posterior rows are normalized internally to unit sum after validation; negative or non-finite values are rejected rather than silently corrected.
Examples
truth <- c(1, 1, 2, 2)
pred <- c(1, 2, 2, 2)
post <- matrix(c(.8, .2,
.4, .6,
.1, .9,
.3, .7), ncol = 2, byrow = TRUE)
colnames(post) <- c("1", "2")
classification_performance(truth, pred, post)
Fit a Semi-Supervised Gaussian Finite Mixture Model
Description
Fits semi-supervised Gaussian finite-mixture classifiers under complete-case, MCAR, entropy-dependent MAR, or mixed MCAR/MAR label-missingness formulations. For mixed models, the MCAR/MAR source may be observed or latent.
Usage
fit_sslfmm(
x, y, g = NULL,
method = c("mixed", "mar", "mcar", "cc"),
covariance_type = c("equal", "unequal"),
indicator = c("latent", "observed"),
missing_source = NULL, init = NULL, n_starts = 5L,
control = list(), entropy_floor = 1e-300,
alpha_starts = c(0, 0.05, 0.15, 0.30),
alpha_upper = 1 - 1e-8, ridge = 1e-4, seed = NULL
)
Arguments
x |
Numeric feature matrix or data.frame with observations in rows and features in columns. Feature values must be fully observed. |
y |
Class labels with one entry per row of |
g |
Positive integer number of mixture components. It is inferred from observed labels when possible. |
method |
One of |
covariance_type |
|
indicator |
For |
missing_source |
Required only for |
init |
Optional output from |
n_starts |
Positive integer number of fitting starts. |
control |
A list controlling numerical fitting. |
entropy_floor |
Single positive finite lower bound used before taking the logarithm of posterior entropy. |
alpha_starts |
Finite starting values for the latent MCAR-channel probability in the latent mixed model. Every value must lie between zero and |
alpha_upper |
Single finite upper bound for alpha, strictly between zero and one. |
ridge |
Single positive finite covariance regularization value used for initialization and complete-case fitting. |
seed |
Optional random seed for initialization and perturbed starts. |
Details
For method = "mcar", unlabelled observations contribute the Gaussian-mixture marginal density. For method = "mar", label missingness follows a logistic model in log posterior entropy. For method = "mixed", the missing-label probability combines an MCAR channel and the entropy-dependent MAR channel. With an observed source indicator, alpha is estimated from the recorded MCAR-source assignments; with a latent source indicator, alpha is estimated jointly with the other model parameters.
Entropy-dependent "mar" and "mixed" fitting requires g >= 2. With one component posterior entropy is constant and the entropy slope is not identifiable. Simulation with g = 1 remains supported as a boundary/API check.
Value
An object of class "SSLfmm". Important components include:
-
pi: fitted mixing proportions, named by class; -
mu: fittedg \times pmean matrix, one component per row; -
sigma: onep \times pmatrix for equal covariance or ap \times p \times garray for unequal covariance; -
xiandalpha: fitted missingness parameters when applicable; -
posterior: fitted class-posterior matrix with class-labelled columns; -
enandentropy: identical fitted posterior-entropy vectors; -
missingandobserved_missing: identical observed label-missingness indicators; -
latent_missing: recorded MCAR-source indicator for observed-source mixed fitting, orNAwhen that source is latent; -
latent_missing_probability: posterior probability of the MCAR source for each row in the latent-source mixed model; -
loglik,convergence,optimizer,start_summary, andstart_diagnostics: fit and start diagnostics.
Examples
set.seed(1)
mu <- matrix(c(-2, 2), nrow = 1, ncol = 2)
sim <- simulate_sslfmm(
n = 60,
pi = c(0.5, 0.5),
mu = mu,
sigma = matrix(1, 1, 1),
mechanism = "mcar",
missing_rate = 0.20,
seed = 1
)
x <- as.matrix(sim$data["x1"])
# A complete-case fit is deterministic and demonstrates the main interface.
fit <- fit_sslfmm(x, sim$data$label, g = 2,
method = "cc", covariance_type = "equal")
fit
predict(fit, x[1:5, , drop = FALSE], type = "posterior")
Initialize SSLfmm Model Parameters
Description
Constructs stable starting values for SSLfmm model fitting. Observed class labels anchor component identities; k-means is used only as a fallback for components without adequate labelled observations.
Usage
initialize_sslfmm(
x, y, g = NULL,
covariance_type = c("equal", "unequal"),
ridge = 1e-4, seed = NULL
)
Arguments
x |
Numeric feature matrix or data.frame with observations in rows and features in columns. |
y |
Class labels with one entry per row of |
g |
Positive integer number of mixture components. Inferred from observed labels when possible. |
covariance_type |
|
ridge |
Single positive finite diagonal regularization value for covariance starts. |
seed |
Optional seed used only for k-means fallback initialization. |
Value
An object of class "SSLfmm_init", implemented as a list containing pi, mu, sigma, g, p, covariance_type, and label_levels. The mean matrix mu is g \times p, with one component per row. For equal covariance, sigma is p \times p; for unequal covariance, it is p \times p \times g.
Examples
x <- rbind(matrix(rnorm(20, -1), 10, 2),
matrix(rnorm(20, 1), 10, 2))
y <- c(rep(1, 7), rep(NA, 3), rep(2, 7), rep(NA, 3))
init <- initialize_sslfmm(x, y, g = 2,
covariance_type = "unequal", seed = 1)
init$pi
init$mu
dim(init$sigma)
Boxplot of Posterior Entropy by Class Label
Description
Draws a boxplot of finite posterior-entropy values grouped by class label.
Usage
plot_entropy_labels(entropy, labels = NULL,
main = "Posterior entropy by class label",
xlab = "Class label", ylab = "Posterior entropy",
legend = TRUE, ...)
Arguments
entropy |
Numeric posterior-entropy vector or an |
labels |
Class labels. If an |
main, xlab, ylab |
Plot labels. |
legend |
Retained for backward compatibility; boxplots do not require a legend. |
... |
Additional arguments passed to |
Value
Invisibly returns the legacy entropy-group summaries together with the boxplot summary.
Examples
ent <- c(0.05, 0.10, 0.20, 0.40, 0.55, 0.65)
lab <- c(1, 1, 2, 1, 2, 2)
plot_entropy_labels(ent, lab)
Methods for SSLfmm Fits
Description
Standard prediction, printing, and summary methods for fitted SSLfmm objects.
Usage
## S3 method for class 'SSLfmm'
predict(object, newdata,
type = c("class", "posterior", "entropy", "all"), ...)
## S3 method for class 'SSLfmm'
print(x, ...)
## S3 method for class 'SSLfmm'
summary(object, ...)
Arguments
object, x |
An object of class |
newdata |
Numeric feature matrix or data.frame with the same number of feature columns as the fitted model. |
type |
Prediction output: |
... |
Unused. |
Value
For predict(), "class" returns predicted labels in the same broad label type used for fitting; "posterior" returns an n \times g numeric matrix with class-labelled columns; "entropy" returns a numeric vector; and "all" returns a list with components class, posterior, and entropy. print() returns the fit invisibly. summary() returns a compact fitted-parameter list.
Examples
mu <- matrix(c(-2, 2), nrow = 1, ncol = 2)
s <- simulate_sslfmm(50, c(0.5, 0.5), mu, matrix(1, 1, 1),
mechanism = "mcar", missing_rate = 0.2, seed = 1)
x <- as.matrix(s$data["x1"])
f <- fit_sslfmm(x, s$data$label, g = 2, method = "cc")
predict(f, x[1:5, , drop = FALSE], type = "posterior")
predict(f, x[1:5, , drop = FALSE], type = "all")
Simulate from a Gaussian Finite Mixture
Description
Generates observations from a Gaussian finite mixture without introducing label missingness.
Usage
rmix(n = 200L, pi, mu, sigma, seed_number = NULL)
Arguments
n |
Positive integer number of observations. |
pi |
Positive finite mixing proportions of length |
mu |
Numeric |
sigma |
Either one shared numeric |
seed_number |
Optional random seed. |
Value
A data.frame with feature columns x1, ..., xp followed by integer component label truth.
Examples
mu <- matrix(c(-1, 1), nrow = 1, ncol = 2)
dat <- rmix(
n = 20,
pi = c(0.5, 0.5),
mu = mu,
sigma = matrix(1, 1, 1),
seed_number = 1
)
head(dat)
Simulate Semi-Supervised Data Under Mixed Label Missingness
Description
Convenience wrapper for simulate_sslfmm(..., mechanism = "mixed"). It uses the same mixed missingness mechanism and the same stable return-value contract.
Usage
simulate_mixed_missingness(
n = 500L, pi, mu, sigma,
alpha = 0.10, xi0 = NULL, xi1 = 3,
mar_rate = 0.30, seed = NULL,
entropy_floor = 1e-300
)
Arguments
n |
Positive integer number of observations. |
pi |
Positive finite mixing proportions of length |
mu |
Numeric |
sigma |
Shared |
alpha |
MCAR-channel probability in |
xi0 |
MAR intercept; when |
xi1 |
Positive finite entropy slope. |
mar_rate |
Target mean MAR probability when |
seed |
Optional random seed. |
entropy_floor |
Positive finite entropy floor. |
Value
The same five-component list documented for simulate_sslfmm(): data, true_setup, groups, probs, and raw.
See Also
simulate_sslfmm(), rmix()
Examples
mu <- matrix(c(-1, 1), nrow = 1, ncol = 2)
sim <- simulate_mixed_missingness(
n = 40,
pi = c(0.5, 0.5),
mu = mu,
sigma = matrix(1, 1, 1),
alpha = 0.10,
mar_rate = 0.25,
seed = 1
)
stopifnot(
is.list(sim),
is.data.frame(sim$data),
identical(sim$data$missing, sim$data$observed_missing)
)
Simulate Semi-Supervised Finite-Mixture Data
Description
Simulates semi-supervised Gaussian finite-mixture data with class-label missingness under complete-case, MCAR, entropy-dependent MAR, or mixed MCAR/MAR mechanisms.
Usage
simulate_sslfmm(
n = 500L, pi, mu, sigma,
mechanism = c("mixed", "mar", "mcar", "cc"),
alpha = 0.10, missing_rate = NULL,
xi0 = NULL, xi1 = 3, mar_rate = 0.30,
seed = NULL, entropy_floor = 1e-300
)
Arguments
n |
Positive integer number of observations. |
pi |
Positive finite mixing proportions of length |
mu |
Numeric |
sigma |
Either one shared numeric |
mechanism |
One of |
alpha |
MCAR-channel probability for |
missing_rate |
Optional MCAR missing-label rate used only for |
xi0 |
MAR intercept. If |
xi1 |
Positive finite slope multiplying log posterior entropy for MAR or mixed simulation. |
mar_rate |
Target average MAR probability when |
seed |
Optional random seed. |
entropy_floor |
Positive finite lower bound used before taking the logarithm of posterior entropy. |
Details
For mixed missingness, let q_i denote the entropy-dependent MAR probability and let the MCAR trigger have probability \alpha. The observed missing-label probability is
\alpha + (1-\alpha)q_i.
The simulator records both the true MCAR trigger and a latent potential-MAR trigger. MCAR takes precedence when both occur. This is distributionally equivalent to generating the MAR trigger only among observations not selected by MCAR, while also making the documented group decomposition reproducible.
When g=1, posterior entropy is constant. Simulation remains supported for API/boundary testing, and automatic xi0 calibration uses the resulting constant-probability analytic solution. Entropy-dependent MAR slope estimation with g=1 is not identifiable and is therefore not supported by fit_sslfmm().
Value
Always a list with exactly the top-level components data, true_setup, groups, probs, and raw.
-
data: a data.frame whose leading columns are, in order,x1, ...,xp,en,missing,label, andtruth. It then containsobserved_missing,latent_missing,missing_source,prob_mar, andentropy.enandentropyare identical;missingandobserved_missingare identical.latent_missingis the true MCAR-channel trigger in the simulation. -
true_setup: a list beginning withpi,mu, andsigma, followed by covariance/missingness metadata and the true missingness parameters when applicable. -
groups: a list beginning withmar_group,obs_group,mcar_in_mar, andmcar_in_obs.mar_groupis the latent potential-MAR stratum,obs_groupits complement, and the twomcar_in_*entries are intersections with the MCAR trigger. Additional entriesobserved,mcar,mar, andmissinggive directly useful row indices. -
probs: numeric vector of MAR probabilitiesq_i; it is identical todata$prob_mar. -
raw: the originalrmix()data.frame augmented withen,missing,label, the explicit missingness indicators/source, and MAR probabilities.
Examples
mu <- matrix(c(-1.5, 1.5), nrow = 1, ncol = 2)
Sigma <- matrix(1, 1, 1)
s_cc <- simulate_sslfmm(30, c(0.5, 0.5), mu, Sigma,
mechanism = "cc", seed = 1)
s_mcar <- simulate_sslfmm(30, c(0.5, 0.5), mu, Sigma,
mechanism = "mcar", missing_rate = 0.25, seed = 2)
s_mar <- simulate_sslfmm(30, c(0.5, 0.5), mu, Sigma,
mechanism = "mar", mar_rate = 0.25, seed = 3)
s_mixed <- simulate_sslfmm(30, c(0.5, 0.5), mu, Sigma,
mechanism = "mixed", alpha = 0.10,
mar_rate = 0.25, seed = 4)
names(s_mixed)
head(s_mixed$data)