NMF-Based Super-Level Analysis and ECMSMA

Atsushi Kawaguchi

2026-08-26

1 Overview

Version 3.2 adds NMF and sparse NMF (sNMF) as super-level decomposition methods. They support clustering-oriented analyses of multiblock data while the default sprmethod = "PCA" preserves the version 3.1 computational path.

dat <- simdata(n = 45, rho = 0.8, Xps = c(5, 5, 5), Yps = 3, seed = 3)
X <- dat$X
names(X) <- paste0("block", seq_along(X))

2 Super-level methods

The principal options are:

fit_pca <- msma(X, comp = c(2, 2), sprmethod = "PCA", intseed = 1)
fit_nmf <- msma(X, comp = c(2, 2), sprmethod = "NMF", intseed = 1)
fit_snmf <- msma(
  X, comp = c(2, 2),
  sprmethod = "sNMF",
  lambdaXsup = 0.05,
  intseed = 1
)

3 Non-negative transformations

NMF requires non-negative input. The nneg argument controls transformation of the block scores:

For a score vector \(s\), positive-negative decomposition is

\[ s^+ = \max(s,0), \qquad s^- = \max(-s,0), \qquad s=s^+-s^-. \]

fit_posneg <- msma(X, comp = c(2, 2), sprmethod = "NMF", nneg = "posneg")
fit_absolute <- msma(X, comp = c(2, 2), sprmethod = "NMF", nneg = "absolute")
fit_min <- msma(X, comp = c(2, 2), sprmethod = "NMF", nneg = "min")

4 Non-negativity and reproducibility

all(unlist(fit_snmf$ssX) >= 0)
#> [1] TRUE
all(unlist(fit_snmf$wsX) >= 0)
#> [1] TRUE
fit_snmf_2 <- msma(
  X, comp = c(2, 2),
  sprmethod = "sNMF",
  lambdaXsup = 0.05,
  intseed = 1
)
all.equal(fit_snmf$ssX, fit_snmf_2$ssX)
#> [1] TRUE
all.equal(fit_snmf$wsX, fit_snmf_2$wsX)
#> [1] TRUE

5 Clustering solutions

A simple cluster assignment is obtained from the largest super-score value for each observation. Each root component supplies one clustering solution.

cluster_matrix <- vapply(
  fit_snmf$ssX,
  function(score) max.col(score, ties.method = "first"),
  integer(nrow(fit_snmf$ssX[[1]]))
)
colnames(cluster_matrix) <- names(fit_snmf$ssX)
head(cluster_matrix)
#>      comp1 comp2
#> [1,]     2     2
#> [2,]     2     2
#> [3,]     1     1
#> [4,]     1     2
#> [5,]     1     1
#> [6,]     1     2
apply(cluster_matrix, 2, table)
#>   comp1 comp2
#> 1    28    23
#> 2    17    22

The resulting matrix may be supplied to a separate consensus or ensemble clustering procedure. The consensus step is not performed automatically by msma().

6 Multiple supervision variables

Z may be a numeric matrix. con4spv specifies weights used to combine its columns. This is a composite-supervision model rather than a multi-task model with a separate loading for every outcome.

set.seed(3)
z1 <- rnorm(nrow(X[[1]]))
z2 <- 0.5 * z1 + rnorm(nrow(X[[1]]), sd = 0.5)
Z <- cbind(clinical = z1, biomarker = z2)

fit_multi_z <- msma(
  X = X, Z = Z,
  con4spv = c(0.7, 0.3),
  comp = 2,
  muX = 0.20,
  intseed = 1
)
fit_multi_z$predictiv
#> [[1]]
#>         clinical   biomarker
#> [1,] 0.004986875 0.004354675
#> 
#> [[2]]
#>      clinical  biomarker
#> [1,] 0.036251 0.04306789

Conceptually, the combined supervision score is

\[ z_c = Zc, \]

where the supplied weights are normalized internally as required by the implementation.

7 One-column matrix compatibility

A vector and a one-column matrix produce the same result.

fit_z_vector <- msma(X, Z = z1, comp = 1, muX = 0.20, intseed = 1)
fit_z_matrix <- msma(X, Z = cbind(z1), comp = 1, muX = 0.20, intseed = 1)
fit_z_vector$call <- NULL
fit_z_matrix$call <- NULL
isTRUE(all.equal(fit_z_vector, fit_z_matrix, tolerance = 1e-8))
#> [1] TRUE

8 Practical recommendations

9 Session information

sessionInfo()
#> R Under development (unstable) (2026-08-25 r90447 ucrt)
#> Platform: x86_64-w64-mingw32/x64
#> Running under: Windows 11 x64 (build 26200)
#> 
#> Matrix products: default
#>   LAPACK version 3.12.1
#> 
#> locale:
#> [1] LC_COLLATE=C                    LC_CTYPE=Japanese_Japan.utf8   
#> [3] LC_MONETARY=Japanese_Japan.utf8 LC_NUMERIC=C                   
#> [5] LC_TIME=Japanese_Japan.utf8    
#> 
#> time zone: Asia/Tokyo
#> tzcode source: internal
#> 
#> attached base packages:
#> [1] stats     graphics  grDevices utils     datasets  methods   base     
#> 
#> other attached packages:
#> [1] msma_3.2
#> 
#> loaded via a namespace (and not attached):
#>  [1] digest_0.6.39   R6_2.6.1        fastmap_1.2.0   xfun_0.60      
#>  [5] cachem_1.1.0    knitr_1.51      htmltools_0.5.9 rmarkdown_2.31 
#>  [9] lifecycle_1.0.5 cli_3.6.6       sass_0.4.10     jquerylib_0.1.4
#> [13] compiler_4.7.0  tools_4.7.0     evaluate_1.0.5  bslib_0.12.0   
#> [17] yaml_2.3.12     otel_0.2.0      rlang_1.3.0     jsonlite_2.0.0