braintools.analysis.population.cca

Contents

braintools.analysis.population.cca#

braintools.analysis.population.cca(x, y, n_components=None, reg=0.0)#

Canonical correlation analysis via SVD of the whitened cross-covariance.

With centred data, covariances \(C_{xx} = X_c^\top X_c/(T-1) + \text{reg}\,I\), \(C_{yy}\) likewise and \(C_{xy} = X_c^\top Y_c/(T-1)\), the whitened cross-covariance \(M = C_{xx}^{-1/2} C_{xy} C_{yy}^{-1/2} = U S V^\top\) gives the canonical correlations \(S\) and weights \(W_x = C_{xx}^{-1/2} U\), \(W_y = C_{yy}^{-1/2} V\) [1] [2].

Parameters:
  • x (array_like or brainunit.Quantity) – First data set, shape (T, p) (a 1-D array is treated as (T, 1)).

  • y (array_like or brainunit.Quantity) – Second data set, shape (T, q), same number of samples.

  • n_components (int | None) – Number of canonical pairs k (static). Defaults to min(p, q), which is also the maximum.

  • reg (float, default=0.0) – Ridge added to the diagonal of both covariance matrices (in the squared data units). Must be non-negative. Use reg > 0 when T is not much larger than p + q.

Returns:

Named tuple (correlations (k,), x_weights (p, k), y_weights (q, k)). With reg=0 the canonical variates (x - x.mean(0)) @ x_weights have unit variance (ddof=1) and are mutually uncorrelated. Signs are deterministic: the largest-magnitude entry of each x_weights column is positive (and the paired y_weights column follows, so the correlations are non-negative).

Return type:

CCAResult

Raises:

ValueError – If the inputs are not 1-D/2-D, their sample counts differ, there are fewer than two samples, n_components is out of range or a concrete reg is negative.

See also

pca

Variance-maximising projection of a single data set.

Notes

Rank-deficient covariances (e.g. collinear features with reg=0) are whitened with a pseudo-inverse square root, so the corresponding directions get zero weight instead of producing inf/nan. Jittable and vmappable; differentiable for generic data (the eigh-based whitening has an undefined derivative when a covariance has repeated eigenvalues). sklearn.cross_decomposition.CCA is an iterative PLS-style algorithm and only agrees approximately.

References

Examples

>>> import jax
>>> import jax.numpy as jnp
>>> from braintools.analysis import population
>>> x = jax.random.normal(jax.random.PRNGKey(0), (500, 3))
>>> y = x @ jnp.array([[1., 0.], [2., 1.], [0., -1.]])  # linear transform
>>> res = population.cca(x, y)
>>> [round(float(c), 4) for c in res.correlations]
[1.0, 1.0]
>>> res.x_weights.shape, res.y_weights.shape
((3, 2), (2, 2))