cca_zoo.nonparametric¶
Kernel- and graph-based nonparametric CCA methods.
KCCA ¶
KCCA(
latent_dimensions: int = 1,
center: bool = True,
c: float | list[float] = 0.1,
kernel: str | list[str] = "linear",
gamma: float | list[float | None] | None = None,
degree: float | list[float] = 1.0,
coef0: float | list[float] = 1.0,
kernel_params: dict[str, object]
| list[dict[str, object]]
| None = None,
eps: float = 0.001,
)
Bases: BaseModel
Kernel Canonical Correlation Analysis.
Extends MCCA to nonlinear relationships by mapping each view into a reproducing kernel Hilbert space via a kernel function \(k_i\). The dual variables (kernel coefficients) \(\boldsymbol{\alpha}_i\) are found by solving the kernelised generalised eigenvalue problem:
where:
- \(A\) is the between-kernel cross-covariance block matrix.
- \(B = \mathrm{block\_diag}\bigl( c_i K_i + (1 - c_i) K_i^2 \bigr)\) is the regularised within-kernel matrix.
References
Hardoon, D. R., Szedmak, S., & Shawe-Taylor, J. (2004). Canonical correlation analysis: An overview with application to learning methods. Neural Computation, 16(12), 2639–2664.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
latent_dimensions
|
int
|
Number of latent dimensions. Default is 1. |
1
|
center
|
bool
|
Whether to subtract column means before fitting. Default True. |
True
|
c
|
float | list[float]
|
Regularisation parameter(s) in |
0.1
|
kernel
|
str | list[str]
|
Kernel name(s) or callable(s) passed to
:func: |
'linear'
|
gamma
|
float | list[float | None] | None
|
Gamma parameter(s) for the RBF/polynomial kernel. |
None
|
degree
|
float | list[float]
|
Degree parameter(s) for the polynomial kernel. |
1.0
|
coef0
|
float | list[float]
|
coef0 parameter(s) for the polynomial/sigmoid kernel. |
1.0
|
kernel_params
|
dict[str, object] | list[dict[str, object]] | None
|
Extra per-view keyword arguments for the kernel. |
None
|
eps
|
float
|
Regularisation floor for the B matrix. Default is 1e-3. |
0.001
|
Examples:
>>> import numpy as np
>>> rng = np.random.default_rng(0)
>>> X1 = rng.standard_normal((30, 5))
>>> X2 = rng.standard_normal((30, 5))
>>> model = KCCA(latent_dimensions=2, c=0.1).fit([X1, X2])
>>> scores = model.transform([X1, X2])
Source code in cca_zoo/nonparametric/_kcca.py
fit ¶
Fit the KCCA model.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
views
|
list[ArrayLike]
|
List of arrays, each (n_samples, n_features_i). |
required |
y
|
None
|
Ignored. |
None
|
Returns:
| Name | Type | Description |
|---|---|---|
self |
KCCA
|
Fitted estimator. |
Raises:
| Type | Description |
|---|---|
ValueError
|
If fewer than 2 views are provided. |
ValueError
|
If views have inconsistent numbers of samples. |
Source code in cca_zoo/nonparametric/_kcca.py
transform ¶
Transform new views using the fitted kernel dual variables.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
views
|
list[ArrayLike]
|
List of arrays, each (n_samples_test, n_features_i). |
required |
Returns:
| Type | Description |
|---|---|
list[ndarray]
|
List of arrays, each (n_samples_test, latent_dimensions). |
Raises:
| Type | Description |
|---|---|
NotFittedError
|
If |
Source code in cca_zoo/nonparametric/_kcca.py
KGCCA ¶
KGCCA(
latent_dimensions: int = 1,
center: bool = True,
c: float | list[float] = 0.1,
kernel: str | list[str] = "linear",
gamma: float | list[float | None] | None = None,
degree: float | list[float] = 1.0,
coef0: float | list[float] = 1.0,
kernel_params: dict[str, object]
| list[dict[str, object]]
| None = None,
view_weights: list[float] | None = None,
eps: float = 1e-06,
)
Bases: BaseModel
Kernel Generalised Canonical Correlation Analysis.
Kernelised version of GCCA. The shared latent vector is found by solving the eigenvalue problem on the weighted sum of kernel projection matrices:
and the dual variables (kernel coefficients) are recovered as \(\boldsymbol{\alpha}_i = K_i^+ T\) where \(T\) is the matrix of top-k eigenvectors of \(Q\).
References
Tenenhaus, A., Philippe, C., & Frouin, V. (2015). Kernel generalized canonical correlation analysis. Computational Statistics & Data Analysis, 90, 114–131.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
latent_dimensions
|
int
|
Number of latent dimensions. Default is 1. |
1
|
center
|
bool
|
Whether to subtract column means before fitting. Default True. |
True
|
c
|
float | list[float]
|
Regularisation parameter(s). Default is 0.1. |
0.1
|
kernel
|
str | list[str]
|
Kernel name(s). Default is |
'linear'
|
gamma
|
float | list[float | None] | None
|
Gamma for RBF/polynomial kernel. |
None
|
degree
|
float | list[float]
|
Degree for polynomial kernel. |
1.0
|
coef0
|
float | list[float]
|
coef0 for polynomial/sigmoid kernel. |
1.0
|
kernel_params
|
dict[str, object] | list[dict[str, object]] | None
|
Extra per-view kernel keyword arguments. |
None
|
view_weights
|
list[float] | None
|
Per-view weights. Default is equal weights. |
None
|
eps
|
float
|
Regularisation floor. Default is 1e-6. |
1e-06
|
Examples:
>>> import numpy as np
>>> rng = np.random.default_rng(0)
>>> X1 = rng.standard_normal((30, 5))
>>> X2 = rng.standard_normal((30, 5))
>>> X3 = rng.standard_normal((30, 5))
>>> model = KGCCA(latent_dimensions=2).fit([X1, X2, X3])
Source code in cca_zoo/nonparametric/_kgcca.py
fit ¶
Fit the KGCCA model.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
views
|
list[ArrayLike]
|
List of arrays, each (n_samples, n_features_i). |
required |
y
|
None
|
Ignored. |
None
|
Returns:
| Name | Type | Description |
|---|---|---|
self |
KGCCA
|
Fitted estimator. |
Raises:
| Type | Description |
|---|---|
ValueError
|
If fewer than 2 views are provided. |
ValueError
|
If views have inconsistent numbers of samples. |
Source code in cca_zoo/nonparametric/_kgcca.py
transform ¶
Transform new views using fitted kernel dual variables.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
views
|
list[ArrayLike]
|
List of arrays, each (n_samples_test, n_features_i). |
required |
Returns:
| Type | Description |
|---|---|
list[ndarray]
|
List of arrays, each (n_samples_test, latent_dimensions). |
Raises:
| Type | Description |
|---|---|
NotFittedError
|
If |
Source code in cca_zoo/nonparametric/_kgcca.py
KTCCA ¶
KTCCA(
latent_dimensions: int = 1,
center: bool = True,
c: float | list[float] = 0.1,
kernel: str | list[str] = "linear",
gamma: float | list[float | None] | None = None,
degree: float | list[float] = 1.0,
coef0: float | list[float] = 1.0,
kernel_params: dict[str, object]
| list[dict[str, object]]
| None = None,
eps: float = 0.001,
random_state: int | None = None,
)
Bases: BaseModel
Kernel Tensor Canonical Correlation Analysis.
Extends TCCA to nonlinear relationships by computing the cross-moment tensor from whitened kernel matrices rather than from the raw views. Each kernel matrix \(K_i\) is whitened using its regularised self-product, then PARAFAC is applied to the resulting cross-moment tensor.
References
Kim, T.-K., Wong, S.-F., & Cipolla, R. (2007). Tensor canonical correlation analysis for action classification. CVPR 2007. IEEE.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
latent_dimensions
|
int
|
Number of latent dimensions. Default is 1. |
1
|
center
|
bool
|
Whether to subtract column means before fitting. Default True. |
True
|
c
|
float | list[float]
|
Regularisation parameter(s). Default is 0.1. |
0.1
|
kernel
|
str | list[str]
|
Kernel name(s). Default is |
'linear'
|
gamma
|
float | list[float | None] | None
|
Gamma for RBF/polynomial kernel. |
None
|
degree
|
float | list[float]
|
Degree for polynomial kernel. |
1.0
|
coef0
|
float | list[float]
|
coef0 for polynomial/sigmoid kernel. |
1.0
|
kernel_params
|
dict[str, object] | list[dict[str, object]] | None
|
Extra per-view keyword arguments for the kernel. |
None
|
eps
|
float
|
Regularisation floor. Default is 1e-3. |
0.001
|
random_state
|
int | None
|
Seed for PARAFAC. Default is None. |
None
|
Examples:
>>> import numpy as np
>>> rng = np.random.default_rng(0)
>>> X1 = rng.standard_normal((20, 5))
>>> X2 = rng.standard_normal((20, 5))
>>> X3 = rng.standard_normal((20, 5))
>>> model = KTCCA(latent_dimensions=1, random_state=0).fit([X1, X2, X3])
Source code in cca_zoo/nonparametric/_ktcca.py
fit ¶
Fit the KTCCA model.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
views
|
list[ArrayLike]
|
List of arrays, each (n_samples, n_features_i). |
required |
y
|
None
|
Ignored. |
None
|
Returns:
| Name | Type | Description |
|---|---|---|
self |
KTCCA
|
Fitted estimator. |
Raises:
| Type | Description |
|---|---|
ValueError
|
If fewer than 2 views are provided. |
ValueError
|
If views have inconsistent numbers of samples. |
Source code in cca_zoo/nonparametric/_ktcca.py
transform ¶
Transform new views using fitted kernel dual variables.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
views
|
list[ArrayLike]
|
List of arrays, each (n_samples_test, n_features_i). |
required |
Returns:
| Type | Description |
|---|---|
list[ndarray]
|
List of arrays, each (n_samples_test, latent_dimensions). |
Raises:
| Type | Description |
|---|---|
NotFittedError
|
If |
Source code in cca_zoo/nonparametric/_ktcca.py
ManifoldCCA ¶
ManifoldCCA(
latent_dimensions: int = 1,
center: bool = True,
method: str = "laplacian",
n_neighbors: int | list[int] = 10,
affinity: str | list[str] = "nearest_neighbors",
gamma: float | list[float | None] | None = None,
lle_reg: float | list[float] = 0.001,
n_operator_components: int
| list[int | None]
| None = None,
eps: float = 1e-06,
)
Bases: BaseModel
ManifoldCCA -- transductive multiview CCA over a shared manifold operator.
Every other multiview method in this library maximises cross-view
covariance subject to a within-view covariance constraint
(:class:~cca_zoo.linear.MCCA's ridge-blended sample covariance,
:class:~cca_zoo.linear.GraphicalLassoCCA's sparse-precision
covariance, :class:~cca_zoo.nonparametric.KCCA's regularised kernel
Gram matrix). Spectral manifold-learning methods
(:class:sklearn.manifold.SpectralEmbedding,
:class:sklearn.manifold.LocallyLinearEmbedding) instead constrain a
single view's embedding against a graph operator \(M\) built from that
view's own local neighbourhood structure -- the graph Laplacian
(\(M = D - W\), small \(\operatorname{tr}(Y^\top M Y)\) means neighbouring
points map to nearby embeddings) or the LLE reconstruction operator
(\(M = (I-W)^\top(I-W)\), small \(\operatorname{tr}(Y^\top M Y)\) means each
point's embedding is well reconstructed from its neighbours'). Both are
themselves generalised eigenproblems of exactly the same
"maximise-subject-to-a-quadratic-constraint" shape as
:class:~cca_zoo.linear.MCCA -- just with \(M\) replacing a covariance
matrix, and with no covariance available at all in the usual sense,
since there's no feature map: the "weight" is the per-training-point
embedding.
ManifoldCCA solves the resulting joint, multiview version:
where \(Z_i \in \mathbb{R}^{n \times k}\) is view \(i\)'s embedding of the
training points and \(M_i\) is that view's own graph operator --
the same joint-eigenproblem construction :class:~cca_zoo.linear.MCCA
and :class:~cca_zoo.nonparametric.KCCA use, but with each view's
"feature map" being the identity (so the projection weight found by the
solver is \(Z_i\) directly -- see :func:_centering_matrix) and its
within-view block \(M_i\) instead of a covariance.
Solved after projecting both sides onto \(\mathbf{1}^\perp\) (see
:func:_orthonormal_complement_of_ones): every \(M_i\) has the constant
vector in its (near-)null space, as does the reward, so leaving it in
would put a spurious, numerically unstable 0/0-type direction at the
top of the spectrum -- the same reason
:class:~sklearn.manifold.SpectralEmbedding always discards its own
trivial constant solution. One consequence worth checking directly: if
two views are given identical data, \(A\) (via the shared reward)
restricted to \(\mathbf{1}^\perp\) is proportional to the identity, so
the joint problem's solution for that view is exactly the ordinary
Rayleigh-quotient minimiser of \(M_i\) alone -- i.e. it reduces exactly
to plain single-view spectral embedding of that view, which is the
right sanity check for "is this actually the natural multiview
generalisation" (verified directly against
:class:~sklearn.manifold.SpectralEmbedding's own affinity
construction in the tests).
Since \(Z_i\) is only ever defined at the training points (there is no feature map to apply to new data), out-of-sample projection reuses each method's own established extension rather than a generic auxiliary model bolted on afterward:
method="lle": a new point's barycentric reconstruction weights (see :func:_barycenter_weights) against itsn_neighborsnearest training points, applied directly to those training points' rows of the fitted \(Z_i\) -- exactly :meth:~sklearn.manifold.LocallyLinearEmbedding.transform's own mechanism, reusing the identical weight computation training used. Valid because that formula is linear in the training embedding: with \(Z_i = Y_i B_i\) (\(Y_i\) the per-view smooth basis, \(B_i\) the joint solve's combination -- see :meth:fit), applying new-point weights to \(Y_i\) first and then \(B_i\), or to \(Z_i = Y_i B_i\) directly, are the same computation.method="laplacian": the classical Nystrom extension (Bengio et al. 2003) of each kept eigenvector individually -- \(y_k(x) = \tfrac{1}{\mu_k}\sum_j \tilde{W}(x, x_j)\, y_k(x_j)\), \(\tilde W\) the degree-normalised new-to-training affinity (built by the same rule as the training graph, see :func:_laplacian_new_point_affinity) and \(\mu_k = 1 - \lambda_k\) -- then the same \(B_i\) combination used at training time. Unlike the LLE case, this can't collapse to a single "apply weights to \(Z_i\)" step, since each eigenvector has its own \(\mu_k\) rescaling before \(B_i\) mixes them.
Both are exact consequences of what :meth:fit actually solved, not a
separately-fit approximation of it.
Note
Unlike :class:~sklearn.manifold.LocallyLinearEmbedding,
Hessian-LLE (method="hessian") and LTSA
(method="ltsa") are not implemented here -- both need a local
Hessian/tangent-space estimate per point (local PCA plus a
polynomial basis, then a null-space projection) that's
substantially more involved to get right than the graph Laplacian
or LLE's own reconstruction weights, and are left for a future
extension rather than shipped undertested. Isomap-flavoured
(geodesic-distance) regularisation is achievable today via
:class:~cca_zoo.nonparametric.KCCA with a precomputed geodesic
Gram matrix in place of a standard kernel, so isn't duplicated here.
inverse_transform/predict are not supported (same as
:class:~cca_zoo.nonparametric.KCCA): both rely on
BaseModel's default view-loading fit, which assumes
weights_[i] has shape (n_features_i, k); here it is
(n_train_samples, k) (the training embedding itself), since
there is no feature-space weight vector to speak of.
method itself is not a per-view parameter, unlike every other
constructor argument: mixing "laplacian" and "lle" across
views is not mathematically ruled out (the joint eigenproblem in
:meth:fit only ever consumes each view's own basis/eigenvalues,
regardless of which operator produced them), but transform's
out-of-sample extension dispatches on method once for every
view at once, and would need its own per-view branch and
per-view-typed fitted state to support a genuine mix -- a
larger, separate change from exposing this class's already
per-view-independent operator hyperparameters.
Solves an \((nM) \times (nM)\) dense generalised eigenproblem
(\(n\) = training samples, \(M\) = number of views), the same cost
profile as :class:~cca_zoo.nonparametric.KCCA -- intended for
moderate training-set sizes, not the very large-\(n\) regime.
References
Roweis, S. T., & Saul, L. K. (2000). Nonlinear dimensionality reduction by locally linear embedding. Science, 290(5500), 2323-2326.
Belkin, M., & Niyogi, P. (2003). Laplacian eigenmaps for dimensionality reduction and data representation. Neural Computation, 15(6), 1373-1396.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
latent_dimensions
|
int
|
Number of latent dimensions. Default is 1. |
1
|
center
|
bool
|
Whether to subtract column means before fitting. Default True. |
True
|
method
|
str
|
|
'laplacian'
|
n_neighbors
|
int | list[int]
|
Number of neighbours used to build each view's graph. Either a single value applied to every view or a list of per-view values. Default 10. |
10
|
affinity
|
str | list[str]
|
|
'nearest_neighbors'
|
gamma
|
float | list[float | None] | None
|
RBF kernel coefficient(s), used only when
|
None
|
lle_reg
|
float | list[float]
|
Regularisation added to each point's local reconstruction
Gram matrix, used only when |
0.001
|
n_operator_components
|
int | list[int | None] | None
|
Number of each view's own smallest-eigenvalue
operator components kept before the joint eigenproblem is
solved (see :func: |
None
|
eps
|
float
|
Floor applied to each kept operator eigenvalue (see
:func: |
1e-06
|
Examples:
>>> import numpy as np
>>> rng = np.random.default_rng(0)
>>> X1 = rng.standard_normal((60, 8))
>>> X2 = rng.standard_normal((60, 6))
>>> model = ManifoldCCA(method="laplacian", n_neighbors=8).fit([X1, X2])
>>> scores = model.transform([X1, X2])
A different neighbourhood size and regularisation strength per view:
>>> model = ManifoldCCA(
... method="laplacian", n_neighbors=[8, 12], n_operator_components=[10, 15]
... ).fit([X1, X2])
Source code in cca_zoo/nonparametric/_manifold_cca.py
fit ¶
Fit ManifoldCCA by a joint generalised eigenproblem over per-view graphs.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
views
|
list[ArrayLike]
|
List of 2 or more arrays, each (n_samples, n_features_i). |
required |
y
|
None
|
Ignored. |
None
|
Returns:
| Name | Type | Description |
|---|---|---|
self |
ManifoldCCA
|
Fitted estimator. |
Raises:
| Type | Description |
|---|---|
ValueError
|
If fewer than 2 views are provided. |
ValueError
|
If views have inconsistent numbers of samples. |
Source code in cca_zoo/nonparametric/_manifold_cca.py
491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 | |
transform ¶
Project new views via each method's own out-of-sample extension.
method="lle" reuses :func:_barycenter_weights against each new
point's nearest training points (exactly
:meth:~sklearn.manifold.LocallyLinearEmbedding.transform's own
mechanism); method="laplacian" uses the classical Nystrom
extension of each kept eigenvector (Bengio et al. 2003) followed by
the same combination :meth:fit used. See the class docstring.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
views
|
list[ArrayLike]
|
List of arrays, each of shape (n_samples, n_features_i). |
required |
Returns:
| Type | Description |
|---|---|
list[ndarray]
|
List of arrays, each of shape (n_samples, latent_dimensions). |
Raises:
| Type | Description |
|---|---|
NotFittedError
|
If |