Scaden trains an ensemble of three multilayer perceptrons of
increasing width (m256, m512,
m1024) on simulated pseudo-bulks and averages their
predictions. It is the simplest of the four ported methods and a
reasonable first thing to run on a new dataset.
Chunks below are not evaluated during build. Sample counts and epochs are reduced for demonstration; use the function defaults for real analyses.
Data
library(quasar)
library(QuasarDeconData)
sc_ref <- load_cov_imm("train")
pbulk <- load_cov_pbulk(1)
bulk <- pbulk$bulk_expression_profiles # genes x samples
truth <- pbulk$ground_truth_proportions # samples x cell typesSimulate
scaden_sim <- scaden_sim_pb(
sc_data = sc_ref,
celltype_col = "cell_type",
n = 500, # cells per pseudo-bulk
samplenum = 5000, # number of pseudo-bulks
sparse = TRUE,
seed = 42
)sparse = TRUE zeroes a subset of cell types in a subset
of samples, producing training mixtures in which some populations are
absent. This matters when the target samples may not contain every cell
type in the reference.
scaden_sim_pb() can also merge several cell types into a
single unknown class via unknown_celltypes. The merge
happens after simulation — each original type gets its own
Dirichlet component and is sampled independently, then the proportion
columns are summed. This mirrors the original Python behaviour and
differs from relabelling cells before simulation.
Process
scaden_proc <- scaden_process(
sim_data = scaden_sim,
bulk_data = bulk,
mode = "scaden",
var_cutoff = 0.1
)Two preprocessing modes are available:
-
"scaden"applies an absolute variance cutoff to the bulk matrix only, then intersects with the training genes. Useslog2(x + 1)and per-sample min-max scaling. -
"tape"applies a top-quantile cutoff to both matrices independently before intersecting. Useslog(x + 1)and either min-max or standardisation viascaler.
The log base is immaterial in practice — both scalers are invariant to multiplication by a positive constant — but each mode stays literal to its source.
Train
scaden_fit <- scaden(
train_x = scaden_proc$train_x,
train_y = scaden_proc$train_y,
lr = 1e-4,
batch_size = 128,
epochs = 20,
seed = 123
)All three architectures train sequentially, each with its own progress bar. Per-batch and per-epoch losses are returned for every model.
Predict
scaden_pred <- scaden_predict(scaden_fit, scaden_proc$test_x)
head(scaden_pred$average_output)The individual ensemble members are returned as well
(prediction_model256, prediction_model512,
prediction_model1024), which is useful for gauging how much
the three architectures disagree — wide disagreement on a sample is a
signal worth following up.
Evaluate
metrics <- quasar_prop_metrics(scaden_pred$average_output, truth)
metrics$cell_type_rmse
metrics$pearson_celltype_cor