ikpls.fast_cross_validation.jax
Contains the PLS class which implements fast cross-validation with partial least-squares regression using Improved Kernel PLS by Dayal and MacGregor: https://arxiv.org/abs/2401.13185 https://doi.org/10.1002/(SICI)1099-128X(199701)11:1%3C73::AID-CEM435%3E3.0.CO;2-%23
This is the JAX counterpart of ikpls.fast_cross_validation.numpy. Instead of
parallelizing folds across CPU processes with joblib, it batches the folds with
jax.vmap so the per-fold fits run together on a CPU/GPU/TPU. The per-fold training
\(\mathbf{X}^{\mathbf{T}}\mathbf{W}\mathbf{X}\) and/or
\(\mathbf{X}^{\mathbf{T}}\mathbf{W}\mathbf{Y}\) (centered/scaled/weighted using
training-set statistics) are obtained by rank-update from the dataset-wide matrices using
cvmatrix with its JAX backend (cvmatrix[jax]).
Both Improved Kernel PLS Algorithm #1 and #2 are supported, mirroring
ikpls.fast_cross_validation.numpy:
Algorithm #2 fits each fold directly from the downdated \(\mathbf{X}^{\mathbf{T}}\mathbf{W}\mathbf{X}\) (K, K) and \(\mathbf{X}^{\mathbf{T}}\mathbf{W}\mathbf{Y}\) (K, M). It is efficient when
Xhas more rows than columns.Algorithm #1 gathers each fold’s training
X(centered/scaled/weighted using the downdated training statistics) and the downdated \(\mathbf{X}^{\mathbf{T}}\mathbf{W}\mathbf{Y}\). It avoids forming \(\mathbf{X}^{\mathbf{T}}\mathbf{W}\mathbf{X}\) and is efficient whenXhas more columns than rows (but materializes per-fold training rows, so usebatch_sizeto bound memory).
Algorithm #1 and #2 produce identical regression coefficients.
Note that the JAX implementations do not emit any underflow warning, in any path
(single fit or cross-validation). Degenerate folds (training sets with too few
non-zero weights to compute centering/scaling statistics) are still rejected up-front
with a ValueError before the vmapped computation.
Author: Ole-Christian Galbo Engstrøm E-mail: ocge@foss.dk
Classes
|
Implements fast cross-validation with partial least-squares regression using Improved Kernel PLS by Dayal and MacGregor: https://arxiv.org/abs/2401.13185 https://doi.org/10.1002/(SICI)1099-128X(199701)11:1%3C73::AID-CEM435%3E3.0.CO;2-%23 |
- class ikpls.fast_cross_validation.jax.PLS(algorithm: int = 1, center_X: bool = True, center_Y: bool = True, scale_X: bool = True, scale_Y: bool = True, ddof: int = 0, copy: bool = True, dtype: str | type[Any] | dtype | SupportsDType = <class 'jax.numpy.float64'>)
Bases:
objectImplements fast cross-validation with partial least-squares regression using Improved Kernel PLS by Dayal and MacGregor: https://arxiv.org/abs/2401.13185 https://doi.org/10.1002/(SICI)1099-128X(199701)11:1%3C73::AID-CEM435%3E3.0.CO;2-%23
The per-fold training kernel matrices are computed by rank-update with
cvmatrix(JAX backend) and the folds are batched withjax.vmap.- Parameters:
algorithm (int, default=1) – Whether to use Improved Kernel PLS Algorithm #1 or #2. Generally, Algorithm #1 is faster if X has fewer rows than columns, while Algorithm #2 is faster if X has more rows than columns. Both yield identical regression coefficients.
center_X (bool, default=True) – Whether to center X before fitting by subtracting its row of column-wise means from each row. The row of column-wise means is computed on the training set for each fold to avoid data leakage.
center_Y (bool, default=True) – Whether to center Y. See center_X.
scale_X (bool, default=True) – Whether to scale X before fitting by dividing each row with the row of X’s column-wise standard deviations, computed on the training set for each fold.
scale_Y (bool, default=True) – Whether to scale Y. See scale_X.
ddof (int, default=0) – The delta degrees of freedom to use when computing the sample standard deviation. A value of 0 corresponds to the biased estimate of the sample standard deviation, while a value of 1 corresponds to Bessel’s correction.
copy (bool, default=True) – Whether to copy X, Y, and sample_weight when cross-validating.
dtype (DTypeLike, default=jnp.float64) – The float datatype to use. Using a lower precision than float64 will yield significantly worse results with an increasing number of components due to propagation of numerical errors.
- Raises:
ValueError – If algorithm is not 1 or 2.
Notes
Any centering and scaling is undone before returning predictions so that predictions are on the original scale. If both centering and scaling are True, then the data is first centered and then scaled.
See also
ikpls.fast_cross_validation.numpy.PLSThe NumPy/joblib counterpart. Its
cross_validateshares the same return type (a dict mapping each fold to its metric) andmetric_functioncontract, but the performance knobs differ: this class takesbatch_sizeandshow_progress(vmap-based), whereas the NumPy class takesn_jobsandverbose(joblib-based).
- cross_validate(X: Array | ndarray | bool | number | bool | int | float | complex, Y: Array | ndarray | bool | number | bool | int | float | complex, A: int, folds: Iterable[Hashable], metric_function: Callable[[...], Any], sample_weight: Array | ndarray | bool | number | bool | int | float | complex | None = None, batch_size: int | None = None, show_progress: bool = True) dict[Hashable, Any]
Cross-validates the PLS model using folds splits on X and Y with A components, evaluating results with metric_function.
- Parameters:
X (Array of shape (N, K)) – Predictor variables.
Y (Array of shape (N, M) or (N,)) – Target variables.
A (int) – Number of components in the PLS model.
folds (Iterable of Hashable with N elements) – An iterable defining cross-validation splits. Each unique value in folds corresponds to a different fold.
metric_function (Callable) – Computes a metric from the true
Y_val(N_val, M) and the predictedY_pred(A, N_val, M) – and, ifsample_weightis not None, alsoweights_val(N_val,) – returning any value.Y_predcontains a prediction for all A components. Must be JAX-traceable (jax.numpy-based): it is evaluated on device insidejax.vmapover the folds, so only the metric (not the prediction tensor) is transferred back.sample_weight (Array of shape (N,) or None, optional, default=None) – Weights for each observation. If None, all observations are weighted equally. Must be non-negative.
batch_size (int or None, optional, default=None) – Number of folds processed together in a single
jax.vmapcall.Noneprocesses all folds of a given validation-set size at once. Use a smaller value to bound peak memory when there are many folds and/or large K (especially for Algorithm #1, which materializes per-fold training rows).show_progress (bool, default=True) – Whether to display a progress bar over the vmapped fold batches.
- Returns:
metrics – A dictionary mapping each unique value in folds to the result of evaluating metric_function on the corresponding validation set.
- Return type:
dict of Hashable to Any
- Raises:
ValueError – If sample_weight are provided and not all weights are non-negative, or if a fold’s training set has too few non-zero weights to compute the requested centering/scaling statistics.
Notes
Folds are grouped by validation-set size so that
jax.vmapsees fixed shapes; leave-one-out and balanced k-fold use a single group, while size-imbalanced folds use one group per distinct size.