nifreeze.model.lovo module¶
Closed-form leave-one-volume-out (LOVO) prediction for kernel models.
A kernel predictor with fixed hyperparameters is linear in the data, and its weights depend only on the gradient table. Given the covariance \(\mathbf{A}\) of the \(N\) diffusion-weighted volumes, the prediction of volume \(i\) from all the others is (Rasmussen and Williams[1], Eq. 5.12)
so all \(N\) LOVO predictions are given by a single smoother matrix \(\mathbf{S} = \mathbf{I} - \operatorname{diag}(\mathbf{P})^{-1}\mathbf{P}\), with a zero diagonal. One inverse replaces \(N\) model fits.
References
- class nifreeze.model.lovo.ClosedFormLOVOMixin(self, dataset: 'Any', *, nvox_prefit: 'int | None' = 1000, random_state: 'int | None' = 0, **kwargs: 'Any') 'None'[source]¶
Bases:
objectExact leave-one-volume-out prediction from a single linear smoother.
Subclasses implement
_covariance(), which returns the(N, N)covariance of the volumes given the gradient table. The smoother is built once and rebuilt only when the gradients change. Each prediction is then one row of the smoother times the signal matrix. Because the held-out volume never contributes to its own prediction, single-fit mode returns the same genuine LOVO predictions and is not a canary.Hyperparameters (if any) are estimated once, on a random subsample of voxels across all volumes. This lets a handful of scalars see the held-out volume, while every prediction remains held-out.
- fit_predict(index: int | None = None, **kwargs: Any) ndarray | None[source]¶
Predict volume
indexfrom all the other volumes (closed form).
- single_fit_is_canary = False¶
- nifreeze.model.lovo.DEFAULT_KRR_LAMBDA_GRID = (np.float64(0.0001), np.float64(0.00031622776601683794), np.float64(0.001), np.float64(0.0031622776601683794), np.float64(0.01), np.float64(0.03162277660168379), np.float64(0.1), np.float64(0.31622776601683794), np.float64(1.0), np.float64(3.1622776601683795), np.float64(10.0), np.float64(31.622776601683793), np.float64(100.0))¶
Default grid of ridge strengths (in units of
sphere_gram()).
- nifreeze.model.lovo.HYPERPARAMETERS_SCHEMA = 'nifreeze-gp-hyperparameters/1'¶
Schema identifier written to (and required from) hyperparameter files.
- nifreeze.model.lovo.ILL_CONDITIONED_THRESHOLD = 1000000000000.0¶
Condition number above which the LOVO smoother is considered unreliable.
- nifreeze.model.lovo.ILL_CONDITIONED_WARN_MSG = 'The covariance matrix is ill-conditioned (condition number {cond:.2e}); closed-form LOVO predictions may be inaccurate.'¶
Warning raised when the covariance is close to singular.
- nifreeze.model.lovo.fit_pooled_hyperparameters(kernel: sklearn.gaussian_process.kernels.Kernel, tables: Sequence[ndarray], signals: Sequence[ndarray], alpha: float = 1e-10, maxiter: int = 200) sklearn.gaussian_process.kernels.Kernel[source]¶
Fit GP hyperparameters shared by several datasets (e.g., subjects).
Maximizes \(\sum_s \log p(\mathbf{Y}_s \mid \mathbf{X}_s, \theta)\), where each dataset keeps its own gradient table \(\mathbf{X}_s\). With identical tables, this equals fitting the concatenated voxels.
- Parameters:
kernel (
Kernel) – Kernel providing the starting values and bounds.tables (
Sequenceofndarray) – One design matrix per dataset, of shape(N_s, n_features).signals (
Sequenceofndarray) – One signal matrix per dataset, of shape(N_s, V_s).alpha (
float, optional) – Value added to the diagonal of each covariance (numerical jitter).maxiter (
int, optional) – Maximum number of L-BFGS-B iterations.
- Returns:
A copy of
kernelwith the fitted hyperparameters.- Return type:
- nifreeze.model.lovo.kernel_with_hyperparameters(kernel: sklearn.gaussian_process.kernels.Kernel, values: Mapping[str, float]) sklearn.gaussian_process.kernels.Kernel[source]¶
Return a copy of
kernelwith the given hyperparameter values.
- nifreeze.model.lovo.load_hyperparameters(source: Path | str | Mapping[str, Any]) dict[str, Any][source]¶
Read and validate a GP hyperparameter record.
- Parameters:
source (
os.pathlikeorMapping) – A JSON file written bysave_hyperparameters(), or its parsed content.- Returns:
The record, with keys
schema,kernel_model,hyperparametersandprovenance.- Return type:
- nifreeze.model.lovo.lovo_error(smoother: ndarray, signals: ndarray) float[source]¶
Compute the closed-form LOVO error, normalized by each voxel’s signal energy.
- Parameters:
smoother (
ndarray) – LOVO smoother of shape(N, N)(seelovo_smoother()).signals (
ndarray) – Signals of shape(N, V)(volumes by voxels).
- Returns:
\(\sum_v \lVert \mathbf{y}_v - \mathbf{S}\mathbf{y}_v \rVert^2 / \lVert \mathbf{y}_v \rVert^2\).
- Return type:
- nifreeze.model.lovo.lovo_smoother(covariance: ndarray, center: bool = False, shells: ndarray | None = None) ndarray[source]¶
Build the closed-form leave-one-volume-out smoother from a covariance matrix.
- Parameters:
covariance (
ndarray) – Symmetric positive-definite covariance \(\mathbf{A}\) of shape(N, N), including any noise or ridge term on its diagonal.center (
bool, optional) – Whether the predictor estimates a constant mean on the \(N - 1\) training volumes (as scikit-learn’snormalize_y=Truedoes). The standard deviation of the normalization cancels in the posterior mean, so only the mean needs correcting.shells (
ndarray, optional) – The shell (b-value) of each volume. The predictor then estimates the mean of each shell on the training volumes, aspredict()does, and predicts each volume around its shell’s mean (the nearest shell’s, if no other volume is in its shell). Excludescenter.
- Returns:
The smoother \(\mathbf{S}\) of shape
(N, N). Row \(i\) holds the weights predicting volume \(i\) from all the others, and its diagonal is zero. Withcenter=Trueorshells, every row sums to one.- Return type:
Examples
>>> A = np.array([[2.0, 1.0, 0.5], [1.0, 2.0, 1.0], [0.5, 1.0, 2.0]]) >>> S = lovo_smoother(A) >>> bool(np.allclose(np.diag(S), 0.0)) True >>> bool(np.allclose(lovo_smoother(A, center=True).sum(axis=1), 1.0)) True >>> bool(np.allclose(lovo_smoother(A, shells=np.zeros(3)), lovo_smoother(A, center=True))) True
- nifreeze.model.lovo.masked_signal_matrix(dataset: ~typing.Any, mask: ~numpy.ndarray, dtype: ~typing.Any = <class 'numpy.float32'>) ndarray[source]¶
Gather the masked signals of all volumes, one volume at a time.
- Parameters:
dataset (
BaseDataset) – Dataset whosedataobjhas volumes along its first axis.mask (
ndarray) – Boolean mask of the voxels to gather.dtype (
dtype, optional) – Output data type.
- Returns:
Signals of shape
(N, V)(volumes by masked voxels).- Return type:
- nifreeze.model.lovo.save_hyperparameters(filename: Path | str, kernel: sklearn.gaussian_process.kernels.Kernel, kernel_model: str, **provenance: Any) Path[source]¶
Write fitted GP hyperparameters to a JSON file.
- Parameters:
- Returns:
The written file.
- Return type:
- nifreeze.model.lovo.select_krr_lambda(grams: Sequence[ndarray], signals: Sequence[ndarray], grid: Sequence[float] = (np.float64(0.0001), np.float64(0.00031622776601683794), np.float64(0.001), np.float64(0.0031622776601683794), np.float64(0.01), np.float64(0.03162277660168379), np.float64(0.1), np.float64(0.31622776601683794), np.float64(1.0), np.float64(3.1622776601683795), np.float64(10.0), np.float64(31.622776601683793), np.float64(100.0)), shells: Sequence[ndarray | None] | None = None) float[source]¶
Choose a ridge strength by closed-form LOVO error, pooled over datasets.
- Parameters:
grams (
Sequenceofndarray) – One Gram matrix of shape(N_s, N_s)per dataset (e.g., subject).signals (
Sequenceofndarray) – One signal matrix of shape(N_s, V_s)per dataset.grid (
Sequenceoffloat, optional) – Candidate ridge strengths, added to the diagonal of each Gram matrix.shells (
Sequenceofndarray, optional) – The shell of each volume, per dataset, when the predictor estimates a mean per shell (seelovo_smoother()).
- Returns:
The ridge strength with the lowest summed LOVO error.
- Return type: