From 13444cabb8318a7759e2d0941baf4aba67308a51 Mon Sep 17 00:00:00 2001 From: Laetitia Chapel Date: Wed, 15 Apr 2020 15:35:16 +0200 Subject: partial with tests --- test/test_partial.py | 141 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 141 insertions(+) create mode 100755 test/test_partial.py (limited to 'test') diff --git a/test/test_partial.py b/test/test_partial.py new file mode 100755 index 0000000..fbcd3c2 --- /dev/null +++ b/test/test_partial.py @@ -0,0 +1,141 @@ +"""Tests for module partial """ + +# Author: +# Laetitia Chapel +# +# License: MIT License + +import numpy as np +import scipy as sp +import ot + + +def test_partial_wasserstein(): + + n_samples = 20 # nb samples (gaussian) + n_noise = 20 # nb of samples (noise) + + mu = np.array([0, 0]) + cov = np.array([[1, 0], [0, 2]]) + + xs = ot.datasets.make_2D_samples_gauss(n_samples, mu, cov) + xs = np.append(xs, (np.random.rand(n_noise, 2) + 1) * 4).reshape((-1, 2)) + xt = ot.datasets.make_2D_samples_gauss(n_samples, mu, cov) + xt = np.append(xt, (np.random.rand(n_noise, 2) + 1) * -3).reshape((-1, 2)) + + M = ot.dist(xs, xt) + + p = ot.unif(n_samples + n_noise) + q = ot.unif(n_samples + n_noise) + + m = 0.5 + + w0, log0 = ot.partial.partial_wasserstein(p, q, M, m=m, log=True) + w, log = ot.partial.entropic_partial_wasserstein(p, q, M, reg=1, m=m, + log=True) + + # check constratints + np.testing.assert_equal( + w0.sum(1) - p <= 1e-5, [True] * len(p)) # cf convergence wasserstein + np.testing.assert_equal( + w0.sum(0) - q <= 1e-5, [True] * len(q)) # cf convergence wasserstein + np.testing.assert_equal( + w.sum(1) - p <= 1e-5, [True] * len(p)) # cf convergence wasserstein + np.testing.assert_equal( + w.sum(0) - q <= 1e-5, [True] * len(q)) # cf convergence wasserstein + + # check transported mass + np.testing.assert_allclose( + np.sum(w0), m, atol=1e-04) + np.testing.assert_allclose( + np.sum(w), m, atol=1e-04) + + w0, log0 = ot.partial.partial_wasserstein2(p, q, M, m=m, log=True) + w0_val = ot.partial.partial_wasserstein2(p, q, M, m=m, log=False) + + G = log0['T'] + + np.testing.assert_allclose(w0, w0_val, atol=1e-1, rtol=1e-1) + + # check constratints + np.testing.assert_equal( + G.sum(1) <= p, [True] * len(p)) # cf convergence wasserstein + np.testing.assert_equal( + G.sum(0) <= q, [True] * len(q)) # cf convergence wasserstein + np.testing.assert_allclose( + np.sum(G), m, atol=1e-04) + + +def test_partial_gromov_wasserstein(): + n_samples = 20 # nb samples + n_noise = 10 # nb of samples (noise) + + p = ot.unif(n_samples + n_noise) + q = ot.unif(n_samples + n_noise) + + mu_s = np.array([0, 0]) + cov_s = np.array([[1, 0], [0, 1]]) + + mu_t = np.array([0, 0, 0]) + cov_t = np.array([[1, 0, 0], [0, 1, 0], [0, 0, 1]]) + + xs = ot.datasets.make_2D_samples_gauss(n_samples, mu_s, cov_s) + xs = np.concatenate((xs, ((np.random.rand(n_noise, 2) + 1) * 4)), axis=0) + P = sp.linalg.sqrtm(cov_t) + xt = np.random.randn(n_samples, 3).dot(P) + mu_t + xt = np.concatenate((xt, ((np.random.rand(n_noise, 3) + 1) * 10)), axis=0) + xt2 = xs[::-1].copy() + + C1 = ot.dist(xs, xs) + C2 = ot.dist(xt, xt) + C3 = ot.dist(xt2, xt2) + + m = 2 / 3 + res0, log0 = ot.partial.partial_gromov_wasserstein(C1, C3, p, q, m=m, + log=True) + res, log = ot.partial.entropic_partial_gromov_wasserstein(C1, C3, p, q, 10, + m=m, log=True) + np.testing.assert_allclose(res0, 0, atol=1e-1, rtol=1e-1) + np.testing.assert_allclose(res, 0, atol=1e-1, rtol=1e-1) + + C1 = sp.spatial.distance.cdist(xs, xs) + C2 = sp.spatial.distance.cdist(xt, xt) + + m = 1 + res0, log0 = ot.partial.partial_gromov_wasserstein(C1, C2, p, q, m=m, + log=True) + G = ot.gromov.gromov_wasserstein(C1, C2, p, q, 'square_loss') + np.testing.assert_allclose(G, res0, atol=1e-04) + + res, log = ot.partial.entropic_partial_gromov_wasserstein(C1, C2, p, q, 10, + m=m, log=True) + G = ot.gromov.entropic_gromov_wasserstein( + C1, C2, p, q, 'square_loss', epsilon=10) + np.testing.assert_allclose(G, res, atol=1e-02) + + w0, log0 = ot.partial.partial_gromov_wasserstein2(C1, C2, p, q, m=m, + log=True) + w0_val = ot.partial.partial_gromov_wasserstein2(C1, C2, p, q, m=m, + log=False) + G = log0['T'] + np.testing.assert_allclose(w0, w0_val, atol=1e-1, rtol=1e-1) + + m = 2 / 3 + res0, log0 = ot.partial.partial_gromov_wasserstein(C1, C2, p, q, m=m, + log=True) + res, log = ot.partial.entropic_partial_gromov_wasserstein(C1, C2, p, q, 10, + m=m, log=True) + # check constratints + np.testing.assert_equal( + res0.sum(1) <= p, [True] * len(p)) # cf convergence wasserstein + np.testing.assert_equal( + res0.sum(0) <= q, [True] * len(q)) # cf convergence wasserstein + np.testing.assert_allclose( + np.sum(res0), m, atol=1e-04) + + np.testing.assert_equal( + res.sum(1) <= p, [True] * len(p)) # cf convergence wasserstein + np.testing.assert_equal( + res.sum(0) <= q, [True] * len(q)) # cf convergence wasserstein + np.testing.assert_allclose( + np.sum(res), m, atol=1e-04) -- cgit v1.2.3 From ef7c11a5df3cf6c82864472f0cfa65d6b2036f2f Mon Sep 17 00:00:00 2001 From: Laetitia Chapel Date: Thu, 16 Apr 2020 15:52:00 +0200 Subject: partial with python 3.8 --- .travis.yml | 2 +- ot/partial.py | 12 ++++++------ test/test_partial.py | 9 ++++----- 3 files changed, 11 insertions(+), 12 deletions(-) (limited to 'test') diff --git a/.travis.yml b/.travis.yml index 072bc55..7ff1b3c 100644 --- a/.travis.yml +++ b/.travis.yml @@ -16,7 +16,7 @@ matrix: python: 3.7 - os: linux sudo: required - python: 2.7 + python: 3.8 # - os: osx # sudo: required # language: generic diff --git a/ot/partial.py b/ot/partial.py index 8698d9d..726a590 100755 --- a/ot/partial.py +++ b/ot/partial.py @@ -232,7 +232,7 @@ def partial_wasserstein(a, b, M, m=None, nb_dummies=1, log=False, **kwargs): b_extended = np.append(b, [(np.sum(a) - m) / nb_dummies] * nb_dummies) a_extended = np.append(a, [(np.sum(b) - m) / nb_dummies] * nb_dummies) - M_extended = np.ones((len(a_extended), len(b_extended))) * 0 + M_extended = np.zeros((len(a_extended), len(b_extended))) M_extended[-1, -1] = np.max(M) * 1e5 M_extended[:len(a), :len(b)] = M @@ -510,9 +510,9 @@ def partial_gromov_wasserstein(C1, C2, p, q, m=None, nb_dummies=1, G0=None, Gprev = G0 M = gwgrad_partial(C1, C2, G0) - M[M < eps] = np.quantile(M[M > eps], thres) + M[M < eps] = np.quantile(M, thres) - M_emd = np.ones(dim_G_extended) * np.max(M) * 1e2 + M_emd = np.zeros(dim_G_extended) M_emd[:len(p), :len(q)] = M M_emd[-nb_dummies:, -nb_dummies:] = np.max(M) * 1e5 M_emd = np.asarray(M_emd, dtype=np.float64) @@ -729,8 +729,8 @@ def entropic_partial_wasserstein(a, b, M, reg, m=None, numItermax=1000, M = np.asarray(M, dtype=np.float64) dim_a, dim_b = M.shape - dx = np.ones(dim_a) - dy = np.ones(dim_b) + dx = np.ones(dim_a, dtype=np.float64) + dy = np.ones(dim_b, dtype=np.float64) if len(a) == 0: a = np.ones(dim_a, dtype=np.float64) / dim_a @@ -738,7 +738,7 @@ def entropic_partial_wasserstein(a, b, M, reg, m=None, numItermax=1000, b = np.ones(dim_b, dtype=np.float64) / dim_b if m is None: - m = np.min((np.sum(a), np.sum(b))) + m = np.min((np.sum(a), np.sum(b))) * 1.0 if m < 0: raise ValueError("Problem infeasible. Parameter m should be greater" " than 0.") diff --git a/test/test_partial.py b/test/test_partial.py index fbcd3c2..1799fd4 100755 --- a/test/test_partial.py +++ b/test/test_partial.py @@ -93,10 +93,7 @@ def test_partial_gromov_wasserstein(): m = 2 / 3 res0, log0 = ot.partial.partial_gromov_wasserstein(C1, C3, p, q, m=m, log=True) - res, log = ot.partial.entropic_partial_gromov_wasserstein(C1, C3, p, q, 10, - m=m, log=True) np.testing.assert_allclose(res0, 0, atol=1e-1, rtol=1e-1) - np.testing.assert_allclose(res, 0, atol=1e-1, rtol=1e-1) C1 = sp.spatial.distance.cdist(xs, xs) C2 = sp.spatial.distance.cdist(xt, xt) @@ -123,8 +120,10 @@ def test_partial_gromov_wasserstein(): m = 2 / 3 res0, log0 = ot.partial.partial_gromov_wasserstein(C1, C2, p, q, m=m, log=True) - res, log = ot.partial.entropic_partial_gromov_wasserstein(C1, C2, p, q, 10, - m=m, log=True) + res, log = ot.partial.entropic_partial_gromov_wasserstein(C1, C2, p, q, + 100, m=m, + log=True) + # check constratints np.testing.assert_equal( res0.sum(1) <= p, [True] * len(p)) # cf convergence wasserstein -- cgit v1.2.3 From 47306ad23d0c9943c14149ffd85d1c3d0544a3df Mon Sep 17 00:00:00 2001 From: Laetitia Chapel Date: Thu, 16 Apr 2020 16:25:16 +0200 Subject: partial with python 3.8 --- test/test_partial.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'test') diff --git a/test/test_partial.py b/test/test_partial.py index 1799fd4..ce363bd 100755 --- a/test/test_partial.py +++ b/test/test_partial.py @@ -123,7 +123,7 @@ def test_partial_gromov_wasserstein(): res, log = ot.partial.entropic_partial_gromov_wasserstein(C1, C2, p, q, 100, m=m, log=True) - + # check constratints np.testing.assert_equal( res0.sum(1) <= p, [True] * len(p)) # cf convergence wasserstein -- cgit v1.2.3 From d2ecce4a79228cd10f4beba8b6b2b28239be796d Mon Sep 17 00:00:00 2001 From: Laetitia Chapel Date: Thu, 16 Apr 2020 16:42:59 +0200 Subject: partial with python 3.8 --- test/test_partial.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'test') diff --git a/test/test_partial.py b/test/test_partial.py index ce363bd..8b1ca89 100755 --- a/test/test_partial.py +++ b/test/test_partial.py @@ -123,7 +123,7 @@ def test_partial_gromov_wasserstein(): res, log = ot.partial.entropic_partial_gromov_wasserstein(C1, C2, p, q, 100, m=m, log=True) - + # check constratints np.testing.assert_equal( res0.sum(1) <= p, [True] * len(p)) # cf convergence wasserstein -- cgit v1.2.3