Skip to content

Getting Started

Installation

Install the core package with pip:

pip install cca-zoo

The core package requires Python ≥ 3.11 and provides all linear and nonparametric methods.

Optional extras

Install extras for additional method families:

pip install cca-zoo[deep]          # DCCA variants (PyTorch + Lightning)
pip install cca-zoo[probabilistic] # Probabilistic CCA (NumPyro + JAX)
pip install cca-zoo[tree]          # XGBoostCCA, LightGBMCCA, CatBoostCCA
pip install cca-zoo[all]           # Everything above

PyTorch installation

For GPU support or specific CUDA versions, follow the PyTorch installation guide before installing cca-zoo[deep].


Core concepts

Views

CCA-Zoo expects data as a list of arrays, one per view:

views = [X1, X2, X3]  # three views
views = [X1, X2]  # two views

Each array has shape (n_samples, n_features_i). All views must share the same number of rows.

The estimator API

Every model follows the same three-step pattern:

from cca_zoo.linear import CCA

model = CCA(n_components=2)  # 1. construct
model.fit(views)  # 2. fit
z = model.transform(views)  # 3. use

Or equivalently:

z = CCA(n_components=2).fit_transform(views)

Evaluating fit quality

score returns the mean canonical correlation, one float as sklearn expects (so it works directly as a GridSearchCV criterion). The per-dimension values come from cca_zoo.metrics:

from cca_zoo.metrics import average_pairwise_correlations, pairwise_correlations

model.score(views)  # e.g. 0.905
scores = model.transform(views)
average_pairwise_correlations(pairwise_correlations(scores))  # e.g. [0.94, 0.87]

Inspecting weights

After fitting, a linear model's weights_ is a list of weight matrices (one per view), and every model's feature_importances_per_view_ gives one non-negative array per view summing to 1:

W1, W2 = model.weights_  # each shape (n_features_i, n_components)
imp1, imp2 = model.feature_importances_per_view_  # each shape (n_features_i,)

Predicting a missing view

predict reconstructs every view from whichever ones you pass — pass None for a view you want reconstructed, including one you don't have:

X2_pred = model.predict([X1_test, None])[1]  # predict view 2 from view 1 alone

Unlike a plain transform-then-project-back approach, this is a proper least-squares reconstruction fitted at training time, so it stays accurate even on unwhitened, differently-scaled views (see BaseModel.predict in the API reference for the full explanation of why CCA needs this and PLS doesn't).

Reconstructing a view from its own score

inverse_transform is predict's narrower sibling: it undoes transform for a view using that view's own score only, with no cross-view imputation —

z1, z2 = model.transform([X1_test, X2_test])
X1_approx, X2_approx = model.inverse_transform([z1, z2])

Use inverse_transform when you already have every view's scores (e.g. after denoising or perturbing them) and just want to map back to feature space; use predict when you have some views but not others.


Quick start

Two-view CCA

from sklearn.model_selection import train_test_split

from cca_zoo.datasets import make_joint_data
from cca_zoo.linear import CCA

# Simulate data from a linear latent variable model
views = make_joint_data(
    n_samples=400,
    n_features=[50, 50],
    n_components=2,
    signal_to_noise=2.0,
    random_state=0,
)
X1_train, X1_test, X2_train, X2_test = train_test_split(
    *views, test_size=0.5, random_state=0
)
train_views, test_views = [X1_train, X2_train], [X1_test, X2_test]

# Fit and evaluate
model = CCA(n_components=2).fit(train_views)
print("Mean canonical correlation:", model.score(test_views))

# Project into the shared latent space
z1, z2 = model.transform(test_views)
print("Latent shape:", z1.shape)  # (200, 2)

Multiview CCA (≥2 views)

from cca_zoo.linear import MCCA

views = make_joint_data(n_samples=200, n_features=30, n_views=3, random_state=0)

model = MCCA(n_components=2).fit(views)
print(model.score(views))

Regularised CCA

from cca_zoo.linear import RidgeCCA

# c controls the ridge penalty (0 = CCA, 1 = PLS)
model = RidgeCCA(n_components=2, shrinkage=0.1).fit(train_views)

Kernel CCA

from cca_zoo.nonparametric import KCCA

model = KCCA(n_components=2, kernel="rbf", gamma=0.01, shrinkage=0.1).fit(train_views)
z1, z2 = model.transform(test_views)

CCA-Zoo's GridSearchCV wraps sklearn's grid search with a multiview interface:

from cca_zoo.model_selection import GridSearchCV
from cca_zoo.nonparametric import KCCA

param_grid = {"shrinkage": [0.01, 0.1, 1.0], "gamma": [0.01, 0.1]}
gs = GridSearchCV(KCCA(n_components=2, kernel="rbf"), param_grid, cv=5)
gs.fit(train_views)
print("Best params:", gs.best_params_)

RandomizedSearchCV, the successive-halving searches and sklearn's cross-validation functions are also available for lists of views — see Model Selection.


Next steps