Tree Methods¶
The cca_zoo.tree module provides XGBoostCCA, LightGBMCCA, and CatBoostCCA, nonlinear
multiview CCA methods that use gradient-boosted trees as the per-view encoders, via
XGBoost, LightGBM, or
CatBoost respectively. All three share the same TreeCCA base class and
fitting recipe, differing only in which gradient-boosting library trains the per-view encoders.
Install the module with:
Background¶
TreeCCA maximises the same unconstrained Eckart-Young (EY) objective used by the stochastic
*_EY models in cca_zoo.linear and by DCCAEY in cca_zoo.deep (the numpy-based models
share the exact same implementation, in cca_zoo._utils._ey):
where, for embeddings \(Z_i = f_i(X_i)\), \(C\) is the mean pairwise cross-covariance (including
\(i = j\) terms) and \(V\) the mean auto-covariance across all views. TreeCCA uses a
gradient-boosted-tree ensemble in place of a linear map or neural network as the function class
for each \(f_i\).
Each of the n_components canonical components is a separate scalar booster per view.
Training proceeds by alternating (Gauss-Seidel) gradient boosting: each round, for every view in
turn, the EY-loss gradient is computed from the current embeddings and used as a custom
regression objective to add one tree to that view's boosters; with gauss_seidel=True (the
default) the gradient is recomputed from the freshest embeddings before moving to the next view.
Boosters start from a random-orthogonal, unit-variance initial embedding per view — random
directions in feature space, rescaled so each component has unit variance. Unit-variance scaling
is what matters for a well-conditioned, non-vanishing gradient at round zero; orthogonality keeps
the initial components uncorrelated.
Because each component is its own boosted-tree ensemble, per-component feature importance (split gain) is available directly from the fitted boosters — no separate interpretability method (such as SHAP) is required.
When to use: Nonlinear multiview CCA where you want built-in, per-component feature importance, and where a tree-based model is a natural fit for the data (e.g. tabular data with mixed scales, non-smooth or threshold-like relationships).
Basic usage¶
Pick the concrete class for the gradient-boosting library you want to use; TreeCCA itself is an
abstract base class and cannot be instantiated directly:
from cca_zoo.tree import XGBoostCCA
model = XGBoostCCA(n_components=2).fit([X1, X2])
z1, z2 = model.transform([X1, X2])
corr = model.score([X1, X2]) # mean canonical correlation
# XGBoostCCA also supports more than two views
model3 = XGBoostCCA(n_components=2, n_estimators=200).fit([X1, X2, X3])
Use LightGBMCCA or CatBoostCCA to train with LightGBM or CatBoost instead (each requires its
own optional package — pip install lightgbm / pip install catboost — both included in the
tree extra):
from cca_zoo.tree import CatBoostCCA, LightGBMCCA
model = LightGBMCCA(n_components=2).fit([X1, X2])
model = CatBoostCCA(n_components=2).fit([X1, X2])
CatBoostCCA has no in-place "continue this booster" call the way XGBoost/LightGBM do, so it
reconstructs and re-continues (via CatBoost's own init_model=) every component's model on each
boosting round — noticeably slower per round than XGBoostCCA/LightGBMCCA as a result. Reach
for it when CatBoost's ordered boosting and symmetric trees are themselves the point, not as a
faster default.
Feature importance¶
feature_importances_per_view_ is each view's total split gain, summed over its components' boosters
and normalised to sum to 1, the same convention as sklearn's gradient-boosting models:
model = XGBoostCCA(n_components=2).fit([X1, X2])
imp1, imp2 = model.feature_importances_per_view_ # each shape (n_features_i,)
The boosters themselves are in boosters_, a list[list[Booster]] indexed
[view][component], for per-component importances or any other backend-specific inspection.
Key parameters¶
| Parameter | Description |
|---|---|
n_estimators |
Boosting rounds (trees added per booster). Default 200; held-out correlation plateaus there on typical data, and more rounds cost time. |
max_depth |
Maximum tree depth. Default 3: two tree ensembles fitted to each other overfit quickly, so shallow trees generalise best. |
min_child_weight |
Minimum leaf size (see the notes below). Default 20, for the same reason. |
learning_rate |
Boosting shrinkage. |
subsample, colsample_bytree |
Row/column subsampling ratios per tree, for regularisation. |
gauss_seidel |
Use freshly-updated view-1 embeddings when computing view 2's gradient each round (default True); set False for Jacobi-style stale updates. |
random_state |
Seed for the boosters and the random-orthogonal initial embedding. |
Hyperparameters are best selected by cross-validation with GridSearchCV from
cca_zoo.model_selection, as for other models.
Practical notes¶
XGBoostCCA,LightGBMCCA, andCatBoostCCAall support 2 or more views.n_componentsmust not exceed the number of features in any view (the random-orthogonal initialisation draws that many orthogonal directions in feature space).- Unlike
KCCA, none of the three classes stores the training data for inference — new data is passed directly through the fitted boosters, sotransformon held-out data is inexpensive. min_child_weightis interpreted per backend: XGBoost's minimum sum of instance weight in a child, LightGBM's/CatBoost's minimum number of samples in a leaf (min_child_samples/min_data_in_leaf).- Reference: Chapman, J. (2026). TreeCCA: Canonical Correlation Analysis via Gradient-Boosted Trees. arXiv:2607.27027.