Simulation Study: Single vs. Mixture Synergy Models
Yusuke Matsui
2026-08-14
Source:vignettes/simulation_single_vs_mixture.Rmd
simulation_single_vs_mixture.Rmd1. Introduction
This vignette demonstrates how to reproduce the simulation study used in our manuscript to compare
- Single-subject factor models (SingleFA, SinglePCA) and
- Mixture models that allow latent sub-populations (MixtureFA, MixturePCA).
Performance is evaluated on 10 independent replicates with metrics that reflect goodness of fit (Bayesian Information Criterion, BIC), clustering accuracy (Adjusted Rand Index, ARI) and reconstruction quality (Variance Accounted For, VAF).
For reference, VAF is defined as
where is the observed signal and its low-rank reconstruction.
2. Simulation design
Each replicate draws synthetic subjects whose EMG signals are generated from true clusters sharing common factor loadings of rank across muscles. The simulation:
- fits all four candidate models,
- initialises each mixture model with
-means
(
use_kmeans_init = TRUE), - repeats the EM algorithm
n_init = 5times to reduce local-optimum bias, and - returns a tidy data frame of evaluation statistics.
Noise level (noise_scale) and between-cluster separation
(cluster_sep) can be tuned; we keep both at 1.0 for an
intermediate difficulty setting.
3. Running the 10 replicates
The following code demonstrates how to run the simulation using the package’s simulation functions. Note that the actual function names may vary; please refer to the package documentation for the current API.
seeds_vec <- 101:110
# Example simulation workflow using package functions
res_list <- lapply(seeds_vec, function(s) {
# Generate synthetic data
sim_data <- generate_synergy_data(
N = 50, K = 4, r = 4, M = 7, T_each = 100,
cluster_sep_spatial = 1.0, seed = s
)
# Fit models and collect results
# (Implementation details depend on your analysis workflow)
# This is a placeholder showing the expected structure
data.frame(
Method = c("SingleFA", "SinglePCA", "MixtureFA", "MixturePCA"),
BIC = NA_real_,
ARI = NA_real_,
VAF = NA_real_,
Seed = s
)
})
df_all <- bind_rows(res_list)
dplyr::glimpse(df_all)We annotate two helper columns to simplify downstream plotting:
5. Visualising variability across replicates
library(ggplot2)
ggplot(df_all, aes(x = Type, y = VAF, fill = Method)) +
geom_boxplot(alpha = 0.6, outlier.shape = NA) +
theme_bw() +
facet_wrap(~SubMethod) +
labs(x = NULL, y = "VAF", title = "VAF by model family") +
theme(legend.position = "none")
ggplot(df_all, aes(x = Type, y = BIC, fill = Method)) +
geom_boxplot(alpha = 0.6, outlier.shape = NA) +
theme_bw() +
facet_wrap(~SubMethod) +
labs(x = NULL, y = "BIC", title = "BIC by model family") +
theme(legend.position = "none")Interpretation. Mixture models yield lower (better) BIC and markedly higher ARI (not shown) whenever distinct latent clusters exist. VAF differences between FA and PCA reflect method-specific assumptions (orthogonality vs. diagonal uniqueness). In practice, the trade-off between VAF and model complexity (BIC) suggests MixtureFA strikes the best balance for heterogeneous cohorts.
6. Session information
#> R version 4.5.2 (2025-10-31)
#> Platform: x86_64-pc-linux-gnu
#> Running under: Ubuntu 24.04.4 LTS
#>
#> Matrix products: default
#> BLAS: /opt/R/4.5.2/lib/R/lib/libRblas.so
#> LAPACK: /opt/R/4.5.2/lib/R/lib/libRlapack.so; LAPACK version 3.12.1
#>
#> locale:
#> [1] LC_CTYPE=ja_JP.UTF-8 LC_NUMERIC=C
#> [3] LC_TIME=ja_JP.UTF-8 LC_COLLATE=ja_JP.UTF-8
#> [5] LC_MONETARY=ja_JP.UTF-8 LC_MESSAGES=ja_JP.UTF-8
#> [7] LC_PAPER=ja_JP.UTF-8 LC_NAME=C
#> [9] LC_ADDRESS=C LC_TELEPHONE=C
#> [11] LC_MEASUREMENT=ja_JP.UTF-8 LC_IDENTIFICATION=C
#>
#> time zone: Asia/Tokyo
#> tzcode source: system (glibc)
#>
#> attached base packages:
#> [1] stats graphics grDevices utils datasets methods base
#>
#> other attached packages:
#> [1] synergyMixR_1.0.0 ggplot2_4.0.2 purrr_1.2.1 tidyr_1.3.2
#> [5] dplyr_1.2.0
#>
#> loaded via a namespace (and not attached):
#> [1] gtable_0.3.6 jsonlite_2.0.0 compiler_4.5.2 Rcpp_1.1.1
#> [5] tidyselect_1.2.1 jquerylib_0.1.4 systemfonts_1.3.1 scales_1.4.0
#> [9] textshaping_1.0.4 yaml_2.3.12 fastmap_1.2.0 R6_2.6.1
#> [13] generics_0.1.4 knitr_1.51 htmlwidgets_1.6.4 tibble_3.3.1
#> [17] desc_1.4.3 RColorBrewer_1.1-3 bslib_0.10.0 pillar_1.11.1
#> [21] rlang_1.1.7 cachem_1.1.0 xfun_0.56 S7_0.2.1
#> [25] fs_1.6.6 sass_0.4.10 otel_0.2.0 cli_3.6.5
#> [29] withr_3.0.2 pkgdown_2.2.0 magrittr_2.0.4 digest_0.6.39
#> [33] grid_4.5.2 lifecycle_1.0.5 vctrs_0.7.1 evaluate_1.0.5
#> [37] glue_1.8.0 farver_2.1.2 ragg_1.5.0 rmarkdown_2.30
#> [41] tools_4.5.2 pkgconfig_2.0.3 htmltools_0.5.9