Skip to content

Commit fefe5de

Browse files
authored
Merge pull request #172 from PLN-team/release-1.3-0
moving DEVLOG in inst directory + synthesis
2 parents 6491dc8 + cb639ca commit fefe5de

4 files changed

Lines changed: 98 additions & 1 deletion

File tree

.Rbuildignore

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,11 +33,11 @@
3333
^inst/simus_ZIPLN$
3434
^inst/benchmark$
3535
^inst/binom$
36+
^inst/devlog$
3637
^\.github$
3738
^data-raw$
3839
^CRAN-SUBMISSION$
3940
^AUTHORS$
4041
^dev$
4142
^\.claude$
42-
^DEVLOG.*\.md$
4343
snowflake.log
File renamed without changes.
File renamed without changes.
Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
---
2+
title: "Synthèse des sessions de développement — optimiseurs PLNmodels"
3+
subtitle: "8-17 juin 2026 (branche `code-enhancement`) et 2-3 juillet 2026 (branche `optim-plnpca`)"
4+
date: 2026-07-03
5+
format:
6+
html:
7+
toc: true
8+
toc-depth: 3
9+
number-sections: true
10+
---
11+
12+
Ce document consolide les journaux de développement `DEVLOG_2026-06-08-17.md` et
13+
`DEVLOG_2026-07-02-03.md` (racine du dépôt) en une synthèse : l'état effectivement
14+
implémenté dans le package, les pistes explorées avec leur verdict, et un résumé
15+
bref des bugs corrigés. Le détail complet (chiffres, code, benchmarks) reste dans
16+
les DEVLOG originaux ; ce document sert de point d'entrée rapide.
17+
18+
# Ce qui est effectivement implémenté dans le package aujourd'hui
19+
20+
## Architecture commune (`covariance_pln.h`)
21+
22+
Les cinq structures de covariance PLN (full, diagonal, spherical, fixed, **genpop**)
23+
partagent un unique moteur via CRTP statique (`CovTraitsBase<Derived>`) :
24+
gradient/objectif/pas de Newton joint (M, ψ) factorisés une seule fois, plus
25+
`diag_scale`/`add_diag` pour éviter les allocations p×p inutiles. Le CRTP statique a
26+
été préféré au polymorphisme virtuel : pas de vtable dans la boucle chaude, `has_em`
27+
exploité comme `constexpr bool` dans un `if constexpr`, et `State` de forme variable
28+
selon la structure (matrice dense, `rowvec`, ou deux `double`). ZIPLN réutilise cette
29+
même machinerie (`A_eff = (1-R) ⊙ A`, `w = ones(n)`) au lieu d'un second jeu de
30+
formules dupliqué.
31+
32+
## Backends par modèle (état final)
33+
34+
| Modèle | Défaut | Backends disponibles | Optimiseur `builtin` |
35+
|---|---|---|---|
36+
| PLN / PLNLDA | **nlopt** (`profiled=TRUE`) | nlopt, builtin, torch (exp.) | Newton joint (M,ψ), B profilé par enveloppe |
37+
| PLNPCA | **nlopt** | nlopt, builtin, torch (exp.) | Newton profilé à région de confiance (Steihaug-CG préconditionné) — remplace l'ancien spectral BB |
38+
| PLNnetwork | **builtin** (`maxit_ve=1`, inception builtin K=5) | builtin, nlopt | Newton VE-step + M-step glasso |
39+
| ZIPLN | **builtin** | builtin, nlopt | Newton joint (M,ψ,R), B profilé |
40+
| ZIPLNnetwork | **builtin** (depuis le 18/06) | builtin, nlopt | idem ZIPLN + glasso |
41+
| PLNmixture | builtin | builtin, nlopt, torch (exp.) | composants PLNfit standards |
42+
43+
## Autres changements livrés
44+
45+
- Normalisation uniforme des covariables (`normalize_covariates()`) dans tous les `optimize()`.
46+
- `future`/`future.apply``parallel::mclapply` (10 sites), pilotable via `options(mc.cores=N)`.
47+
- Init ZIPLN par LM + GLM binomial (`pscl` retiré des dépendances, ×60-240 plus rapide).
48+
- Init PLNPCA par LM par défaut ; EM tronqué (`init_method="EM"`) en option pour les grands rangs.
49+
- `PLNnetwork`/`ZIPLNnetwork` héritent correctement de `config_optim` pour leur modèle d'inception.
50+
- README.qmd (exécuté, sur `barents`) et vignette ZIPLN (sur `microcosm`) ajoutés.
51+
- 5ᵉ covariance `genpop` (héritabilité, $\Sigma = \sigma^2(\rho C + (1-\rho)I)$) câblée pour `PLN()` seul.
52+
53+
## Session de juillet (branche `optim-plnpca`, en cours)
54+
55+
Nouveau backend `builtin` pour PLNPCA : Newton profilé à région de confiance avec
56+
complément de Schur, remplaçant l'ancien optimiseur spectral (supprimé). `nlopt`
57+
reste le défaut.
58+
59+
# Pistes explorées — conservées vs abandonnées
60+
61+
| Piste | Statut | Pourquoi |
62+
|---|---|---|
63+
| Newton coordonnée (`homemade`) puis B profilé par enveloppe (`homemade_alt`) | **Conservé**, fusionné en un seul backend `builtin` | B profilé + Armijo à pente projetée (Q_step) élimine le cold-start et bat l'ancienne version partout |
64+
| `hybrid` (nlopt → Newton) | **Abandonné**, supprimé | Ne dépasse jamais `builtin` seul, systématiquement plus lent |
65+
| Hessienne M exacte (bloc p×p par obs.) / `block_newton_thresh` | **Abandonné**, supprimé | Coût O(np³) prohibitif, aucun gain de loglik vs l'approximation diagonale par blocs |
66+
| Pas Newton conjoint (M,ψ) avec terme croisé | **Conservé** | Capture le couplage M-S, remplace le point fixe séparé (plus lent) |
67+
| Warm-start Ω dans GLASSO (intra/inter-modèles) | **Abandonné**, reverté | Pire en qualité ET en temps (Σ change trop entre itérations / path de pénalités dans le mauvais sens) |
68+
| `maxit_ve` (E-step Newton partiel) pour PLNnetwork/ZIPLNnetwork | **Conservé** | Neutralise les oscillations de l'alternance GLASSO↔VE-step sur-convergée |
69+
| Inception tronquée (`inception_niter`, `init_method="EM"`) | **Conservé**, en option | Aide les grands rangs/modèles pénalisés (M "à mi-chemin") ; nuit aux petits rangs (sur-convergence) — sweet spot K=2–10 |
70+
| `approx_ZI` (formule Lambert W "exacte" pour R) | **Abandonné**, supprimé | La formule σ(·) est l'optimum exact de l'ELBO ; Lambert W optimise une autre fonctionnelle et donne un ELBO pire de 77-86 points |
71+
| L-BFGS bloc-alterné (EM) pour PLNPCA | **Abandonné** | 7-10× plus lent que le joint, gain de loglik nul (convergence EM extérieure linéaire) |
72+
| L-BFGS joint + Wolfe fort (PLNPCA, ancien "builtin") | **Conservé un temps puis remplacé** en juillet | Battait nlopt sur 6/9 cas, mais surclassé par le nouveau Newton région de confiance (juillet) |
73+
| SQUAREM (accélération EM) sur ZIPLN/PLNmixture | **Abandonné** (pas de défaut) | Coupe les cycles externes mais chaque cycle coûte plus cher ; net plus lent (25-40%) ; léger mieux d'ELBO seulement |
74+
| Newton région de confiance + Schur pour PLNPCA | **Conservé**, devient `builtin` | Bat nlopt et l'ancien builtin sur qualité et vitesse ; convergence lente à grand n comprise et acceptée (indéfini du Hessien réduit) |
75+
| Garde-fou CG "stop si résidu grossit" | **Abandonné** | Empire les résultats (les itérations errantes produisent quand même de bons pas) |
76+
| Warm-start entre rangs PLNPCA (`sequential`) | **Abandonné par défaut**, gardé en option | Net négatif pour Newton-TR (coût dans la rampe indéfinie, pas dans la distance à l'init) |
77+
| GLTR/Lanczos (solveur TR indéfini exact) | **Non retenu** | ROI incertain, ~150 lignes, pas déjà quasi-exacts |
78+
79+
# Bugs corrigés (résumé)
80+
81+
- `ifelse()` au lieu de `if/else` dans le dispatch backend de PLNLDAfit (diagonal/spherical) → crash torch.
82+
- `PLNfit_fixedcov` : VE-step manquant dans `setup_optimizer` → crash `predict(level=1)`.
83+
- PLNmixture : clé `maxit_out` au lieu de `maxit_em` → smoothing 25× trop lent.
84+
- `do.call` sensible à l'ordre des noms dans jackknife/bootstrap PLNfit.
85+
- M sans `colnames` après VE-step → perte des noms d'espèces en prédiction.
86+
- `latent_pos` de PLNmixturefit utilisait M_full au lieu de M_res → k-means biaisé.
87+
- `compute_PLN_starting_point` : NA non protégés, `singular.ok=FALSE` rendait un garde-fou inaccessible.
88+
- `extract_model` : détection de formule incomplète (`is.symbol``!inherits`).
89+
- Gradient faux dans `nlopt_optimize_vestep_spherical` (signe/direction M vs ω²).
90+
- `solve()` sur matrice 0×0 quand formule sans covariable (`~0`).
91+
- Initialisation M de PLNPCA : mauvais indexage SVD (`v[1:q,1:q]` au lieu des colonnes) → résidu ‖M·Cᵀ−M_PLN‖ divisé par ~100 après fix.
92+
- Bug XTOL nlopt prématuré sur covariables mal conditionnées (barents Depth~300) → régression majeure (+4118 ll après fix).
93+
- ZIPLNnetwork bloqué à `nlopt` par un `stopifnot` alors qu'architecturalement compatible avec builtin.
94+
- `browser()` oublié en debug dans ZIPLNfit.
95+
- Warning igraph (`frame.color` NA comme attribut au lieu d'argument `plot()`).
96+
- Signe de `dJ/dρ` dans la bissection de la covariance `genpop` (ρ convergeait toujours vers la borne basse).
97+
- (Session juillet) crash `solve()` et non-convergence à l'échelle pour le nouveau Newton-TR PLNPCA (tolérance absolue au lieu de relative) ; normalisation X incompatible avec la région de confiance.

0 commit comments

Comments
 (0)