structboost.StabilitySelectionResult¶
- class structboost.StabilitySelectionResult(frequency, stable_support, threshold, avg_selected, expected_false_positives, n_subsamples, subsample_frac, mode='subsample', n_iterations=0, dim_match_quality=nan, coefficient_cond_mean=None, coefficient_sd=None, sign_consistency=None)[source]¶
Bases:
objectResult of
structboost.stability_selection().- Parameters:
stable_support (numpy.ndarray)
threshold (float)
expected_false_positives (ndarray[tuple[Any, ...], dtype[float64]])
n_subsamples (int)
subsample_frac (float)
mode (str)
n_iterations (int)
dim_match_quality (float)
coefficient_cond_mean (ndarray[tuple[Any, ...], dtype[float64]] | None)
coefficient_sd (ndarray[tuple[Any, ...], dtype[float64]] | None)
sign_consistency (ndarray[tuple[Any, ...], dtype[float64]] | None)
- frequency¶
Per-gene, per-dimension selection frequency, shape
(n_genes, latent_dim). Entry(g, j)is the fraction of subsamples in which genegreceived a nonzero coefficient for latent dimensionj.- Type:
NDArray[np.float64]
- stable_support¶
Boolean mask
frequency >= threshold, shape(n_genes, latent_dim).- Type:
BoolArray
- avg_selected¶
Mean number of genes selected per subsample, per dimension, shape
(latent_dim,). This is theqin the error bound below.- Type:
NDArray[np.float64]
- expected_false_positives¶
Meinshausen-Bühlmann upper bound on the expected number of falsely stable genes per dimension,
E[V] <= q^2 / ((2*threshold - 1) * p), shape(latent_dim,). Hereqis the average number of competitively selected genes andpthe number of candidate genes; forced (mandatory) genes are excluded from both, since they are always selected by construction and are not candidates.NaNwhenthreshold <= 0.5(the bound is undefined there) or when every gene is mandatory. The bound holds under the paper’s exchangeability and “no worse than random guessing” assumptions, which real data may violate; treat it as a guideline, not a guarantee.- Type:
NDArray[np.float64]
- n_subsamples¶
Number of subsamples drawn.
0formode="iteration", which draws no subsamples.- Type:
- mode¶
Which resampling scheme produced the frequencies.
"subsample"Meinshausen-Bühlmann cell subsampling with the model frozen. Targets variance under cell resampling.
frequencyis per latent dimension andexpected_false_positivescarries the paper’s error bound."iteration"Selection frequency across additional training iterations of a single fit. Targets variance from the optimizer’s position on its loss plateau, which is a different — and on measured data, larger — source of instability.
frequencyis per latent dimension, with each iteration’s dimensions matched to the fitted model’s before counting — seedim_match_quality.expected_false_positivesisNaN: training iterations are neither independent nor exchangeable, so the Meinshausen-Bühlmann bound does not apply and no error control is claimed.
- Type:
- coefficient_cond_mean¶
Shape
(n_genes, latent_dim), orNonewhen coefficients were not collected. Mean coefficient over the runs in which each entry was selected — reliability-blind but scale-preserving, since its expectation equals the per-run coefficient. Feedsstable_encoder().- Type:
NDArray[np.float64] | None
- coefficient_sd¶
Standard deviation of the same conditional distribution. This is a spread, not a standard error: subsample runs share half their cells by construction and iteration runs are autocorrelated, so the effective sample size is far below
n_runsandsd / sqrt(n_runs)would be badly overconfident. Reporting it as a precision would require a block bootstrap.- Type:
NDArray[np.float64] | None
- sign_consistency¶
Fraction of selecting runs in which each coefficient took its modal sign. A gene selected every time with a sign that flips is not stable, which a selection frequency alone cannot reveal. Measured at ~0.999 on real data, so in practice a guard rather than a headline.
- Type:
NDArray[np.float64] | None
- dim_match_quality¶
mode="iteration"only: mean absolute cosine similarity between each iteration’s latent dimensions and the fitted model’s, after optimal matching. Per-dimension frequencies are only meaningful when dimensions keep their identity across iterations, and this quantifies that rather than assuming it. Near 1 means the anchoring held; low values mean the per-dimension split should not be trusted andfrequency.max(axis=1)(the flat union) is the safer readout.NaNformode="subsample".- Type:
Methods
__init__(frequency, stable_support, ...[, ...])Aggregate the per-run coefficients into a more reproducible encoder.
Attributes
Mean coefficient over all runs, counting unselected runs as zero.
Number of resampling runs, whichever mode produced this result.
- property coefficient_mean: ndarray[tuple[Any, ...], dtype[float64]] | None¶
Mean coefficient over all runs, counting unselected runs as zero.
Equals
coefficient_cond_mean * frequency, so a gene selected in 40% of runs is shrunk to 40% of its typical weight — shrinkage proportional to reliability. Statistically the more principled estimator, but it changes the latent scale the decoder was trained against, which is whystable_encoder()does not offer it.
- stable_encoder()[source]¶
Aggregate the per-run coefficients into a more reproducible encoder.
Among stably selected entries the run-to-run coefficient spread is large (CV ~0.34 median on measured data), so the support of a fit is more reproducible than its weights. This returns the conditional mean coefficient restricted to the stable support: the frequency threshold decides which genes, the conditional mean decides how much.
Measured on simulated data against exact ground truth, with the decoder left untouched, it improves on the fitted encoder on every axis that matters for selection:
encoder
precision
FDR
genes
fitted
0.62
0.38
156
this
0.74
0.26
116
and raises reconstruction from 55% to 59% of the linear ceiling. The same ordering holds under batch conditioning (precision 0.754 vs 0.691, FDR 0.246 vs 0.309). Because the latent scale is preserved, the result can be installed with
BAE.apply_encoder()without refitting the decoder.To trade precision for recall, lower
thresholdwhen callingBAE.stability_selection()rather than reaching for a different estimator — the threshold is that dial. An unmasked conditional mean is simply this withthresholdat zero, and it was measured to be a worse selector at every setting tried (precision 0.47 unconditioned, 0.56 conditioned) as well as numerically fragile on batch-dominated fits, where it produced a reconstruction worse than predicting zero.- Returns:
ndarray of shape
(n_genes, latent_dim)– Same orientation asfrequencyandadata.varm.- Raises:
ValueError – If coefficients were not collected for this result.
- Return type: