spacr.mixed_gpu¶
Fit profiled REML mixed models with PyTorch on CPU or CUDA.
The backend fits the same nested random-intercept model as statsmodels
MixedLM:
- y = X b + sum_k Z_k u_k + e, u_k ~ N(0, sigma^2 theta_k I),
e ~ N(0, sigma^2 I)
The group intercept supplies one Z_k and each variance component supplies
another, nested within the outer group as in MixedLM.vc_formula. For
example, vc_formula={'rowID': '0 + C(rowID)'} with groups=gene
represents (1 | gene:rowID), not (1 | rowID).
The implementation evaluates the profiled REML deviance from Bates et al. (2015, equation 41):
- d(theta) = log|Lambda’ Z’Z Lambda + I| + log|X’ W^-1 X|
(n - p) [1 + log(2 pi r^2 / (n - p))]
Here Lambda = diag(sqrt(theta)), W = I + Z Lambda^2 Z', and r^2
is the minimized penalized residual sum of squares. Device-side cross-products
Z'Z, Z'X, Z'y, X'X, X'y, and y'y are computed once.
Each optimizer evaluation then requires a q x q Cholesky factorization and
triangular solves. Autograd differentiates the deviance and L-BFGS optimizes
log(theta), which enforces positive variance ratios.
Reference measurements explain where acceleration is expected. Statsmodels
MixedLM took 54 times as long as OLS on a 40-gene screen and 67 times as
long on an 80-gene screen. At q = 1212, the Cholesky step took 204 ms on
the CPU and 7.69 ms on an RTX 3090. For a design with 1,830 observations, 387
genes, 710 guides, 388 fixed effects, and 1,097 random levels, end-to-end times
were 11.3 s for statsmodels, 0.80 s for this backend on CPU, and 0.47 s on the
RTX 3090. Use benchmark_against_statsmodels() to measure the supported
backends on another design and device.
Selecting a CUDA device never falls back silently to CPU. If PyTorch or CUDA
is unavailable, MixedBackendUnavailable explains what is missing.
Exceptions¶
Indicate that PyTorch or the requested compute device is unavailable. |
Classes¶
Store a PyTorch REML fit with statsmodels-compatible result fields. |
Functions¶
|
Return the bytes currently available on a CPU or CUDA device. |
|
Fit the same mixed model with statsmodels and PyTorch and compare them. |
|
Return whether PyTorch can use a CUDA device at call time. |
|
Describe the installed PyTorch and CUDA device for logs or tooltips. |
|
Return the byte size of a dense |
|
Fit |
|
Fit a formula mixed model with the PyTorch REML backend. |
|
Resolve a device string without silently substituting the CPU. |
|
Return whether PyTorch is importable without importing it. |
Module Contents¶
Bases:
RuntimeErrorIndicate that PyTorch or the requested compute device is unavailable.
Initialize self. See help(type(self)) for accurate signature.
- class spacr.mixed_gpu.TorchMixedResults[source]¶
Store a PyTorch REML fit with statsmodels-compatible result fields.
fe_params,pvalues,random_effects,converged, residuals, and fitted values use the meanings expected byspacr.ml.fit_mixed_model(). Variance entries inparamsandthetaare relative to residual variance;cov_reandvcompare absolute variances on the response scale.device,fit_seconds,n_deviance_evals, andgradient_normrecord backend diagnostics.- Parameters:
fe_params – Estimated fixed-effect coefficients indexed by fixed-design column.
bse_fe – Standard errors of the fixed-effect coefficients, indexed like
fe_params.params – Combined statsmodels-shaped vector of fixed-effect coefficients followed by variance ratios.
bse – Standard errors aligned with
params; variance-ratio entries arenanbecause this backend does not estimate their standard errors.tvalues – Fixed-effect z statistics aligned with
params; variance-ratio entries arenan.pvalues – Two-sided standard-normal p-values aligned with
params; variance-ratio entries arenan.scale – Estimated residual variance on the response scale.
cov_re – One-by-one covariance matrix for the outer-group random intercept on the response scale.
vcomp – Absolute variances of the nested variance components, in the input component order.
random_effects – Conditional random-effect estimates keyed by outer-group level, with statsmodels-compatible component labels.
resid – Conditional residuals,
y - fittedvalues, in input-observation order.fittedvalues – Conditional fitted values including fixed and random effects, in input-observation order.
converged – Whether the final log-variance gradient norm is below the backend’s reported-convergence threshold of
1e-3.llf – Restricted log-likelihood at the reported solution.
n_obs – Number of observations included in the fit.
k_fe – Number of fixed-effect coefficients.
backend – Backend identifier recorded in logs and run metadata.
device – PyTorch device used for the fit.
fit_seconds – Wall-clock seconds spent in L-BFGS optimization.
n_deviance_evals – Number of profiled-deviance evaluations performed during optimization and finalization.
theta – Variance ratios relative to residual variance, ordered as the outer-group intercept followed by nested components.
gradient_norm – Euclidean norm of the final gradient with respect to log variance ratios.
- spacr.mixed_gpu.available_memory(device: str = 'cpu') int[source]¶
Return the bytes currently available on a CPU or CUDA device.
- spacr.mixed_gpu.benchmark_against_statsmodels(y, X, groups, vc=None, *, device: str = GPU_DEVICE)[source]¶
Fit the same mixed model with statsmodels and PyTorch and compare them.
- Parameters:
y (array-like) – Response values with shape
(n_observations,).X (array-like) – Fixed-effects design with shape
(n_observations, n_fixed_effects).groups (array-like) – Outer grouping labels with shape
(n_observations,).vc (mapping of str to array-like, optional) – Nested variance-component labels.
device (str, optional) – Device used by the PyTorch fit.
- Returns:
dict – Timings, speedup, maximum fixed-effect and variance-component disagreement, residual-scale disagreement, resolved device, and PyTorch deviance-evaluation count.
- spacr.mixed_gpu.cuda_available() bool[source]¶
Return whether PyTorch can use a CUDA device at call time.
This function imports PyTorch and is intended for fit-time validation, not lightweight settings-panel construction.
- spacr.mixed_gpu.describe_device() str[source]¶
Describe the installed PyTorch and CUDA device for logs or tooltips.
- spacr.mixed_gpu.design_bytes(n: int, q: int, *, itemsize: int = 8) int[source]¶
Return the byte size of a dense
n x qrandom-effects design.- Parameters:
n – number of observation rows in the design.
q – number of random-effect columns in the design.
itemsize – bytes used by each matrix element.
Exact rather than estimated: the shape is known before the matrix exists.
- spacr.mixed_gpu.fit_mixed_reml_torch(y, X, groups, vc=None, *, device: str = GPU_DEVICE, max_iter: int = 400, verbose: bool = False)[source]¶
Fit
y ~ X + (1 | groups) + variance componentsby profiled REML.- Parameters:
y (array-like) – Response values with shape
(n_observations,).X (array-like) – Fixed-effects design with shape
(n_observations, n_fixed_effects). A DataFrame preserves its column names inTorchMixedResults.fe_params.groups (array-like) – Outer grouping labels with shape
(n_observations,). A random intercept is always included, equivalent tore_formula='1'.vc (mapping of str to array-like, optional) – Additional grouping labels. Each entry defines one variance component nested within
groups, matching statsmodelsvc_formulasemantics.device (str, optional) – PyTorch device. Requesting CUDA raises instead of falling back to CPU when no CUDA device is available.
max_iter (int, optional) – Maximum L-BFGS iterations. Typical screen-sized fits use 20–40; the default of 400 is a safety limit.
verbose (bool, optional) – Print the deviance at each optimizer evaluation.
- Returns:
TorchMixedResults – Fixed effects, variance components, conditional fitted values and residuals, BLUPs, convergence diagnostics, and timing information.
- Raises:
MixedBackendUnavailable – If PyTorch or the requested device is unavailable.
ValueError – If input dimensions disagree or the fixed-effects design is not identifiable.
MemoryError – If the dense random-effects design exceeds the configured share of available device memory.
Notes
Validation against statsmodels
MixedLM(...).fit()produced the following differences:quantity
nested fixture (1,620 rows)
screen-shaped fixture (1,830 rows, p=388, q=1,097)
fixed effects
1.20e-7 absolute
2.39e-4 absolute (2.0e-4 of one SE)
variance components
1.29e-3 relative
2.02e-4 relative
residual scale
4.12e-6 relative
1.94e-5 relative
standard errors
3.88e-4 relative
1.04e-3 median; 1.80e-2 maximum across 388
guide BLUPs
7.64e-5 absolute
not evaluated
Both backends maximize the same REML criterion. On the screen-shaped fixture, this fit ended at gradient norm 1.3e-11 and log-likelihood -804.143968098; the default statsmodels fit returned -804.143968682. Setting statsmodels
gtol=1e-12reduced fixed-effect disagreement to 1.52e-8 absolute and fixture variance-component disagreement to 1.02e-4 relative.Reference end-to-end times for that fixture were 11.3 s for statsmodels, 0.80 s for this backend on CPU, and 0.47 s on an RTX 3090. Under concurrent CPU load, statsmodels took 21.3 s and the CUDA backend 0.57 s.
- spacr.mixed_gpu.mixedlm_torch(formula, data, groups, vc_formula=None, *, device: str = GPU_DEVICE, **kwargs)[source]¶
Fit a formula mixed model with the PyTorch REML backend.
The call shape parallels
statsmodels.formula.api.mixedlm()sospacr.ml.fit_mixed_model()can select either backend.- Parameters:
formula (str) – Patsy fixed-effects formula, such as
'response ~ predictor'.data (pandas.DataFrame) – Frame in which the formula and grouping columns are evaluated.
groups (str or array-like) – Outer grouping column or one label per row.
vc_formula (mapping of str to str, optional) – Variance components in the supported form
'0 + C(column)'.device (str, optional) – PyTorch compute device.
**kwargs – Additional arguments passed to
fit_mixed_reml_torch().
- Returns:
TorchMixedResults – Fitted mixed-model results.
- Raises:
ValueError – If a variance-component formula is unsupported or names an absent column.
MixedBackendUnavailable – If PyTorch or the requested device is unavailable.
- spacr.mixed_gpu.resolve_device(device: str = GPU_DEVICE)[source]¶
Resolve a device string without silently substituting the CPU.
- Parameters:
device (str, optional) –
'cuda','cpu', or another PyTorch device string.- Returns:
torch.device – Validated compute device.
- Raises:
MixedBackendUnavailable – If PyTorch is not installed or a CUDA device was requested but is not available.
Nested helpers¶
- fit_mixed_reml_torch._solve(log_theta)¶
The profiled REML deviance at
theta = exp(log_theta).Returns the deviance plus everything the caller needs afterwards, so the final quantities come from the same factorisation that scored the final theta rather than from a re-solve that could differ.
spacr/mixed_gpu.py:551
- fit_mixed_reml_torch.closure()¶
Evaluate and differentiate the captured LBFGS objective.
- Returns:
differentiable profiled REML deviance at the current captured log-theta. Existing optimizer gradients are cleared, the deviance is backpropagated, and verbose mode reports its numeric value with the exponentiated variance parameters.
spacr/mixed_gpu.py:585