From c161fcf6cc6422cdfa97756c88136f0eda41d97f Mon Sep 17 00:00:00 2001 From: jameschapman19 Date: Thu, 19 Oct 2023 18:44:04 +0100 Subject: [PATCH] Validation set for Gradient Based Models woohoo --- cca_zoo/deep/objectives.py | 72 ++++++++--------- cca_zoo/linear/__init__.py | 4 +- cca_zoo/linear/_gradient/__init__.py | 4 +- cca_zoo/linear/_gradient/_base.py | 2 +- cca_zoo/probabilistic/__init__.py | 1 + cca_zoo/probabilistic/_cca.py | 2 +- cca_zoo/probabilistic/_rcca.py | 6 +- cca_zoo/visualisation/umap_scores.py | 2 +- pyproject.toml | 1 + test/test_cross_corr.py | 15 ++-- test/test_data.py | 8 +- test/test_deepmodels.py | 116 +++++++++++++++------------ test/test_explained_variance.py | 11 ++- test/test_gradient.py | 83 +++++++++---------- test/test_nonparametric.py | 8 +- test/test_plotting.py | 9 ++- test/test_preprocessing.py | 3 +- test/test_probabilistic.py | 2 +- test/test_regularised.py | 23 ------ test/test_search.py | 5 +- test/test_sequential.py | 4 +- 21 files changed, 188 insertions(+), 193 deletions(-) diff --git a/cca_zoo/deep/objectives.py b/cca_zoo/deep/objectives.py index 9cd22cda..0213c833 100644 --- a/cca_zoo/deep/objectives.py +++ b/cca_zoo/deep/objectives.py @@ -266,26 +266,26 @@ def loss(self, representations, independent_representations=None): } -class CCA_SVDLoss(CCA_EYLoss): - def loss(self, representations, independent_representations=None): - C = torch.cov(torch.hstack(representations).T) - latent_dims = representations[0].shape[1] - - Cxy = C[:latent_dims, latent_dims:] - Cxx = C[:latent_dims, :latent_dims] - - if independent_representations is None: - Cyy = C[latent_dims:, latent_dims:] - else: - Cyy = torch.cov(independent_representations[1].T) - - rewards = torch.trace(2 * Cxy) - penalties = torch.trace(Cxx @ Cyy) - return { - "objective": -rewards + penalties, # return the negative objective value - "rewards": rewards, # return the total rewards - "penalties": penalties, # return the penalties matrix - } +# class CCA_SVDLoss(CCA_EYLoss): +# def loss(self, representations, independent_representations=None): +# C = torch.cov(torch.hstack(representations).T) +# latent_dims = representations[0].shape[1] +# +# Cxy = C[:latent_dims, latent_dims:] +# Cxx = C[:latent_dims, :latent_dims] +# +# if independent_representations is None: +# Cyy = C[latent_dims:, latent_dims:] +# else: +# Cyy = torch.cov(independent_representations[1].T) +# +# rewards = torch.trace(2 * Cxy) +# penalties = torch.trace(Cxx @ Cyy) +# return { +# "objective": -rewards + penalties, # return the negative objective value +# "rewards": rewards, # return the total rewards +# "penalties": penalties, # return the penalties matrix +# } class PLS_EYLoss(CCA_EYLoss): @@ -317,19 +317,19 @@ def get_AB(self, representations, weights=None): return A / len(representations), B / len(representations) -class PLS_SVDLoss(PLS_EYLoss): - def loss(self, representations, weights=None): - C = cross_cov(representations[0], representations[1], rowvar=False) - - Cxy = C - Cxx = weights[0].T @ weights[0] / representations[0].shape[0] - Cyy = weights[1].T @ weights[1] / representations[1].shape[0] - - rewards = torch.trace(2 * Cxy) - penalties = torch.trace(Cxx @ Cyy) - - return { - "objective": -rewards + penalties, - "rewards": rewards, - "penalties": penalties, - } +# class PLS_SVDLoss(PLS_EYLoss): +# def loss(self, representations, weights=None): +# C = cross_cov(representations[0], representations[1], rowvar=False) +# +# Cxy = C +# Cxx = weights[0].T @ weights[0] / representations[0].shape[0] +# Cyy = weights[1].T @ weights[1] / representations[1].shape[0] +# +# rewards = torch.trace(2 * Cxy) +# penalties = torch.trace(Cxx @ Cyy) +# +# return { +# "objective": -rewards + penalties, +# "rewards": rewards, +# "penalties": penalties, +# } diff --git a/cca_zoo/linear/__init__.py b/cca_zoo/linear/__init__.py index 7ee69e5c..60986df8 100644 --- a/cca_zoo/linear/__init__.py +++ b/cca_zoo/linear/__init__.py @@ -1,5 +1,5 @@ from ._gcca import GCCA -from ._gradient import CCA_EY, CCA_GHA, CCA_SVD, PLS_EY, PLSStochasticPower +from ._gradient import CCA_EY, CCA_GHA, PLS_EY, PLSStochasticPower from ._grcca import GRCCA from ._iterative import ( PLS_ALS, @@ -39,6 +39,6 @@ "CCA_EY", "PLS_EY", "CCA_GHA", - "CCA_SVD", + # "CCA_SVD", "PLSStochasticPower", ] diff --git a/cca_zoo/linear/_gradient/__init__.py b/cca_zoo/linear/_gradient/__init__.py index de9cc9a6..0d93d070 100644 --- a/cca_zoo/linear/_gradient/__init__.py +++ b/cca_zoo/linear/_gradient/__init__.py @@ -2,13 +2,13 @@ from ._gha import CCA_GHA from ._stochasticpls import PLSStochasticPower -from ._svd import CCA_SVD +# from ._svd import CCA_SVD __all__ = [ "CCA_EY", "PLS_EY", "CCA_GHA", - "CCA_SVD", + # "CCA_SVD", # "PLS_SVD", "PLSStochasticPower", ] diff --git a/cca_zoo/linear/_gradient/_base.py b/cca_zoo/linear/_gradient/_base.py index a8dbbae3..a201206f 100644 --- a/cca_zoo/linear/_gradient/_base.py +++ b/cca_zoo/linear/_gradient/_base.py @@ -34,7 +34,7 @@ def __init__( batch_size=None, dataloader_kwargs=None, epochs=1, - learning_rate=1, + learning_rate=5e-2, initialization: Union[str, callable] = "random", trainer_kwargs=None, optimizer_kwargs=None, diff --git a/cca_zoo/probabilistic/__init__.py b/cca_zoo/probabilistic/__init__.py index bd3a29e7..6c6fc2ae 100644 --- a/cca_zoo/probabilistic/__init__.py +++ b/cca_zoo/probabilistic/__init__.py @@ -1,6 +1,7 @@ from ._cca import ProbabilisticCCA from ._plsregression import ProbabilisticPLSRegression from ._rcca import ProbabilisticRCCA + # from ._pls import ProbabilisticPLS __all__ = [ diff --git a/cca_zoo/probabilistic/_cca.py b/cca_zoo/probabilistic/_cca.py index 522becb1..ad717800 100644 --- a/cca_zoo/probabilistic/_cca.py +++ b/cca_zoo/probabilistic/_cca.py @@ -196,7 +196,7 @@ def _guide(self, views): n = X1.shape[0] if X1 is not None else X2.shape[0] with numpyro.plate("n", n): - z=numpyro.sample( + z = numpyro.sample( "representations", dist.MultivariateNormal( jnp.zeros(self.latent_dimensions), jnp.eye(self.latent_dimensions) diff --git a/cca_zoo/probabilistic/_rcca.py b/cca_zoo/probabilistic/_rcca.py index 7b502412..e3656773 100644 --- a/cca_zoo/probabilistic/_rcca.py +++ b/cca_zoo/probabilistic/_rcca.py @@ -144,8 +144,7 @@ def _model(self, views): "X1", dist.MultivariateNormal( z @ W1.T + mu1, - covariance_matrix=psi1 - + self.c[0] * jnp.eye(self.n_features_[0]), + covariance_matrix=psi1 + self.c[0] * jnp.eye(self.n_features_[0]), ), obs=X1, ) @@ -153,8 +152,7 @@ def _model(self, views): "X2", dist.MultivariateNormal( z @ W2.T + mu2, - covariance_matrix=psi2 - + self.c[1] * jnp.eye(self.n_features_[1]), + covariance_matrix=psi2 + self.c[1] * jnp.eye(self.n_features_[1]), ), obs=X2, ) diff --git a/cca_zoo/visualisation/umap_scores.py b/cca_zoo/visualisation/umap_scores.py index 003f32de..b2656836 100644 --- a/cca_zoo/visualisation/umap_scores.py +++ b/cca_zoo/visualisation/umap_scores.py @@ -9,7 +9,7 @@ def _validate_plot_params(self): check_umap_support("UMAPScoreDisplay") check_seaborn_support("TSNEScoreDisplay") - def plot(self): + def plot(self, **kwargs): self._validate_plot_params() import umap import matplotlib.pyplot as plt diff --git a/pyproject.toml b/pyproject.toml index 20c6872b..c966a9ff 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -45,6 +45,7 @@ pytest-cov = "*" seaborn = "*" opentsne = "*" umap-learn = "*" +rdata = "*" [build-system] diff --git a/test/test_cross_corr.py b/test/test_cross_corr.py index 51e82c12..f385c3e0 100644 --- a/test/test_cross_corr.py +++ b/test/test_cross_corr.py @@ -2,22 +2,25 @@ from cca_zoo.utils.cross_correlation import cross_corrcoef, cross_cov +N = 50 +features = [4, 6] + def test_crosscorrcoef(): - X = np.random.rand(100, 5) - Y = np.random.rand(100, 5) / 10 + X = np.random.rand(N, features[0]) + Y = np.random.rand(N, features[1]) / 10 - m = np.corrcoef(X, Y, rowvar=False)[:5, 5:] + m = np.corrcoef(X, Y, rowvar=False)[:4, 4:] n = cross_corrcoef(X, Y, rowvar=False) assert np.allclose(m, n) def test_crosscov(bias=False): - X = np.random.rand(100, 5) - Y = np.random.rand(100, 5) / 10 + X = np.random.rand(N, features[0]) + Y = np.random.rand(N, features[1]) / 10 - m = np.cov(X, Y, rowvar=False)[:5, 5:] + m = np.cov(X, Y, rowvar=False)[:4, 4:] n = cross_cov(X, Y, rowvar=False) assert np.allclose(m, n) diff --git a/test/test_data.py b/test/test_data.py index 3bad6d41..3dc9cd1f 100644 --- a/test/test_data.py +++ b/test/test_data.py @@ -41,8 +41,8 @@ def test_cca_on_simulated_data_maintains_expected_correlation( # Additional test to verify the shape of generated data def test_simulated_data_shapes(): data = JointData( - view_features=[10, 12], latent_dims=4, correlation=[0.8, 0.7, 0.6, 0.5] + view_features=[4, 6], latent_dims=4, correlation=[0.8, 0.7, 0.6, 0.5] ) - x_train, y_train = data.sample(500) - assert x_train.shape == (500, 10) - assert y_train.shape == (500, 12) + x_train, y_train = data.sample(5) + assert x_train.shape == (5, 4) + assert y_train.shape == (5, 6) diff --git a/test/test_deepmodels.py b/test/test_deepmodels.py index 0830f895..8025d8b5 100644 --- a/test/test_deepmodels.py +++ b/test/test_deepmodels.py @@ -25,19 +25,20 @@ manual_seed(0) rng = check_random_state(0) -X = rng.rand(256, 10) -Y = rng.rand(256, 12) -Z = rng.rand(256, 14) +feature_size = [3, 4, 5] +X = rng.rand(64, feature_size[0]) +Y = rng.rand(64, feature_size[1]) +Z = rng.rand(64, feature_size[2]) X -= X.mean(axis=0) Y -= Y.mean(axis=0) Z -= Z.mean(axis=0) -X_conv = rng.rand(256, 1, 16, 16) -Y_conv = rng.rand(256, 1, 16, 16) +X_conv = rng.rand(64, 1, 4, 4) +Y_conv = rng.rand(64, 1, 4, 4) X_conv -= X_conv.mean(axis=0) Y_conv -= Y_conv.mean(axis=0) dataset = NumpyDataset([X, Y, Z]) check_dataset(dataset) -train_dataset, val_dataset = random_split(dataset, [256 - 56, 56]) +train_dataset, val_dataset = random_split(dataset, [64 - 16, 16]) loader = get_dataloaders(dataset) train_loader, val_loader = get_dataloaders(train_dataset, val_dataset) conv_dataset = NumpyDataset((X_conv, Y_conv)) @@ -58,18 +59,18 @@ def test_numpy_dataset(): def test_linear_mcca(): - max_epochs = 100 + max_epochs = 50 latent_dimensions = 2 mcca = MCCA(latent_dimensions=latent_dimensions).fit((X, Y, Z)) # DCCA_MCCA encoder_1 = architectures.LinearEncoder( - latent_dimensions=latent_dimensions, feature_size=10 + latent_dimensions=latent_dimensions, feature_size=feature_size[0] ) encoder_2 = architectures.LinearEncoder( - latent_dimensions=latent_dimensions, feature_size=12 + latent_dimensions=latent_dimensions, feature_size=feature_size[1] ) encoder_3 = architectures.LinearEncoder( - latent_dimensions=latent_dimensions, feature_size=14 + latent_dimensions=latent_dimensions, feature_size=feature_size[2] ) dmcca = DCCA( latent_dimensions=latent_dimensions, @@ -88,18 +89,18 @@ def test_linear_mcca(): def test_linear_gcca(): - max_epochs = 100 + max_epochs = 50 latent_dimensions = 2 gcca = GCCA(latent_dimensions=latent_dimensions).fit((X, Y, Z)) # DCCA_GCCA encoder_1 = architectures.LinearEncoder( - latent_dimensions=latent_dimensions, feature_size=10 + latent_dimensions=latent_dimensions, feature_size=feature_size[0] ) encoder_2 = architectures.LinearEncoder( - latent_dimensions=latent_dimensions, feature_size=12 + latent_dimensions=latent_dimensions, feature_size=feature_size[1] ) encoder_3 = architectures.LinearEncoder( - latent_dimensions=latent_dimensions, feature_size=14 + latent_dimensions=latent_dimensions, feature_size=feature_size[2] ) dgcca = DGCCA( latent_dimensions=latent_dimensions, @@ -117,15 +118,15 @@ def test_linear_gcca(): def test_DTCCA_methods(): - max_epochs = 100 + max_epochs = 20 # check that DTCCA is equivalent to CCALoss for 2 representations with linear encoders latent_dimensions = 2 cca = CCA(latent_dimensions=latent_dimensions) encoder_1 = architectures.LinearEncoder( - latent_dimensions=latent_dimensions, feature_size=10 + latent_dimensions=latent_dimensions, feature_size=feature_size[0] ) encoder_2 = architectures.LinearEncoder( - latent_dimensions=latent_dimensions, feature_size=12 + latent_dimensions=latent_dimensions, feature_size=feature_size[1] ) dtcca = DTCCA( latent_dimensions=latent_dimensions, encoders=[encoder_1, encoder_2], lr=1e-2 @@ -146,16 +147,15 @@ def test_DTCCA_methods(): def test_DCCA_methods(): - N = len(train_dataset) - max_epochs = 100 + max_epochs = 40 latent_dimensions = 2 cca = CCA(latent_dimensions=latent_dimensions).fit((X, Y)) # DCCA encoder_1 = architectures.Encoder( - latent_dimensions=latent_dimensions, feature_size=10 + latent_dimensions=latent_dimensions, feature_size=feature_size[0] ) encoder_2 = architectures.Encoder( - latent_dimensions=latent_dimensions, feature_size=12 + latent_dimensions=latent_dimensions, feature_size=feature_size[1] ) dcca = DCCA( latent_dimensions=latent_dimensions, @@ -171,10 +171,10 @@ def test_DCCA_methods(): ) # DCCA_GHA encoder_1 = architectures.Encoder( - latent_dimensions=latent_dimensions, feature_size=10 + latent_dimensions=latent_dimensions, feature_size=feature_size[0] ) encoder_2 = architectures.Encoder( - latent_dimensions=latent_dimensions, feature_size=12 + latent_dimensions=latent_dimensions, feature_size=feature_size[1] ) dcca_gha = DCCA_GHA( latent_dimensions=latent_dimensions, @@ -189,10 +189,10 @@ def test_DCCA_methods(): ) # DCCA_SVD encoder_1 = architectures.Encoder( - latent_dimensions=latent_dimensions, feature_size=10 + latent_dimensions=latent_dimensions, feature_size=feature_size[0] ) encoder_2 = architectures.Encoder( - latent_dimensions=latent_dimensions, feature_size=12 + latent_dimensions=latent_dimensions, feature_size=feature_size[1] ) dcca_svd = DCCA_SVD( latent_dimensions=latent_dimensions, @@ -207,10 +207,10 @@ def test_DCCA_methods(): ) # DCCA_EY encoder_1 = architectures.Encoder( - latent_dimensions=latent_dimensions, feature_size=10 + latent_dimensions=latent_dimensions, feature_size=feature_size[0] ) encoder_2 = architectures.Encoder( - latent_dimensions=latent_dimensions, feature_size=12 + latent_dimensions=latent_dimensions, feature_size=feature_size[1] ) dcca_ey = DCCA_EY( latent_dimensions=latent_dimensions, @@ -225,13 +225,13 @@ def test_DCCA_methods(): ) # DCCA_NOI encoder_1 = architectures.Encoder( - latent_dimensions=latent_dimensions, feature_size=10 + latent_dimensions=latent_dimensions, feature_size=feature_size[0] ) encoder_2 = architectures.Encoder( - latent_dimensions=latent_dimensions, feature_size=12 + latent_dimensions=latent_dimensions, feature_size=feature_size[1] ) dcca_noi = DCCA_NOI( - latent_dimensions, encoders=[encoder_1, encoder_2], rho=0.2, lr=1e-2 + latent_dimensions, encoders=[encoder_1, encoder_2], rho=0.2, lr=1e-3 ) trainer = pl.Trainer(max_epochs=max_epochs, **trainer_kwargs) trainer.fit(dcca_noi, train_loader) @@ -241,10 +241,10 @@ def test_DCCA_methods(): ) # Soft Decorrelation (_stochastic Decorrelation Loss) encoder_1 = architectures.Encoder( - latent_dimensions=latent_dimensions, feature_size=10 + latent_dimensions=latent_dimensions, feature_size=feature_size[0] ) encoder_2 = architectures.Encoder( - latent_dimensions=latent_dimensions, feature_size=12 + latent_dimensions=latent_dimensions, feature_size=feature_size[1] ) sdl = DCCA_SDL( latent_dimensions, encoders=[encoder_1, encoder_2], lam=1e-2, lr=1e-3 @@ -256,10 +256,10 @@ def test_DCCA_methods(): ) # Barlow Twins encoder_1 = architectures.Encoder( - latent_dimensions=latent_dimensions, feature_size=10 + latent_dimensions=latent_dimensions, feature_size=feature_size[0] ) encoder_2 = architectures.Encoder( - latent_dimensions=latent_dimensions, feature_size=12 + latent_dimensions=latent_dimensions, feature_size=feature_size[1] ) barlowtwins = BarlowTwins( latent_dimensions=latent_dimensions, @@ -273,10 +273,10 @@ def test_DCCA_methods(): ) # DGCCA encoder_1 = architectures.Encoder( - latent_dimensions=latent_dimensions, feature_size=10 + latent_dimensions=latent_dimensions, feature_size=feature_size[0] ) encoder_2 = architectures.Encoder( - latent_dimensions=latent_dimensions, feature_size=12 + latent_dimensions=latent_dimensions, feature_size=feature_size[1] ) dgcca = DCCA( latent_dimensions=latent_dimensions, @@ -291,10 +291,10 @@ def test_DCCA_methods(): ) # DMCCA encoder_1 = architectures.Encoder( - latent_dimensions=latent_dimensions, feature_size=10 + latent_dimensions=latent_dimensions, feature_size=feature_size[0] ) encoder_2 = architectures.Encoder( - latent_dimensions=latent_dimensions, feature_size=12 + latent_dimensions=latent_dimensions, feature_size=feature_size[1] ) dmcca = DCCA( latent_dimensions=latent_dimensions, @@ -313,16 +313,16 @@ def test_DCCAE_methods(): max_epochs = 2 latent_dimensions = 2 encoder_1 = architectures.CNNEncoder( - latent_dimensions=latent_dimensions, feature_size=(16, 16) + latent_dimensions=latent_dimensions, feature_size=(4, 4) ) encoder_2 = architectures.CNNEncoder( - latent_dimensions=latent_dimensions, feature_size=(16, 16) + latent_dimensions=latent_dimensions, feature_size=(4, 4) ) decoder_1 = architectures.CNNDecoder( - latent_dimensions=latent_dimensions, feature_size=(16, 16) + latent_dimensions=latent_dimensions, feature_size=(4, 4) ) decoder_2 = architectures.CNNDecoder( - latent_dimensions=latent_dimensions, feature_size=(16, 16) + latent_dimensions=latent_dimensions, feature_size=(4, 4) ) # SplitAE splitae = SplitAE( @@ -346,22 +346,30 @@ def test_DVCCA_p_methods(): max_epochs = 2 latent_dimensions = 2 encoder_1 = architectures.Encoder( - latent_dimensions=latent_dimensions, feature_size=10, variational=True + latent_dimensions=latent_dimensions, + feature_size=feature_size[0], + variational=True, ) encoder_2 = architectures.Encoder( - latent_dimensions=latent_dimensions, feature_size=12, variational=True + latent_dimensions=latent_dimensions, + feature_size=feature_size[1], + variational=True, ) private_encoder_1 = architectures.Encoder( - latent_dimensions=latent_dimensions, feature_size=10, variational=True + latent_dimensions=latent_dimensions, + feature_size=feature_size[0], + variational=True, ) private_encoder_2 = architectures.Encoder( - latent_dimensions=latent_dimensions, feature_size=12, variational=True + latent_dimensions=latent_dimensions, + feature_size=feature_size[1], + variational=True, ) decoder_1 = architectures.Decoder( - latent_dimensions=2 * latent_dimensions, feature_size=10 + latent_dimensions=2 * latent_dimensions, feature_size=feature_size[0] ) decoder_2 = architectures.Decoder( - latent_dimensions=2 * latent_dimensions, feature_size=12 + latent_dimensions=2 * latent_dimensions, feature_size=feature_size[1] ) # DVCCA dvcca = DVCCA( @@ -379,16 +387,20 @@ def test_DVCCA_methods(): max_epochs = 2 latent_dimensions = 2 encoder_1 = architectures.Encoder( - latent_dimensions=latent_dimensions, feature_size=10, variational=True + latent_dimensions=latent_dimensions, + feature_size=feature_size[0], + variational=True, ) encoder_2 = architectures.Encoder( - latent_dimensions=latent_dimensions, feature_size=12, variational=True + latent_dimensions=latent_dimensions, + feature_size=feature_size[1], + variational=True, ) decoder_1 = architectures.Decoder( - latent_dimensions=latent_dimensions, feature_size=10 + latent_dimensions=latent_dimensions, feature_size=feature_size[0] ) decoder_2 = architectures.Decoder( - latent_dimensions=latent_dimensions, feature_size=12 + latent_dimensions=latent_dimensions, feature_size=feature_size[1] ) dvcca = DVCCA( latent_dimensions=latent_dimensions, diff --git a/test/test_explained_variance.py b/test/test_explained_variance.py index 59a877ef..76100ec0 100644 --- a/test/test_explained_variance.py +++ b/test/test_explained_variance.py @@ -4,6 +4,9 @@ from cca_zoo._base import BaseModel from cca_zoo.linear import MPLS +N = 50 +features = [4, 6, 8] + @pytest.fixture def rng(): @@ -19,10 +22,10 @@ def toy_model(rng): @pytest.fixture def synthetic_views(rng): - # Generating three synthetic representations with 100 samples each - view1 = rng.random((100, 10)) - view2 = rng.random((100, 8)) - view3 = rng.random((100, 5)) + # Generating three synthetic representations with N samples each + view1 = rng.random((N, features[0])) + view2 = rng.random((N, features[1])) + view3 = rng.random((N, features[2])) # demean view1 -= view1.mean(axis=0) view2 -= view2.mean(axis=0) diff --git a/test/test_gradient.py b/test/test_gradient.py index 4870cbe0..baac1b0a 100644 --- a/test/test_gradient.py +++ b/test/test_gradient.py @@ -1,34 +1,29 @@ import numpy as np import pytest -import scipy.sparse as sp from sklearn.utils import check_random_state from cca_zoo.linear import CCA, PLS n = 50 rng = check_random_state(0) -X = rng.rand(n, 10) -Y = rng.rand(n, 11) -Z = rng.rand(n, 12) -X_sp = sp.random(n, 10, density=0.5, random_state=rng) -Y_sp = sp.random(n, 11, density=0.5, random_state=rng) +X = rng.rand(n, 4) +Y = rng.rand(n, 6) +Z = rng.rand(n, 8) # centre the data X -= X.mean(axis=0) Y -= Y.mean(axis=0) Z -= Z.mean(axis=0) -X_sp -= X_sp.mean(axis=0) -Y_sp -= Y_sp.mean(axis=0) latent_dims = 3 epochs = 100 -batch_size = 10 +batch_size = 5 random_state = 1 - - -def scale_objective(obj): - # log scale the objective if negative, otherwise nan - obj = np.array(obj) - return np.sign(obj) * np.log(np.abs(obj) + 1e-10) +trainer_kwargs = dict( + enable_checkpointing=False, + logger=False, + enable_model_summary=False, + enable_progress_bar=False, +) def scale_transform(model, X, Y): @@ -50,6 +45,7 @@ def test_batch_pls(): latent_dimensions=latent_dims, epochs=epochs, random_state=random_state, + trainer_kwargs=trainer_kwargs, ).fit((X, Y)) pls_score = scale_transform(pls, X, Y) plsey_score = scale_transform(plsey, X, Y) @@ -58,32 +54,36 @@ def test_batch_pls(): def test_batch_cca(): pytest.importorskip("torch") - from cca_zoo.linear import CCA_EY, CCA_GHA, CCA_SVD + from cca_zoo.linear import CCA_EY, CCA_GHA cca = CCA(latent_dimensions=3).fit((X, Y)) ccaey = CCA_EY( latent_dimensions=latent_dims, epochs=epochs, random_state=random_state, + trainer_kwargs=trainer_kwargs, ).fit((X, Y)) ccagha = CCA_GHA( latent_dimensions=latent_dims, epochs=epochs, random_state=random_state, + trainer_kwargs=trainer_kwargs, ).fit((X, Y)) - ccasvd = CCA_SVD( - latent_dimensions=latent_dims, - epochs=epochs * 2, - random_state=random_state, - ).fit((X, Y)) + # ccasvd = CCA_SVD( + # latent_dimensions=latent_dims, + # epochs=epochs*10, + # random_state=random_state, + # trainer_kwargs=trainer_kwargs, + # learning_rate=1e-1, + # ).fit((X, Y)) cca_score = cca.score((X, Y)) ccaey_score = ccaey.score((X, Y)) ccagh_score = ccagha.score((X, Y)) - ccasvd_score = ccasvd.score((X, Y)) + # ccasvd_score = ccasvd.score((X, Y)) # check all methods are similar to cca assert np.allclose(cca_score.sum(), ccaey_score.sum(), atol=1e-1) assert np.allclose(cca_score.sum(), ccagh_score.sum(), atol=1e-1) - assert np.allclose(cca_score.sum(), ccasvd_score.sum(), atol=1e-1) + # assert np.allclose(cca_score.sum(), ccasvd_score.sum(), atol=1e-1) def test_stochastic_pls(): @@ -99,33 +99,27 @@ def test_stochastic_pls(): epochs=epochs, batch_size=batch_size, random_state=random_state, + trainer_kwargs=trainer_kwargs, ).fit((X, Y)) - # plssvd = PLS_SVD( - # latent_dimensions=latent_dims, - # epochs=epochs, - # batch_size=batch_size, - # random_state=random_state, - # ).fit((X, Y)) spls = PLSStochasticPower( latent_dimensions=latent_dims, epochs=epochs, batch_size=batch_size, random_state=random_state, + trainer_kwargs=trainer_kwargs, ).fit((X, Y)) pls_score = scale_transform(pls, X, Y) spls_score = scale_transform(spls, X, Y) plsey_score = scale_transform(plsey, X, Y) - # plssvd_score = scale_transform(plssvd, X, Y) # check all methods are similar to pls assert np.allclose(np.trace(pls_score), np.trace(spls_score), atol=1e-1) assert np.allclose(np.trace(pls_score), np.trace(plsey_score), atol=1e-1) - # assert np.allclose(np.trace(pls_score), np.trace(plssvd_score), atol=1e-1) def test_stochastic_cca(): pytest.importorskip("torch") - from cca_zoo.linear import CCA_EY, CCA_GHA, CCA_SVD + from cca_zoo.linear import CCA_EY, CCA_GHA cca = CCA(latent_dimensions=3).fit((X, Y)) ccaey = CCA_EY( @@ -133,27 +127,30 @@ def test_stochastic_cca(): epochs=epochs, batch_size=batch_size, random_state=random_state, + trainer_kwargs=trainer_kwargs, ).fit((X, Y)) ccagha = CCA_GHA( latent_dimensions=3, epochs=epochs, batch_size=batch_size, random_state=random_state, + trainer_kwargs=trainer_kwargs, ).fit((X, Y)) - ccasvd = CCA_SVD( - latent_dimensions=latent_dims, - epochs=epochs, - batch_size=batch_size, - random_state=random_state, - ).fit((X, Y)) + # ccasvd = CCA_SVD( + # latent_dimensions=latent_dims, + # epochs=epochs, + # batch_size=batch_size, + # random_state=random_state, + # trainer_kwargs=trainer_kwargs, + # ).fit((X, Y)) cca_score = cca.score((X, Y)) ccaey_score = ccaey.score((X, Y)) ccagha_score = ccagha.score((X, Y)) - ccasvd_score = ccasvd.score((X, Y)) + # ccasvd_score = ccasvd.score((X, Y)) # check all methods are similar to cca assert np.allclose(cca_score.sum(), ccaey_score.sum(), atol=2e-1) assert np.allclose(cca_score.sum(), ccagha_score.sum(), atol=2e-1) - assert np.allclose(cca_score.sum(), ccasvd_score.sum(), atol=2e-1) + # assert np.allclose(cca_score.sum(), ccasvd_score.sum(), atol=2e-1) def test_with_validation(): @@ -163,10 +160,8 @@ def test_with_validation(): cca = CCA(latent_dimensions=3).fit((X, Y)) ccaey = CCA_EY( latent_dimensions=latent_dims, - epochs=5, + epochs=epochs, batch_size=batch_size, random_state=random_state, - trainer_kwargs={ - "logger": True, - }, + trainer_kwargs=trainer_kwargs, ).fit((X, Y), validation_views=(X, Y)) diff --git a/test/test_nonparametric.py b/test/test_nonparametric.py index c5b96f5b..d56b9233 100644 --- a/test/test_nonparametric.py +++ b/test/test_nonparametric.py @@ -10,10 +10,12 @@ @pytest.fixture def data(): + N = 50 + features = [4, 6, 8] np.random.seed(1) - X = np.random.normal(size=(100, 10)) - Y = np.random.normal(size=(100, 10)) - Z = np.random.normal(size=(100, 10)) + X = np.random.normal(size=(N, features[0])) + Y = np.random.normal(size=(N, features[1])) + Z = np.random.normal(size=(N, features[2])) return X, Y, Z diff --git a/test/test_plotting.py b/test/test_plotting.py index c4adfe12..911aa19f 100644 --- a/test/test_plotting.py +++ b/test/test_plotting.py @@ -7,6 +7,7 @@ ExplainedVarianceDisplay, ExplainedCovarianceDisplay, ) +from sklearn.model_selection import train_test_split import numpy as np from cca_zoo.linear import MCCA import matplotlib.pyplot as plt @@ -23,13 +24,13 @@ @pytest.fixture(scope="module") def setup_data(): - X = np.random.rand(100, 10) - Y = np.random.rand(100, 10) + X = np.random.rand(50, 4) + Y = np.random.rand(50, 6) X -= X.mean(axis=0) Y -= Y.mean(axis=0) - X_train, X_test = X[:50], X[50:] - Y_train, Y_test = Y[:50], Y[50:] + # train test split + X_train, X_test, Y_train, Y_test = train_test_split(X, Y, test_size=0.2) views = [X_train, Y_train] test_views = [X_test, Y_test] diff --git a/test/test_preprocessing.py b/test/test_preprocessing.py index 42be8e0d..c21c06e8 100644 --- a/test/test_preprocessing.py +++ b/test/test_preprocessing.py @@ -6,7 +6,8 @@ @pytest.fixture def mock_data(): - brain_data = np.random.rand(100, 10) + N = 50 + brain_data = np.random.rand(N, 10) behavior_data = np.random.rand(100, 10) groups = np.random.randint(0, 2, 100) return brain_data, behavior_data, groups diff --git a/test/test_probabilistic.py b/test/test_probabilistic.py index af2c218f..ee4cc0cf 100644 --- a/test/test_probabilistic.py +++ b/test/test_probabilistic.py @@ -39,4 +39,4 @@ def test_cca_vs_probabilisticCCA(setup_data): assert ( correlation > 0.9 - ), f"Expected correlation greater than 0.95, got {correlation}" \ No newline at end of file + ), f"Expected correlation greater than 0.95, got {correlation}" diff --git a/test/test_regularised.py b/test/test_regularised.py index a422a598..04b7541d 100644 --- a/test/test_regularised.py +++ b/test/test_regularised.py @@ -50,11 +50,6 @@ def test_initialisation(): assert np.all(scores > 0), "Not all scores are positive." -def test_linear_simulated_data(): - sim_data = JointData([10, 10]).sample(100) - assert CCA().fit(sim_data).score(sim_data) > 0.9 - - def test_regularized_methods(): # Test that linear regularized methods match PLS solution when using maximum regularisation. latent_dims = 2 @@ -89,12 +84,6 @@ def test_sparse_methods(): pmd_cv = GridSearchCV(SCCA_PMD(random_state=rng), param_grid=param_grid).fit([X, Y]) assert (pmd_cv.best_estimator_.weights[0] == 0).sum() > 0 assert (pmd_cv.best_estimator_.weights[1] == 0).sum() > 0 - # tau1 = [5e-1] - # tau2 = [5e-1] - # param_grid = {"tau": [tau1, tau2]} - # pdd_cv = GridSearchCV( - # AltMaxVar(proximal="L0", random_state=rng), param_grid=param_grid - # ).fit([X, Y]) alpha1 = loguniform(1e-2, 2e-2) alpha2 = loguniform(1e-2, 2e-2) param_grid = {"alpha": [alpha1, alpha2], "l1_ratio": [[0.9], [0.9]]} @@ -115,16 +104,8 @@ def test_sparse_methods(): ).fit([X, Y]) tau1 = [1e-1] tau2 = [1e-1] - param_grid = {"tau": [tau1, tau2]} - # admm_cv = GridSearchCV(SCCA_ADMM(random_state=rng), param_grid=param_grid).fit( - # [representations, Y] - # ) - # assert (pdd_cv.best_estimator_.weights[0] == 0).sum() > 0 - # assert (pdd_cv.best_estimator_.weights[1] == 0).sum() > 0 assert (scca_cv.best_estimator_.weights[0] == 0).sum() > 0 assert (scca_cv.best_estimator_.weights[1] == 0).sum() > 0 - # assert (admm_cv.best_estimator_.weights[0] == 0).sum() > 0 - # assert (admm_cv.best_estimator_.weights[1] == 0).sum() > 0 assert (parkhomenko_cv.best_estimator_.weights[0] == 0).sum() > 0 assert (parkhomenko_cv.best_estimator_.weights[1] == 0).sum() > 0 assert (elastic_cv.best_estimator_.weights[0] == 0).sum() > 0 @@ -157,12 +138,8 @@ def test_l0(): span_cca = SCCA_Span( latent_dimensions=1, regularisation="l0", tau=[2, 2], random_state=rng ).fit([X, Y]) - # swcca = SWCCA(tau=[5, 5], sample_support=5, random_state=rng).fit([representations, Y]) assert (np.abs(span_cca.weights[0]) > 1e-5).sum() == 2 assert (np.abs(span_cca.weights[1]) > 1e-5).sum() == 2 - # assert (np.abs(swcca.weights[0]) > 1e-5).sum() == 5 - # assert (np.abs(swcca.weights[1]) > 1e-5).sum() == 5 - # assert (np.abs(swcca.sample_weights) > 1e-5).sum() == 5 def test_partialcca(): diff --git a/test/test_search.py b/test/test_search.py index c0edca2b..fa95c24f 100644 --- a/test/test_search.py +++ b/test/test_search.py @@ -52,8 +52,9 @@ def test_param2grid_with_iterable_types(): @pytest.fixture def random_data(): - X = np.random.normal(size=(100, 10)) - Y = np.random.normal(size=(100, 10)) + N = 50 + X = np.random.normal(size=(N, 10)) + Y = np.random.normal(size=(N, 10)) return X, Y diff --git a/test/test_sequential.py b/test/test_sequential.py index 5be70838..e702222e 100644 --- a/test/test_sequential.py +++ b/test/test_sequential.py @@ -10,8 +10,8 @@ # Fixtures @pytest.fixture def simulated_data(): - data_generator = JointData(view_features=[10, 10], latent_dims=5, correlation=0.8) - X, Y = data_generator.sample(200) + data_generator = JointData(view_features=[4, 6], latent_dims=5, correlation=0.8) + X, Y = data_generator.sample(50) return X, Y