structboost.linear_ceiling

structboost.linear_ceiling(adata, n_components, *, layer=None)[source]

Variance explainable by the best n_components-dimensional linear model.

A reconstruction MSE means little on its own. On the z-transformed input BAE expects, predicting zero everywhere scores exactly 1.0, so an MSE of 0.85 is 15% of variance explained, not “close to perfect”. Even that number needs a reference: most per-gene variance in scRNA-seq is dropout and sampling noise, so no n_components-dimensional model can reach 1. This returns that reference — the fraction captured by the leading n_components principal components, which upper-bounds any linear encoder of the same width.

Compare it against adata.uns["bae"]["variance_explained"]. A fit sitting near the ceiling is doing as well as its latent budget allows and should be given more dimensions rather than more iterations; one far below it is underfitting, and boosting_stepno or max_iterations is the lever.

Parameters:
  • adata (AnnData) – AnnData object. Uses the same matrix BAE was fitted on.

  • n_components (int) – Latent width to compare against, i.e. config.latent_dim.

  • layer (str | None) – Optional adata.layers key to use instead of adata.X. Pass the same layer the model was fitted with (adata.uns["bae"]["layer"], or absent when the fit read adata.X); a ceiling computed on a different matrix is not comparable with the model’s reconstruction.

Returns:

  • Fraction of total variance in [0, 1] captured by the top

  • n_components principal components.

Return type:

float

See also

structboost.BAE.fit

Writes uns["bae"]["variance_explained"] to compare against this ceiling.

Examples

>>> ceiling = linear_ceiling(adata, adata.uns["bae"]["latent_dim"])
>>> got = adata.uns["bae"]["variance_explained"]
>>> print(f"BAE reaches {100 * got / ceiling:.0f}% of the linear ceiling")