PLNnetwork()andZIPLNnetwork()now use an internal graphical Lasso, a C++ port of the GLASSOFAST algorithm (Sustik and Calderhead, 2012) shared with the normalblockr package, instead of callingglassoFast::glassoFast(). glassoFast is no longer a dependency (it moves toSuggests, for tests only).- The motivation is robustness: glassoFast's Fortran routine could loop forever on a nearly collapsed covariance matrix (entries of order 1e-8, as a rank-deficient residual covariance produces), in compiled code that no R-level timeout could stop. The new solver always terminates (non-finite input and zero-variance coordinates are rejected, the inner coordinate descent is bounded), reports non-convergence instead of hanging, and can be interrupted from R, by the user or by
setTimeLimit()/R.utils::withTimeout(), which then raise their usual error. - On ordinary input, results are those of glassoFast up to machine precision: identical supports along penalty paths and relative differences below 1e-15 on the precision matrix, for scalar as well as weighted penalties with an unpenalized diagonal;
PLNnetwork()andZIPLNnetwork()fits with the default"builtin"backend are unchanged (log-likelihoods within 1e-11). Fits withbackend = "nlopt"can differ slightly along the path: that backend is sensitive to perturbations at the level of the last floating-point digit. Speed is the same or slightly better. - The solver is exported as
graphical_lasso(S, rho, thr, maxit, w_init, wi_init), returningw,wi,niter,converged,statusanddelta, with the same defaults as glassoFast and an optional warm start. - It stops when it is cycling rather than converging. On an ill-conditioned covariance (ie rank-deficient, as
PLNnetwork()produces when p ~ n) the sweeps settle into a small limit cycle: the convergence criterion stops decreasing and oscillates just above its threshold forever. glassoFast spends its whole 10000-sweep budget on these and reports success regardless. The cycle is now detected after 1000 sweeps without progress (tunable throughstall_patience), and reported asstatus = "stalled". - Non-convergence of the graphical Lasso is recorded in the fits' monitoring (
$optim_par$glasso_nonconvergedand$optim_par$glasso_stalled, counted along the alternating optimization). A warning is now raised only for the numerical failures ("degenerate","inner_failure","max_iter"), not for a stalled solve, which says something about the problem (too weak a penalty for a nearly rank-deficient covariance) rather than about the solution. - Behaviour change in a degenerate case: when the covariance matrix has no off-diagonal mass, the (diagonal) precision matrix is now the correct
1 / (S_ii + rho_ii), where glassoFast returned1 / max(rho_ii, 1.1e-16).
- The EBIC of
PLNnetworkfitandZIPLNfit_sparseis now the one of Foygel and Drton (2010),BIC - 2 gamma |E| log(p), which was designed for the graphical Lasso, instead of the Stirling approximation of Chen and Chen (2008)'s original criterion that was used so far. The tuning parameter is exposed as$ebic_gamma(default0.5,0gives back the BIC), on a single fit or on a whole collection. EBIC values change, and so may the model selected bygetBestModel("EBIC"). - The
$densityof a network is now|E| / (p (p - 1) / 2): it divided the edge count byp^2rather than by the number of possible edges, and was thus understated by a factor(p - 1) / p. - In the
igraphoutput ofplot()on a network fit, the opacity of an edge is now proportional to the strength of its partial correlation, as its width already was. Dense networks are no longer a solid blob of colour. The opacity of the weakest edge is the newedge.alphaargument (default0.2, set it to1to restore uniformly opaque edges).
-
PLNPCA()'s variational bound carried a spuriousp / 2per observation, the entropy constant of the full-covariance models: a rank-qmodel's variational distribution is over theq-dimensional scores, and itsq / 2constant was already in the Kullback-Leibler term.loglik,BICandICLof everyPLNPCAfittherefore decrease byn * p / 2. Rank selection is unchanged (the term does not depend on the rank), but aPLNPCA()fit is now comparable with aPLN()one, or with any other model. Reported by Nguyen Quang Huy (Actuarial Science Laboratory, National Economics University, Vietnam). -
PLNnetwork()andZIPLNnetwork()no longer fail outright when one model along the penalty path cannot be fitted: the collection is truncated with a warning instead, andstability_selection()treats a model with no estimated network as fully unstable. A second line of defense on top of the solver above (thanks @rfriedman22, #176).
ZIPLNnetwork()fitted its inception with the regularization path's truncated optimizer which is appropriate for models that are warm-started from one another, but the inception starts from scratch and was given the same budget. The inception is now fitted with an untruncated optimizer, asPLNnetworkfamily.
-
New built-in Newton optimizer (
backend = "builtin") for PLN, ZIPLN and PLNnetwork: envelope-theorem Newton steps with strong Wolfe line search, no dependency on NLOPT. Substantially faster and more accurate than nlopt on large datasets with full covariance. -
PLNPCA's
"builtin"backend rewritten as a profiled trust-region Newton: the variational block(M, S)is profiled out with a per-observation Newton VE-step, and the loadings(B, C)are optimised with a saddle-aware trust-region Newton on the resulting objective (analytic Schur-complement Hessian-vector products, Jacobi-preconditioned Steihaug-CG) — replacing the previous spectral projected-gradient"builtin". It reliably reaches a higher variational bound than"nlopt"at comparable-to-better speed; tuning keyscg_maxit,maxit_out,ftol_out,gtol,delta0inconfig_optim(see?PLNPCA_param)."nlopt"remains the default forPLNPCA. -
Backend defaults revisited package-wide, based on extensive benchmarking: PLN and PLNPCA keep
"nlopt"(PLN now consistently faster thanks toprofiled = TRUE, see below); PLNnetwork and ZIPLNnetwork now default to"builtin", which finds a better optimum at a modest speed cost; ZIPLN keeps its"builtin"default. All backends remain configurable via thebackendargument; see the corresponding*_param()documentation for the trade-offs. Thetorchbackend is now clearly marked experimental everywhere. -
Quality and speed improvements:
config_optim$profiled = TRUEis now the default for full-covariance nlopt fits (faster, slightly better loglik); ZIPLN's variational step now optimises(M, ψ, R)jointly via Newton instead of sequentially; PLNPCA shares a single SVD initialisation across ranks and can warm-start from a pre-fittedPLNfitfor large ranks (inception/init_method, see?PLNPCA_param); ZIPLN's starting point no longer relies onpscl::zeroinfl(now an internal LM + binomial GLM routine), which is both much faster and a better starting point —psclis no longer a dependency. -
Fixed a critical nlopt convergence bug affecting PLN/PLNPCA: ill-conditioned covariate scaling could trigger the XTOL stopping criterion after very few iterations, well before convergence. The built-in backend was never affected; nlopt is now also fixed via better parameter scaling.
- Shared covariance abstraction: the optimization machinery for PLN's covariance structures (full, diagonal, spherical, fixed) is now expressed once via a small set of C++ traits (
CovTraitsBaseincovariance_pln.h) instead of being duplicated per structure. PLNPCA and ZIPLN's variational step now reuse the same machinery instead of separate hand-rolled implementations, removing a substantial amount of duplicated code and fixing minor inefficiencies along the way (e.g. ZIPLN's VE-step used to treat the precision matrix as dense even for diagonal/spherical covariance, at unnecessaryO(np^2)cost). - Consistent C++ naming: exported optimizer functions across PLN, PLNPCA and ZIPLN now follow the same
{backend}_optimize_{structure}convention.
-
Uniform covariate normalization: a
normalize_covariates()helper (zero mean, unit variance per column) is now applied consistently in alloptimize()methods (PLN, PLNPCA, PLNnetwork, ZIPLN). This makes the nlopt XTOL criterion scale-invariant and stabilises the torch backend. -
Parallelism backend:
future.apply::future_lapplyis replaced byparallel::mclapplythroughout (stability selection for PLNnetwork / ZIPLNnetwork). Useoptions(mc.cores = N)to set the number of cores. -
Bug fixes: PLNnetwork/ZIPLNnetwork's inception (warm-start) model didn't inherit
ftol_em/maxit_emfrom the user'sconfig_optim, silently falling back to defaults and producing a wrong penalty grid; the PLNPCA rank-model objective usedA − Ywhere it should useA − Y ⊙ Z; various ZIPLN prediction/initialization fixes (#146, #149, #150, #152). -
microcosm data now included (#153, #154); AIC added for PLN and ZIPLN classes (#151); other fixes (#155).
-
CRAN check fixes (no user-visible effect): removed an unused
-fopenmpcompilation flag insrc/Makevarsthat was inadvertently turning on Armadillo's internal OpenMP parallelisation and inflating the CPU/elapsed time ratio of several examples; fixed a GCC-Wmismatched-new-deletefalse positive insrc/packing.cpp's internal test helper by restructuring the code (no diagnostic-suppressing pragma involved).
- fix for #143 (remove LBFGS_NOCEDAL variant from the possible algorithms)
- fix NOTES in CRAN due to missing packages in \link{} (PR #142)
- Now requires R >= 4.1.0 because package code uses the pipe |> (PR #142)
- fix sandwich variance estimation (PR #140)
- fix use of native pipe to ensure compatibility with R 3.6 (merge PR #125, fix #124)
- new feature: ZIPLN (PLN with zero inflation) for standard PLN and PLN Network
- ZIPLN() and ZIPLNfit-class to allow for zero-inflation in the standard PLN model (merge PR #116)
- ZIPLNnetwork() and ZIPLNfit_sparse-class to allow for zero-inflation in the PLNnetwork model (merge PR #118)
- Code factorization between PLNnetwork and ZIPLNnetwork (and associated classes)
- fix inconsistency between fitted and predict (merge PR #115)
- Update documentation of PLN*_param() functions to include torch optimization parameters
- Add (somehow) explicit error message when torch convergence fails
- Change initialization in
variance_jackknife()andvariance_bootstrap()to prevent estimation recycling, results from those functions are now comparable to doing jackknife / bootstrap "by hand". - Merge PR #110 from Cole Trapnell to add:
- bootstrap estimation of the variance of model parameter
- improved interface for model initialization / optimisation parameters, which are now passed on to jackknife / bootstrap post-treatments
- better support of GPU when using torch backend
- Change behavior of
predict()function for PLNfit model to (i) return fitted values if newdata is missing or (ii) perform one VE step to improve fit if responses are provided (fix issue #114)
- changed initial value in optim for variational variance (1 -> 0.1) in VE-step of PLN and PLNPCA
- fix sign in objective of VE_step for PLN with full covariance Issue #100
- add a
scaleargument compute_offset() to force the offsets (RLE, CSS, GMPR, Wrench) to be on the same scale as the counts, like TSS. - add a new "TMM" for compute_offset()
- fix nb_param for PLNLDA, which caused wrong BIC/ICL and erratic model selection
- fix minor issues #102, #103 plus some others
- fix package file documentation as suggested in r-lib/roxygen2#1491
- higher tolerance on a single test (among 700) that fails on the 'noLD' additional architecture on CRAN (tests without long double)
- changed initial value in optim for variational variance (1 -> 0.1), which caused failure in some cases
- fix bug when using inception in PLNnetwork()
- starting handling of missing data
- slightly faster (factorized) initialization for PCA
- fix in the use of future_lapply which used to make post-Treatments in PLNPCA last for ever with multicore in v1.0.0...
- prevent use of bootstrap/jackknife when not appropriate
- fix bug in PLNmixture() when the sequence of cluster numbers (
clusters) is not of the form1:K_max - use bibentry to replace citEntry in CITATION
-
interface for controlling the fits now use list generated by dedicated functions
- PLN_param() for PLN
- PLNLDA_param() for PLNLDA
- PLNnetwork_param() for PLNnetwork
- PLNPCA_param() for PLNPCA
- PLNmixture_param() for PLNmixture The use of 'control = list()' is deprecated: the code stop and send an error.
-
The regression coefficients are now denoted by B, not Theta, such as B = t(Theta). We keep on sending back Theta as a field of myPLN$model_par$Theta, but this will soon be deprecated
- added Barents fish data set
- support for PLN when (inverse) covariance is known/fixed
- estimator of the variance of the model parameters
- integration of sandwich estimator of the variance-covariance of Theta when Sigma is fixed
- variational estimation of the variance-covariance based on variational approximation of the Fisher information
- jackknife estimation of the variance of Theta and Sigma
- bootstrap estimation of the variance of Theta and Sigma
- handle list of penalty weights in PLNnetwork
- first support for torch optimizers (for PLN and PLNLDA)
- fix in objective functions of ve_step of standard PLN models
- fix in objective functions of main of standard PLN models
- fix expression of ELBO in VEstep, related to #91
- typos and regeneration of documentation( HTML5)
- added an S3 method predict_cond to perform conditional predictions
- fix #89 bug by forcing an intercept in
PLNLDA()and changingextract_model()to conform withmodel.frame()
- fix wrong use of all.equal
- fix linking problem in new version of nloptr (>=2.0.0)
- fixing #79 by using the same variational distribution to approximate the spherical case as in the fully parametrized and diagonal cases
- faster examples and build for vignettes
- additional R6 method
$VEStep()for PLN-PCA, dealing with low rank matrices - additional R6 method
$project()for PLN-PCA, used to project newdata into PCA space - use future_lapply in PLNmixture_family
- remove a NOTE due to a DESeq2 link and a failure on solaris on CRAN machines
- some bug fixes
- use future_lapply in PLNPCA, PLNmixture and stability_selection (plan must be set by the user)
- bug fix in prediction for PLN-LDA
- bug fix in gradients of PLN-network and PLN-spherical
- suppressing method
$latent_pos()which is equivalent to active binding$latent - finalizing integration of PLNmixture (in particular faster smoothing)
- added an argument 'reverse' to the plot methods for criteria, so that users can get their "usual" BIC definition (-2 loglik)
- support for covariates in PLNmixture (spherical, diagonal, full)
- more support for PLNmixture (S3/R6 methods, vignette)
- Rewriting C++ by merging modern_cpp to dev, thanks to François Gindraud
- various bug fixes in offset
- less verbose about R squared when questionable
- correction in BIC/ICL for PLNPCA
- Enhanced vignettes for PLNPCA and PLNmixture
- Add compatibility with factoextra for PLNPCA
- Add development version of PLNmixture
- add type = "poscounts" option to RLE normalization
- added wrench normalization to the list of available offsets
- added the oaks data set from Jakuschkin et al (2016)
- Correction in likelihood of diagonal PLN
- amending test-pln to fulfill CRAN request (error on ATLAS variant of BLAS...)
- Refactor code of R6 classes to benefit from Roxygen 7.0.0 R6-related new features for documentation
- Change name of variational variance parameters to S2 (used to be S)
- use spell_check to check spelling, found many typos
- Change in optimization for all PLN models (PLNs, PCA, LDA, networks): solving in S such that S = S² for the variational parameters, thus avoiding lower bound and constrained optimization. Slightly finer results/estimations for similar computational cost, but easier to maintain.
- Fix bug in predict() methods when factor levels differ between train and test datasets.
- Fix bug in PLNPCAfit S3 plot() method
- Some simplification in C++ code
- correction/changes in PLN likelihoods? + added constant terms in all likelihoods of all PLN models
- VEstep now available for all model of covariance in PLN (full, diagonal, spherical)
- removed any use of rmarkdown::paged_table() in the vignettes
- added screenshot.force = FALSE, in knitr options in the vignettes
- removing dependencies to bioconductor packages, too cumbersome to maintain on CRAN
- correction in test to comply new class of matrix object
- added the possibility for matrix of weights for the penalty in PLNnetworks
- various bug fixes
- Use nloptr to prepare CRAN release
- Enhancement in PLNLDA
- Preparing first CRAN release
- Added a
NEWS.mdfile to track changes to the package.