Fit the self-gated mixture-of-experts single-sample discriminator
Source:R/singlesample-moe-gated-scorer.R
fit_moe_gated.RdTrains a LayerNorm MLP encoder, \(E\) linear logistic expert heads, and a linear gating network JOINTLY on the per-sample-rCLR, universe-aligned TRAINING matrix (via reticulate-python torch; Adam, cross-entropy on the gate-softmax mixture logit), EXPORTS the encoder weights, the LayerNorm parameters, the \(E\) expert weight/bias, and the gate weight/bias to R as plain numeric matrices/vectors, and DISCARDS the python module. The fitted model holds no external pointer; the score is the pure-R mixture logit \(s(z) = \sum_e g_e(z)\,h_e(z)\) with \(z = \mathrm{enc}(\mathrm{rclr}(x))\).
The gate is driven by the specimen's OWN embedding (SELF-gated), NOT by external kit/technology metadata, so the method is single-sample-deployable (no external covariate at score). See the method description for this design departure from the manifest's "kit-gated" name.
Usage
fit_moe_gated(X_train, y_train, meta_train = NULL, hp = list())Arguments
- X_train
Numeric matrix (samples \(\times\) features) of non-negative abundances with unique, non-empty feature names (colnames).
- y_train
Numeric / integer 0/1 labels (1 = case), length
nrow(X_train), with at least one case and one control.- meta_train
Optional per-sample metadata. Accepted for interface uniformity and otherwise ignored (the gate is self-driven, not kit-driven).
- hp
Optional list of hyperparameters. Allowed fields:
hidden(positive-integer vector of encoder layer widths; the LAST entry is the embedding dim \(d\); defaultc(64L, 32L)),activation("relu"(default) or"tanh"),n_experts(number of experts \(E\), integer \(\geq 2\); default4L),epochs(positive integer; default200L),lr(positive Adam learning rate; default1e-3),weight_decay(non-negative Adam L2; default1e-4),min_features(feature-overlap floor at scoring, positive integer; default3L),device("cpu"(default),"cuda", or"auto";"cuda"/"auto"fall back to CPU with no GPU), andseed(integer; default42L).
Value
Object of class moe_gated_model: a list with
feature_universe, weights (exported per-layer list(W, b)
encoder), layernorm (per-layer list(gamma, beta, eps)),
activation, W_e (\(E \times d\) expert weights), b_e
(length-\(E\) expert biases), W_g (\(E \times d\) gate weights),
b_g (length-\(E\) gate biases), n_experts, embedding_dim,
device (resolved), seed, and hp.
Details
The score is the convex combination \(s(z) = \sum_e g_e(z)\,h_e(z)\) where the expert logits are \(h_e(z) = (z W_e^\top + b_e)_e\) and the gate weights are the softmax \(g_e(z) = \mathrm{softmax}(z W_g^\top + b_g)_e\). Because the gate is a softmax, the mixture logit lies within \([\min_e h_e, \max_e h_e]\) per row. Larger = more case-like.
References
Jacobs RA, Jordan MI, Nowlan SJ, Hinton GE. (1991) Adaptive Mixtures of Local Experts. Neural Computation 3(1):79-87. Shazeer N, et al. (2017) Outrageously Large Neural Networks: The Sparsely-Gated Mixture-of-Experts Layer. ICLR. arXiv:1701.06538.
Examples
if (FALSE) { # \dontrun{
set.seed(1)
n <- 80; p <- 30; k <- 8
L <- matrix(stats::rnorm(n * p, 4, 0.5), nrow = n,
dimnames = list(NULL, paste0("miR-", seq_len(p))))
y <- rep(c(0, 1), each = n / 2)
L[y == 1, seq_len(k)] <- L[y == 1, seq_len(k)] + 1.2
X <- exp(L)
model <- fit_moe_gated(X, y)
score_moe_gated(model, X[1, , drop = FALSE])
} # }