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 pairsk(static). Defaults tomin(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 > 0whenTis not much larger thanp + q.
- Returns:
Named tuple
(correlations (k,), x_weights (p, k), y_weights (q, k)). Withreg=0the canonical variates(x - x.mean(0)) @ x_weightshave unit variance (ddof=1) and are mutually uncorrelated. Signs are deterministic: the largest-magnitude entry of eachx_weightscolumn is positive (and the pairedy_weightscolumn follows, so the correlations are non-negative).- Return type:
- Raises:
ValueError – If the inputs are not 1-D/2-D, their sample counts differ, there are fewer than two samples,
n_componentsis out of range or a concreteregis negative.
See also
pcaVariance-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 producinginf/nan. Jittable and vmappable; differentiable for generic data (theeigh-based whitening has an undefined derivative when a covariance has repeated eigenvalues).sklearn.cross_decomposition.CCAis 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))