gpca_mle() now separates the penalty effect of reciprocal rescaling
(loglik_rescale_delta, exactly zero with scale_fix = "none") from final
refitting and objective reevaluation (loglik_refit_delta). The reported
likelihood remains evaluated at the returned fit and metrics.
Strictly positive diagonal weights are retained in both forward and inverse metric factors. Previously a small positive weight could contribute a large singular value while its recovered loading was zero. The fix covers GPCA, covariance PCA and PLS operators, including base-matrix diagonal inputs.
rank_rtol from the iteration
threshold. All backends also apply a common final component filter. Empty
C++ deflation results return empty singular-value and variance vectors.genpca_solver_nonconvergence. Existing
dense fallbacks handle this error; operator callers without a fallback stop
instead of returning an unchecked fit."clip" repairs remove negative eigenvalues even within the PSD
validation tolerance and report the change, up to reconstruction roundoff.geigen_cov() documents its projected equation for singular metrics and the
range constraint on its vectors. Commuting metrics and covariances need not
give the same leading component under GMD and generalized eigenanalysis.X or a metric. New
rank_rtol argument in genpca(), genpca_cov() and the internal
solvers: component j is dropped when d_j <= rank_rtol * d_1 (default
1e-6), for every method. Metric validation and null-space detection use
a separate relative tolerance, sqrt(.Machine$double.eps). The previous
absolute cutoffs (1e-8 on eigenvalues, 1e-9 on singular values, a
1e-8 total-variance floor, an absolute jitter_metric) could change the
number of components returned, or return wrong values from the randomized
backend, when X was rescaled.is_psd(), is_pd(), both shifted Cholesky probes with relative
tolerance). ensure_spd() always returns a positive definite matrix and
forwards its tolerance; previously a zero or singular matrix could be
returned unchanged.constraints_remedy. The
relative asymmetry ||A - A'|| / ||A|| is measured; below 1e-10 the two
triangles are averaged, above it the call stops. Previously one triangle
was silently used, so the result depended on which triangle the caller
had filled. The same applies to C and R in genpca_cov().constraints_remedy = "clip" now guarantees a PSD result; the previous
tolerant fast path could return a matrix with a small negative eigenvalue.constraints_remedy. Previously the eigen path rejected what the other
backends silently accepted or clamped.method = "eigen" never truncates a metric any more. A positive definite
general metric is factored exactly by Cholesky at any size; a singular
general metric needs a dense eigendecomposition, which is refused above
maxeig rows (default now 5000) with a message naming the
alternatives. The previous behaviour, keeping only the maxeig largest
eigenvectors of the metric before looking at X, could discard the
dominant component entirely (a direction with a small metric eigenvalue
and large data variance). warn_approx is deprecated and ignored.genpca_cov(method = "gmd") requires C to be PSD within tolerance and
no longer clamps negative metric eigenvalues silently. Its tol argument
is deprecated in favor of rank_rtol and metric_rtol.repair_metric() returns a repaired metric together with a
metric_repair_report (minimum eigenvalue before and after, Gershgorin
bound, applied shift, rank, condition number).genpca() now defaults to constraints_remedy = "error": an indefinite
metric stops the fit instead of being silently shifted. Opt into a repair
with constraints_remedy = "ridge", "clip" or "identity"; every
repair that changes the metric emits a warning of class
genpca_metric_repaired whose report field is the repair_metric()
diagnostic. gpca_mle() inherits the new default.genpls(), genplsc() and gplssvd_op() gain the same
constraints_remedy argument (default "error"). Previously their
metric operators applied a Gershgorin ridge to any indefinite weight
matrix with no message and no way to opt out.verbose = TRUE is no longer needed to find out that a metric was
replaced by the identity; the warning always fires.gpca_mle()genpca_cov() is now the GMD estimator only (eigendecomposition of
R^{1/2} C R^{1/2}). The generalized eigenproblem C v = lambda R v, a
different estimator, is the new exported
geigen_cov(). genpca_cov(method = "geigen") still works for one
release and forwards with a deprecation warning.gpca_mle() defaults to scale_fix = "none". The ridge penalty already
identifies the overall scale of the learned metrics, and the previous
default "trace" rescaled the metrics after convergence in a way the
penalized objective is not invariant to, while still reporting the
pre-rescale value. loglik is now always the penalized objective at the
returned metrics; loglik_unpenalized and loglik_rescale_delta (the
change caused by a "trace"/"det" rescale) are new.method = "spectra" computes the
top-k singular triplets of the metric-whitened data F_M' X F_A
(M = F_M F_M', A = F_A F_A') as an implicit operator: diagonal, dense
Cholesky, sparse (CHOLMOD) Cholesky and eigen factors (for singular
metrics) are all supported, and a dense SVD is used when the iterative
solver does not converge. The C++ Spectra kernel and the LinkingTo:
RSpectra dependency are gone. gmd_fast_cpp() remains as an alias of the
new gmd_spectra(); its maxit and seed arguments are ignored.genpls(), genplsc() and gplssvd_op() accept
svd_backend = "eigencore" (new default); "RSpectra" is accepted as a
deprecated alias..Random.seed.M and column metric A
(genpca()), following Allen, Grosenick & Taylor (2014).C = X' M X
(genpca_cov()), with eigen and gmd paths.eigen, spectra (matrix-free C++
via RSpectra), randomized, and deflation. The auto heuristic
picks among them.genpls(), genplsc())
and an operator-level interface (gplssvd_op()) that avoids
materialising whitened matrices.sfpca()), regularised PLS (rpls()), and
matrix-normal PCA via maximum residual likelihood (mnpca_mrl()).
sfpca() solves each rank-1 subproblem exactly via C++ coordinate
descent in the constraint form of Allen & Weylandt (2019), deflates
implicitly (sparse inputs never densify), and selects sparsity
penalties per component by BIC along a warm-started lambda path;
smoothness weights default to the scale-free 1 / lambda_max(Omega).
The former uthresh/vthresh quantile heuristics are deprecated.
sfpca() now returns a multivarious bi_projector (class "sfpca"),
so scores(), components(), sdev(), and reconstruct() work as
they do for genpca(). The pre-0.1 list fields $d and $u remain
readable but emit a deprecation warning.gpca_mle())."ridge", "clip", and "identity"
remediation strategies.gpca_mle() now optimizes a single penalized (MAP) matrix-normal
objective with exact block updates (sequential flip-flop covariance
updates; the ridge lambda is part of the objective), so
loglik_path is monotone non-decreasing. scale_fix is applied once
at exit as a joint, likelihood-preserving rescale (row covariance
normalized, factor absorbed into the column covariance) instead of
normalizing both factors independently during iteration, and the
returned fit is computed with the returned canonicalized metrics.
Reported log-likelihood values now include the penalty term, so they
differ numerically from previous versions.scores() on genpca fits now matches Allen, Grosenick & Taylor (2014)'s
convention (z_k = X A ov_k = ou_k d_k) and is identical to
project(fit, X) on the training data; previously the two could disagree.reconstruct.genpca(fit, colind = ) now applies the inverse
pre-processing transform to the selected columns, rather than to the
first length(colind) columns.threshold argument
of genpca(method = "deflation") and the internal SFPCA solver) are now
relative to the scale of the problem rather than absolute, so results are
invariant to rescaling the input data.constraints_remedy = "clip" now performs a real spectral clip to the
PSD cone (previously it did not clip); it requires a dense
eigendecomposition and refuses sparse input larger than 2000 rows/columns,
recommending "ridge" instead.genpca(method = "randomized") no longer mutates the caller's
.Random.seed; the C++ kernel seeds its own stream from
seed_randomized, which now fully controls reproducibility.scad_a range,
strictly positive diagonal) to the internal C++ coordinate-descent solver
used by sfpca().genpls()'s $ncomp field now reports the number of components actually
extracted, which may be less than the requested ncomp.Any scripts or data that you put into this service are public.
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.