@@ -1183,7 +1183,7 @@ simlrU <- function(
11831183 if (mixAlg == " avg" ) {
11841184 avgU <- projectionsU [[1 ]] * 0.0
11851185 for (j in wtobind ) {
1186- avgU <- avgU + projectionsU [[j ]] / ( nmodalities - 1 )
1186+ avgU <- avgU + projectionsU [[j ]] / length( wtobind )
11871187 }
11881188 basis <- avgU
11891189 } else if (mixAlg == " stochastic" ) { # FIXME
@@ -1218,77 +1218,57 @@ simlrU <- function(
12181218 }
12191219 } else if (mixAlg == " newton-schulz" ) {
12201220 # This is a fast way to get an orthogonal basis from the averaged projections
1221- n_mod_minus_1 <- length(wtobind )
1221+ n_mod <- length(wtobind )
12221222 M <- matrix (0 , nrow(avgU ), nc )
1223- for (idx in seq_len(n_mod_minus_1 )) {
1223+ for (idx in seq_len(n_mod )) {
12241224 start_col <- (idx - 1 ) * nc + 1
12251225 end_col <- idx * nc
12261226 M <- M + avgU [, start_col : end_col ]
12271227 }
1228- M <- M / n_mod_minus_1
1229-
1230- if (expBeta > 0 && ! is.null(previousU )) {
1231- # Exponential moving average blending
1232- M <- (1 - expBeta ) * M + expBeta * previousU
1233- # Single Newton-Schulz iteration step for symmetric decorrelation
1234- MtM <- t(M ) %*% M
1235- # We use a single NS step logic: W_{k+1} = 0.5 * W_k * (3I - W_k^T W_k)
1236- # But we must ensure it's still a valid approximation.
1237- # Alternatively, use inv_sqrt_sym_newton with max_iter=1
1238- inv_sqrt_MtM <- inv_sqrt_sym_newton(MtM , max_iter = 1L )
1239- basis <- M %*% inv_sqrt_MtM
1240- } else {
1241- # Standard full convergence
1242- MtM <- t(M ) %*% M
1243- inv_sqrt_MtM <- inv_sqrt_sym_newton(MtM )
1244- basis <- M %*% inv_sqrt_MtM
1245- }
1228+ M <- M / n_mod
1229+ MtM <- t(M ) %*% M
1230+ inv_sqrt_MtM <- inv_sqrt_sym_newton(MtM )
1231+ basis <- M %*% inv_sqrt_MtM
12461232 } else if (mixAlg == " ica-newton" ) {
12471233 # FastICA-style update with Newton-Schulz symmetric decorrelation
1248- n_mod_minus_1 <- length(wtobind )
1234+ n_mod <- length(wtobind )
12491235 M <- matrix (0 , nrow(avgU ), nc )
1250- for (idx in seq_len(n_mod_minus_1 )) {
1236+ for (idx in seq_len(n_mod )) {
12511237 start_col <- (idx - 1 ) * nc + 1
12521238 end_col <- idx * nc
12531239 M <- M + avgU [, start_col : end_col ]
12541240 }
1255- M <- M / n_mod_minus_1
1256-
1257- if (expBeta > 0 && ! is.null(previousU )) {
1258- # 1. Blend current average with previous state
1259- M_blended <- (1 - expBeta ) * M + expBeta * previousU
1260- # 2. Whiten blended (single step)
1261- MtM <- t(M_blended ) %*% M_blended
1262- M_whitened <- M_blended %*% inv_sqrt_sym_newton(MtM , max_iter = 1L )
1263- # 3. Single FastICA fixed-point step
1264- tanhM <- tanh(M_whitened )
1265- E1 <- t(M_whitened ) %*% tanhM / nrow(M_whitened )
1266- E2 <- colMeans(1 - tanhM ^ 2 )
1267- basis <- M_whitened %*% (E1 - diag(E2 ))
1268- # 4. Single NS decorrelation step
1269- BtB <- t(basis ) %*% basis
1270- basis <- basis %*% inv_sqrt_sym_newton(BtB , max_iter = 1L )
1271- } else {
1272- # Standard full convergence (initial step or no EMA)
1273- MtM <- t(M ) %*% M
1274- M <- M %*% inv_sqrt_sym_newton(MtM )
1275- tanhM <- tanh(M )
1276- E1 <- t(M ) %*% tanhM / nrow(M )
1277- E2 <- colMeans(1 - tanhM ^ 2 )
1278- basis <- M %*% (E1 - diag(E2 ))
1279- BtB <- t(basis ) %*% basis
1280- basis <- basis %*% inv_sqrt_sym_newton(BtB )
1281- }
1241+ M <- M / n_mod
1242+ # Standard full convergence (initial step or no EMA)
1243+ MtM <- t(M ) %*% M
1244+ M <- M %*% inv_sqrt_sym_newton(MtM )
1245+ tanhM <- tanh(M )
1246+ E1 <- t(M ) %*% tanhM / nrow(M )
1247+ E2 <- colMeans(1 - tanhM ^ 2 )
1248+ basis <- M %*% (E1 - diag(E2 ))
1249+ BtB <- t(basis ) %*% basis
1250+ basis <- basis %*% inv_sqrt_sym_newton(BtB )
12821251 } else {
12831252 basis <- (ba_svd(scale(avgU ,T ,T ), nu = nc , nv = 0 )$ u )
12841253 }
12851254 }
12861255
1287- if (expBeta > 0 && ! is.null(previousU ) && ! (mixAlg %in% c(" newton-schulz" , " ica-newton" ))) {
1288- basis <- (1 - expBeta ) * basis + expBeta * previousU
1256+ if (ncol(basis ) < nc ) {
1257+ needed <- nc - ncol(basis )
1258+ if (! is.null(previousU ) && ncol(previousU ) == nc ) {
1259+ pad <- previousU [, (ncol(basis ) + 1 ): nc , drop = FALSE ]
1260+ } else {
1261+ pad <- matrix (rnorm(nrow(basis ) * needed ), nrow = nrow(basis ), ncol = needed )
1262+ }
1263+ basis <- cbind(basis , pad )
1264+ }
1265+
1266+ if (expBeta > 0 && ! is.null(previousU ) ) {
1267+ basis <- nsa_flow( Y0 = basis , X0 = previousU , w = expBeta , retraction = " soft_polar" ,
1268+ max_iter = 10 , apply_nonneg = FALSE )$ Y
12891269 # Single Newton-Schulz iteration step for symmetric decorrelation
1290- BtB <- t(basis ) %*% basis
1291- basis <- basis %*% inv_sqrt_sym_newton(BtB , max_iter = 1L )
1270+ # BtB <- t(basis) %*% basis
1271+ # basis <- basis %*% inv_sqrt_sym_newton(BtB, max_iter = 1L)
12921272 }
12931273 colnames(basis )= paste0(" PC" ,1 : nc )
12941274 if (! orthogonalize ) {
0 commit comments