Signed-Bottleneck NMF-AE: Three-Layer NMF-AE with Signed Bottleneck
Source:R/nmfae.signed.R
nmfae.signed.Rdnmfae.signed fits a three-layer non-negative matrix factorization
autoencoder with a signed bottleneck, solving
$$Y_1 \approx X_1 (C_{+} - C_{-}) X_2 Y_2,
\quad X_1 \ge 0,\; C_{+} \ge 0,\; C_{-} \ge 0,\; X_2 \ge 0,$$
where \(\Theta = C_{+} - C_{-}\) is the signed bottleneck. The basis
matrices \(X_1\) (columns sum to 1) and \(X_2\) (rows sum to 1) retain
their non-negative "parts-based" interpretability, while \(\Theta\) can
express anti-correlations (e.g., refractive index up vs. Abbe number down).
The algorithm uses Direct Multiplicative Updates derived from Ding et al. (2010) sign-splitting technique, applied block-wise to the four non-negative blocks \((C_{+}, C_{-}, X_1, X_2)\). Each block update monotonically decreases the true objective \(\|Y_1 - X_1(C_{+} - C_{-})X_2 Y_2\|_F^2\) (Lee-Seung auxiliary function method).
Relation to nmfae: When \(\Theta \ge 0\) suffices
(the nmfae case), nmfae.signed reduces to nmfae up to
the \(C_{+} - C_{-}\) parameterization. Use nmfae.signed when the
data exhibit negative cross-property correlations that tri-NMF-AE cannot
express (e.g., high refractive index <-> low Abbe number trade-off).
Usage
nmfae.signed(
Y1,
Y2 = Y1,
rank = 2,
rank.encoder = rank,
epsilon = 1e-04,
maxit = 5000,
verbose = FALSE,
...
)Arguments
- Y1
Output matrix \(Y_1\) (P1 x N). Negative entries allowed (
Y.signed = TRUEis auto-detected).- Y2
Input matrix \(Y_2\) (P2 x N). Must be non-negative. Default
Y1(autoencoder).- rank
Integer. Decoder rank Q. Default 2. Alias
Qaccepted via....- rank.encoder
Integer. Encoder rank R. Default
rank. AliasRaccepted via....- epsilon
Relative convergence tolerance on the objective. Default
1e-4.- maxit
Maximum iterations. Default 5000.
- verbose
Logical. Print progress. Default
FALSE.- ...
Additional arguments:
warm.startOne of
TRUE(default, hybrid: warm-start \(X_1, X_2\) fromnmfaebut initialize \(C_{+}, C_{-}\) randomly),"full"(warm-start everything including \(C_{+} = C_{\mathrm{tri}}\), \(C_{-} = \delta\)), orFALSE(random for all blocks). The hybrid default avoids the \(C_{-} = 0\) local-minimum trap inherited from tri-NMF-AE while still benefiting from good \(X_1, X_2\) initialization. Ignored when \(Y_1\) has negative entries.nstartInteger, default 1 (cf.
kmeans). Number of random restarts for \(C_{+}, C_{-}\). Each restart uses seedseed + 7919 * (s-1). Returns the best run by final objective. Signed models have more local minima than non-negative ones because the bottleneck \(\Theta = C_{+} - C_{-}\) can take both positive and negative values; during exploration a largernstart(e.g., 10-50) reduces the chance of being trapped at an inferior stationary point (particularly the \(C_{-} = 0\) trap from warm-start from non-negative tri-NMF-AE). Use the default 1 for fast development and raise for publication-grade runs.Y1.weightsOptional non-negative weight matrix (P1 x N) or vector (length N) for \(Y_1\), analogous to the
weightsargument oflm. Loss becomes \(\sum W_{ij} \, (Y_{1,ij} - \hat Y_{1,ij})^2\) (lm()-style, linear in \(W\)). Logical matrices (TRUE/FALSE) are also accepted. Used bynmfae.signed.ecvto hold out test elements via a binary mask \(W \in \{0,1\}\); real-valued weights for importance weighting are also supported. Default: ifY1hasNA, a binary mask is auto-generated (0 forNA, 1 elsewhere).Cp.init,Cn.initExplicit \(Q \times R\) non-negative matrices for initialization. Overrides warm.start.
C.initExplicit signed \(Q \times R\) matrix, internally split into \((C_{+}, C_{-})\).
X1.init,X2.initExplicit basis matrices.
seedRNG seed. Default 123.
print.traceLogical. Print iteration trace. Default
FALSE.prefix.dec,prefix.encLabel prefixes for decoder/encoder factors. Default
"Dec","Enc".
Value
An object of class c("nmfae.signed", "nmfae", "nmf") with:
- X1
Decoder basis (P1 x Q), column sum 1.
- Cp, Cn
Non-negative parts of \(\Theta\) (each Q x R).
- C
Signed bottleneck \(\Theta = C_{+} - C_{-}\) (Q x R).
- X2
Encoder basis (R x P2), row sum 1.
- Y1hat
Fitted values \(X_1 (C_{+} - C_{-}) X_2 Y_2\).
- H
Encoding \((C_{+} - C_{-}) X_2 Y_2\) (Q x N, signed).
- rank
c(Q = Q, R = R).- dims
c(P1, P2, N).- objfunc, objfunc.iter
Final and per-iteration objective values.
- r.squared, sigma, mae
Goodness of fit statistics.
- niter, runtime
Iterations and elapsed seconds.
- Y.signed
Logical; whether \(Y_1\) contained negative entries.
- call
Matched call.
References
Ding, C.H.Q., Li, T., and Jordan, M.I. (2010). Convex and Semi-Nonnegative Matrix Factorizations. IEEE TPAMI, 32(1), 45-55.
Satoh, K. (2026). Signed-Bottleneck NMF-AE: Signed-Bottleneck 3-Layer NMF (research memo, 2026-04-18).
Ding, C. H. Q., Li, T., & Jordan, M. I. (2010). Convex and semi-nonnegative matrix factorizations. IEEE Transactions on Pattern Analysis and Machine Intelligence, 32(1), 45–55.
Examples
# \donttest{
set.seed(1)
Y1 <- matrix(abs(rnorm(12)), 3, 4)
Y2 <- matrix(abs(rnorm(20)), 5, 4)
res <- nmfae.signed(Y1, Y2, rank = 2, rank.encoder = 2, maxit = 500)
summary(res)
#>
#> Call:
#> nmfae.signed(Y1 = Y1, Y2 = Y2, rank = 2, rank.encoder = 2, maxit = 500)
#>
#> Signed-Bottleneck NMF-AE (Direct MU; signed bottleneck Theta = Cp - Cn)
#>
#> Dimensions:
#> P1 (output rows): 3
#> P2 (input rows): 5
#> N (samples): 4
#> Q (decoder rank): 2
#> R (encoder rank): 2
#> Parameters: 24
#>
#> Convergence:
#> Iterations: 16
#> Runtime (secs): 0.03
#> Final objfunc: 2.128
#>
#> Goodness of fit:
#> R-squared: 0.04789
#> Sigma (RMSE): 0.4211
#> MAE: 0.344
#>
#> Structure (range / sparsity / negative mass):
#> X1 (P1 x Q): range [6.232e-139, 0.9987] sparsity 16.7%
#> Cp (Q x R): range [0, 2.459] sparsity 75.0%
#> Cn (Q x R): range [0, 0.01288] sparsity 50.0%
#> C=Cp-Cn (Q x R): range [-0.01288, 2.459] sparsity 25.0% neg-mass 0.6%
#> X2 (R x P2): range [1.027e-30, 0.8354] sparsity 30.0%
#> Encoding H (Q x N): neg-mass 0.1%
#>
# }