Skip to content

VBPCApy 0.5.0 qualification

Version 0.5 introduces native scikit-learn estimators and selection helpers with samples × features inputs. Existing 0.4 applications need an explicit migration: there is no shape guessing. The feature-first adapter remains available from vbpca_py.legacy; the low-level pca_full layout is unchanged. The migration guide and compatibility-mode comparison provide executed examples and describe the observation-policy changes.

Published artifacts are available from the GitHub release, PyPI and the version-specific Zenodo record. The Zenodo concept DOI resolves to the newest archived version.

Public compatibility changes

Contract Native 0.5 behavior Migration
Input layout Samples × features for estimators, selection and raw-cell CV Transpose old feature-first inputs or use the explicit legacy API
Fitted factors Components (q,p), joint training scores (n,q), mean (p,) Update consumers of fitted arrays
Projection fit_transform(X) returns fit(X).transform(X) conditional means Access joint variational training means through scores_
Observation mode Native estimators and selection default to modern Specify a mode explicitly for reproductions; the legacy adapter keeps its historical default
Solver options Explicit constructor parameters, string-compatible enums and frozen PCAOptions Use set_params, not mutation of .opts; unknown options fail
Stored artifacts Native estimators and prepared raw-CV folds have versioned layouts Rebuild pre-0.5 native pickles and old prepared folds; do not reinterpret their axes

Rank zero remains a supported mean-only model. Projection can return the full latent covariance through transform_posterior; ordinary transform avoids that covariance bank. New-row Gaussian scoring integrates latent scores under fitted loading means and noise. It does not integrate loading uncertainty and is distinct from cellwise PRMS/Brier selection.

Native rank-zero score/loading updates return validated empty outputs directly. This avoids the empty matrix solve that crashes with Eigen 3.3.4 in manylinux builds. A dedicated older-header CI job supplements the current-header checks.

Modern observations retain finite numeric zeros and small values. Sparse stored entries are observed and absent entries are missing; sparse conversions and probe splitting preserve stored zeros. Explicit masks are consumed before learned preprocessing and categorical expansion. The public make_xprobe_mask helper also defaults to modern splitting; historical helper-based reproduction requires compat_mode="strict_legacy". Observed raw sparse infinities are checked before duplicate aggregation. Fits refuse observed probes that would be lost when training-only empty axes are removed.

Pipeline, types and examples

Preprocessors use native estimator validation, transactional fitted state and fitted feature names. Strict numeric encoding schemas require usable affine metadata for continuous/ordinal decoding. ObservationMasker routes the original mask before expansion, including through row CV and GridSearchCV. Optional pandas and Polars outputs preserve the documented names and row order. The complete Pipeline example projects independent rows and decodes in original input units.

Public configuration/result annotations, numerical array dtypes, slotted records and ownership contracts ship with py.typed. Strict consumer typing remains a separate gate from numerical validation. Six executed gallery sources, the mixed-data notebook and maintained documentation blocks exercise the installed API; short example fits do not establish convergence or predictive calibration.

Qualified runtime changes

Marginal variance uses bounded covariance matrix products. Sparse updates reuse CSR/CSC views and avoid per-observation native heap allocations. Eligible dense, nearly complete full-covariance fits can use screened complete-minus-missing noise statistics, with observed accumulation as the fallback. The screen retains observed zeros and covariance cross terms. These changes preserve the numerical model; no universal speedup or peak-memory bound is claimed.

Historical full cost traces remain the default for PRMS selection. Explicit endpoint-only diagnostics avoid those traces when no requested stopping rule requires them. Coarse configuration recommendations no longer enable relative cost-change/composite stopping; this does not certify posterior stability. Sequential first-minimum selection has its own explicit rule and is distinct from exhaustive minimum and one-standard-error selection.

Thread tuning measures representative covariance/layout work. Opt-in execution profiles retain machine, allocation, build, BLAS and workload fingerprints; incompatible profiles are rejected. Performance CI remains advisory, with timing and allocation evidence separate from numerical parity.

Supported artifacts and release gates

Component Qualification requirement
Python CPython 3.11, 3.12, 3.13 and 3.14; free-threaded builds are excluded
scikit-learn Runtime >=1.8; native contracts and installed-wheel docs tested on 1.8.0 and 1.9.1
Wheels All four Python versions on Linux x86_64, macOS arm64 and Windows amd64: twelve wheels
Source archive Install the actual archive, run its extracted tests/API examples and build/verify its strict site
Runtime arrays NumPy and SciPy sparse; pandas through data, Polars 2 through polars, plotting through plot
Numerical checks Independent numerical references, native allocation contracts and actual Octave parity

From the release checkout:

uv sync --extra dev --extra plot --extra docs
uv run python scripts/check_release_metadata.py --tag v0.5.0
just ci
uv run python scripts/check_numerical_reference.py
uv run python scripts/check_sparse_allocations.py
just docs-check
just build-check
just build-test

The publishing workflow installs the wheel's declared dev,plot extras in each test environment, including pandas and Polars for the public container contracts. It tests the installed source archive with scripts/check_sdist_tests.py dist --qualify, requires the complete advertised artifact matrix and runs strict distribution metadata checks. The archive includes all three fixed MATLAB reference fixtures; qualification refuses missing fixtures so the associated regressions cannot silently skip. A manual workflow dispatch builds and qualifies artifacts without uploading to PyPI or TestPyPI. Production upload runs only for a published GitHub release, after the qualification jobs pass.

Frozen scientific installations retain their registered versions and policies until their owners record an adoption decision. This compatibility release does not retune scientific stopping/default policies or change frozen application runs.