summaryrefslogtreecommitdiff
path: root/test
diff options
context:
space:
mode:
Diffstat (limited to 'test')
-rw-r--r--test/test_bregman.py137
-rw-r--r--test/test_da.py469
-rw-r--r--test/test_dr.py59
-rw-r--r--test/test_emd_multi.py48
-rw-r--r--test/test_gpu.py79
-rw-r--r--test/test_gpu_sinkhorn.py26
-rw-r--r--test/test_gpu_sinkhorn_lpl1.py28
-rw-r--r--test/test_load_module.py10
-rw-r--r--test/test_optim.py67
-rw-r--r--test/test_ot.py102
-rw-r--r--test/test_plot.py49
-rw-r--r--test/test_utils.py125
12 files changed, 1087 insertions, 112 deletions
diff --git a/test/test_bregman.py b/test/test_bregman.py
new file mode 100644
index 0000000..4a800fd
--- /dev/null
+++ b/test/test_bregman.py
@@ -0,0 +1,137 @@
+"""Tests for module bregman on OT with bregman projections """
+
+# Author: Remi Flamary <remi.flamary@unice.fr>
+#
+# License: MIT License
+
+import numpy as np
+import ot
+
+
+def test_sinkhorn():
+ # test sinkhorn
+ n = 100
+ rng = np.random.RandomState(0)
+
+ x = rng.randn(n, 2)
+ u = ot.utils.unif(n)
+
+ M = ot.dist(x, x)
+
+ G = ot.sinkhorn(u, u, M, 1, stopThr=1e-10)
+
+ # check constratints
+ np.testing.assert_allclose(
+ u, G.sum(1), atol=1e-05) # cf convergence sinkhorn
+ np.testing.assert_allclose(
+ u, G.sum(0), atol=1e-05) # cf convergence sinkhorn
+
+
+def test_sinkhorn_empty():
+ # test sinkhorn
+ n = 100
+ rng = np.random.RandomState(0)
+
+ x = rng.randn(n, 2)
+ u = ot.utils.unif(n)
+
+ M = ot.dist(x, x)
+
+ G, log = ot.sinkhorn([], [], M, 1, stopThr=1e-10, verbose=True, log=True)
+ # check constratints
+ np.testing.assert_allclose(u, G.sum(1), atol=1e-05)
+ np.testing.assert_allclose(u, G.sum(0), atol=1e-05)
+
+ G, log = ot.sinkhorn([], [], M, 1, stopThr=1e-10,
+ method='sinkhorn_stabilized', verbose=True, log=True)
+ # check constratints
+ np.testing.assert_allclose(u, G.sum(1), atol=1e-05)
+ np.testing.assert_allclose(u, G.sum(0), atol=1e-05)
+
+ G, log = ot.sinkhorn(
+ [], [], M, 1, stopThr=1e-10, method='sinkhorn_epsilon_scaling',
+ verbose=True, log=True)
+ # check constratints
+ np.testing.assert_allclose(u, G.sum(1), atol=1e-05)
+ np.testing.assert_allclose(u, G.sum(0), atol=1e-05)
+
+
+def test_sinkhorn_variants():
+ # test sinkhorn
+ n = 100
+ rng = np.random.RandomState(0)
+
+ x = rng.randn(n, 2)
+ u = ot.utils.unif(n)
+
+ M = ot.dist(x, x)
+
+ G0 = ot.sinkhorn(u, u, M, 1, method='sinkhorn', stopThr=1e-10)
+ Gs = ot.sinkhorn(u, u, M, 1, method='sinkhorn_stabilized', stopThr=1e-10)
+ Ges = ot.sinkhorn(
+ u, u, M, 1, method='sinkhorn_epsilon_scaling', stopThr=1e-10)
+ Gerr = ot.sinkhorn(u, u, M, 1, method='do_not_exists', stopThr=1e-10)
+
+ # check values
+ np.testing.assert_allclose(G0, Gs, atol=1e-05)
+ np.testing.assert_allclose(G0, Ges, atol=1e-05)
+ np.testing.assert_allclose(G0, Gerr)
+
+
+def test_bary():
+
+ n_bins = 100 # nb bins
+
+ # Gaussian distributions
+ a1 = ot.datasets.get_1D_gauss(n_bins, m=30, s=10) # m= mean, s= std
+ a2 = ot.datasets.get_1D_gauss(n_bins, m=40, s=10)
+
+ # creating matrix A containing all distributions
+ A = np.vstack((a1, a2)).T
+
+ # loss matrix + normalization
+ M = ot.utils.dist0(n_bins)
+ M /= M.max()
+
+ alpha = 0.5 # 0<=alpha<=1
+ weights = np.array([1 - alpha, alpha])
+
+ # wasserstein
+ reg = 1e-3
+ bary_wass = ot.bregman.barycenter(A, M, reg, weights)
+
+ np.testing.assert_allclose(1, np.sum(bary_wass))
+
+ ot.bregman.barycenter(A, M, reg, log=True, verbose=True)
+
+
+def test_unmix():
+
+ n_bins = 50 # nb bins
+
+ # Gaussian distributions
+ a1 = ot.datasets.get_1D_gauss(n_bins, m=20, s=10) # m= mean, s= std
+ a2 = ot.datasets.get_1D_gauss(n_bins, m=40, s=10)
+
+ a = ot.datasets.get_1D_gauss(n_bins, m=30, s=10)
+
+ # creating matrix A containing all distributions
+ D = np.vstack((a1, a2)).T
+
+ # loss matrix + normalization
+ M = ot.utils.dist0(n_bins)
+ M /= M.max()
+
+ M0 = ot.utils.dist0(2)
+ M0 /= M0.max()
+ h0 = ot.unif(2)
+
+ # wasserstein
+ reg = 1e-3
+ um = ot.bregman.unmix(a, D, M, M0, h0, reg, 1, alpha=0.01,)
+
+ np.testing.assert_allclose(1, np.sum(um), rtol=1e-03, atol=1e-03)
+ np.testing.assert_allclose([0.5, 0.5], um, rtol=1e-03, atol=1e-03)
+
+ ot.bregman.unmix(a, D, M, M0, h0, reg,
+ 1, alpha=0.01, log=True, verbose=True)
diff --git a/test/test_da.py b/test/test_da.py
new file mode 100644
index 0000000..104a798
--- /dev/null
+++ b/test/test_da.py
@@ -0,0 +1,469 @@
+"""Tests for module da on Domain Adaptation """
+
+# Author: Remi Flamary <remi.flamary@unice.fr>
+#
+# License: MIT License
+
+import numpy as np
+from numpy.testing.utils import assert_allclose, assert_equal
+
+import ot
+from ot.datasets import get_data_classif
+from ot.utils import unif
+
+
+def test_sinkhorn_lpl1_transport_class():
+ """test_sinkhorn_transport
+ """
+
+ ns = 150
+ nt = 200
+
+ Xs, ys = get_data_classif('3gauss', ns)
+ Xt, yt = get_data_classif('3gauss2', nt)
+
+ clf = ot.da.SinkhornLpl1Transport()
+
+ # test its computed
+ clf.fit(Xs=Xs, ys=ys, Xt=Xt)
+ assert hasattr(clf, "cost_")
+ assert hasattr(clf, "coupling_")
+
+ # test dimensions of coupling
+ assert_equal(clf.cost_.shape, ((Xs.shape[0], Xt.shape[0])))
+ assert_equal(clf.coupling_.shape, ((Xs.shape[0], Xt.shape[0])))
+
+ # test margin constraints
+ mu_s = unif(ns)
+ mu_t = unif(nt)
+ assert_allclose(np.sum(clf.coupling_, axis=0), mu_t, rtol=1e-3, atol=1e-3)
+ assert_allclose(np.sum(clf.coupling_, axis=1), mu_s, rtol=1e-3, atol=1e-3)
+
+ # test transform
+ transp_Xs = clf.transform(Xs=Xs)
+ assert_equal(transp_Xs.shape, Xs.shape)
+
+ Xs_new, _ = get_data_classif('3gauss', ns + 1)
+ transp_Xs_new = clf.transform(Xs_new)
+
+ # check that the oos method is working
+ assert_equal(transp_Xs_new.shape, Xs_new.shape)
+
+ # test inverse transform
+ transp_Xt = clf.inverse_transform(Xt=Xt)
+ assert_equal(transp_Xt.shape, Xt.shape)
+
+ Xt_new, _ = get_data_classif('3gauss2', nt + 1)
+ transp_Xt_new = clf.inverse_transform(Xt=Xt_new)
+
+ # check that the oos method is working
+ assert_equal(transp_Xt_new.shape, Xt_new.shape)
+
+ # test fit_transform
+ transp_Xs = clf.fit_transform(Xs=Xs, ys=ys, Xt=Xt)
+ assert_equal(transp_Xs.shape, Xs.shape)
+
+ # test semi supervised mode
+ clf = ot.da.SinkhornLpl1Transport()
+ clf.fit(Xs=Xs, ys=ys, Xt=Xt)
+ n_unsup = np.sum(clf.cost_)
+
+ # test semi supervised mode
+ clf = ot.da.SinkhornLpl1Transport()
+ clf.fit(Xs=Xs, ys=ys, Xt=Xt, yt=yt)
+ assert_equal(clf.cost_.shape, ((Xs.shape[0], Xt.shape[0])))
+ n_semisup = np.sum(clf.cost_)
+
+ assert n_unsup != n_semisup, "semisupervised mode not working"
+
+
+def test_sinkhorn_l1l2_transport_class():
+ """test_sinkhorn_transport
+ """
+
+ ns = 150
+ nt = 200
+
+ Xs, ys = get_data_classif('3gauss', ns)
+ Xt, yt = get_data_classif('3gauss2', nt)
+
+ clf = ot.da.SinkhornL1l2Transport()
+
+ # test its computed
+ clf.fit(Xs=Xs, ys=ys, Xt=Xt)
+ assert hasattr(clf, "cost_")
+ assert hasattr(clf, "coupling_")
+ assert hasattr(clf, "log_")
+
+ # test dimensions of coupling
+ assert_equal(clf.cost_.shape, ((Xs.shape[0], Xt.shape[0])))
+ assert_equal(clf.coupling_.shape, ((Xs.shape[0], Xt.shape[0])))
+
+ # test margin constraints
+ mu_s = unif(ns)
+ mu_t = unif(nt)
+ assert_allclose(np.sum(clf.coupling_, axis=0), mu_t, rtol=1e-3, atol=1e-3)
+ assert_allclose(np.sum(clf.coupling_, axis=1), mu_s, rtol=1e-3, atol=1e-3)
+
+ # test transform
+ transp_Xs = clf.transform(Xs=Xs)
+ assert_equal(transp_Xs.shape, Xs.shape)
+
+ Xs_new, _ = get_data_classif('3gauss', ns + 1)
+ transp_Xs_new = clf.transform(Xs_new)
+
+ # check that the oos method is working
+ assert_equal(transp_Xs_new.shape, Xs_new.shape)
+
+ # test inverse transform
+ transp_Xt = clf.inverse_transform(Xt=Xt)
+ assert_equal(transp_Xt.shape, Xt.shape)
+
+ Xt_new, _ = get_data_classif('3gauss2', nt + 1)
+ transp_Xt_new = clf.inverse_transform(Xt=Xt_new)
+
+ # check that the oos method is working
+ assert_equal(transp_Xt_new.shape, Xt_new.shape)
+
+ # test fit_transform
+ transp_Xs = clf.fit_transform(Xs=Xs, ys=ys, Xt=Xt)
+ assert_equal(transp_Xs.shape, Xs.shape)
+
+ # test semi supervised mode
+ clf = ot.da.SinkhornL1l2Transport()
+ clf.fit(Xs=Xs, ys=ys, Xt=Xt)
+ n_unsup = np.sum(clf.cost_)
+
+ # test semi supervised mode
+ clf = ot.da.SinkhornL1l2Transport()
+ clf.fit(Xs=Xs, ys=ys, Xt=Xt, yt=yt)
+ assert_equal(clf.cost_.shape, ((Xs.shape[0], Xt.shape[0])))
+ n_semisup = np.sum(clf.cost_)
+
+ assert n_unsup != n_semisup, "semisupervised mode not working"
+
+ # check everything runs well with log=True
+ clf = ot.da.SinkhornL1l2Transport(log=True)
+ clf.fit(Xs=Xs, ys=ys, Xt=Xt)
+ assert len(clf.log_.keys()) != 0
+
+
+def test_sinkhorn_transport_class():
+ """test_sinkhorn_transport
+ """
+
+ ns = 150
+ nt = 200
+
+ Xs, ys = get_data_classif('3gauss', ns)
+ Xt, yt = get_data_classif('3gauss2', nt)
+
+ clf = ot.da.SinkhornTransport()
+
+ # test its computed
+ clf.fit(Xs=Xs, Xt=Xt)
+ assert hasattr(clf, "cost_")
+ assert hasattr(clf, "coupling_")
+ assert hasattr(clf, "log_")
+
+ # test dimensions of coupling
+ assert_equal(clf.cost_.shape, ((Xs.shape[0], Xt.shape[0])))
+ assert_equal(clf.coupling_.shape, ((Xs.shape[0], Xt.shape[0])))
+
+ # test margin constraints
+ mu_s = unif(ns)
+ mu_t = unif(nt)
+ assert_allclose(np.sum(clf.coupling_, axis=0), mu_t, rtol=1e-3, atol=1e-3)
+ assert_allclose(np.sum(clf.coupling_, axis=1), mu_s, rtol=1e-3, atol=1e-3)
+
+ # test transform
+ transp_Xs = clf.transform(Xs=Xs)
+ assert_equal(transp_Xs.shape, Xs.shape)
+
+ Xs_new, _ = get_data_classif('3gauss', ns + 1)
+ transp_Xs_new = clf.transform(Xs_new)
+
+ # check that the oos method is working
+ assert_equal(transp_Xs_new.shape, Xs_new.shape)
+
+ # test inverse transform
+ transp_Xt = clf.inverse_transform(Xt=Xt)
+ assert_equal(transp_Xt.shape, Xt.shape)
+
+ Xt_new, _ = get_data_classif('3gauss2', nt + 1)
+ transp_Xt_new = clf.inverse_transform(Xt=Xt_new)
+
+ # check that the oos method is working
+ assert_equal(transp_Xt_new.shape, Xt_new.shape)
+
+ # test fit_transform
+ transp_Xs = clf.fit_transform(Xs=Xs, Xt=Xt)
+ assert_equal(transp_Xs.shape, Xs.shape)
+
+ # test semi supervised mode
+ clf = ot.da.SinkhornTransport()
+ clf.fit(Xs=Xs, Xt=Xt)
+ n_unsup = np.sum(clf.cost_)
+
+ # test semi supervised mode
+ clf = ot.da.SinkhornTransport()
+ clf.fit(Xs=Xs, ys=ys, Xt=Xt, yt=yt)
+ assert_equal(clf.cost_.shape, ((Xs.shape[0], Xt.shape[0])))
+ n_semisup = np.sum(clf.cost_)
+
+ assert n_unsup != n_semisup, "semisupervised mode not working"
+
+ # check everything runs well with log=True
+ clf = ot.da.SinkhornTransport(log=True)
+ clf.fit(Xs=Xs, ys=ys, Xt=Xt)
+ assert len(clf.log_.keys()) != 0
+
+
+def test_emd_transport_class():
+ """test_sinkhorn_transport
+ """
+
+ ns = 150
+ nt = 200
+
+ Xs, ys = get_data_classif('3gauss', ns)
+ Xt, yt = get_data_classif('3gauss2', nt)
+
+ clf = ot.da.EMDTransport()
+
+ # test its computed
+ clf.fit(Xs=Xs, Xt=Xt)
+ assert hasattr(clf, "cost_")
+ assert hasattr(clf, "coupling_")
+
+ # test dimensions of coupling
+ assert_equal(clf.cost_.shape, ((Xs.shape[0], Xt.shape[0])))
+ assert_equal(clf.coupling_.shape, ((Xs.shape[0], Xt.shape[0])))
+
+ # test margin constraints
+ mu_s = unif(ns)
+ mu_t = unif(nt)
+ assert_allclose(np.sum(clf.coupling_, axis=0), mu_t, rtol=1e-3, atol=1e-3)
+ assert_allclose(np.sum(clf.coupling_, axis=1), mu_s, rtol=1e-3, atol=1e-3)
+
+ # test transform
+ transp_Xs = clf.transform(Xs=Xs)
+ assert_equal(transp_Xs.shape, Xs.shape)
+
+ Xs_new, _ = get_data_classif('3gauss', ns + 1)
+ transp_Xs_new = clf.transform(Xs_new)
+
+ # check that the oos method is working
+ assert_equal(transp_Xs_new.shape, Xs_new.shape)
+
+ # test inverse transform
+ transp_Xt = clf.inverse_transform(Xt=Xt)
+ assert_equal(transp_Xt.shape, Xt.shape)
+
+ Xt_new, _ = get_data_classif('3gauss2', nt + 1)
+ transp_Xt_new = clf.inverse_transform(Xt=Xt_new)
+
+ # check that the oos method is working
+ assert_equal(transp_Xt_new.shape, Xt_new.shape)
+
+ # test fit_transform
+ transp_Xs = clf.fit_transform(Xs=Xs, Xt=Xt)
+ assert_equal(transp_Xs.shape, Xs.shape)
+
+ # test semi supervised mode
+ clf = ot.da.EMDTransport()
+ clf.fit(Xs=Xs, Xt=Xt)
+ n_unsup = np.sum(clf.cost_)
+
+ # test semi supervised mode
+ clf = ot.da.EMDTransport()
+ clf.fit(Xs=Xs, ys=ys, Xt=Xt, yt=yt)
+ assert_equal(clf.cost_.shape, ((Xs.shape[0], Xt.shape[0])))
+ n_semisup = np.sum(clf.cost_)
+
+ assert n_unsup != n_semisup, "semisupervised mode not working"
+
+
+def test_mapping_transport_class():
+ """test_mapping_transport
+ """
+
+ ns = 150
+ nt = 200
+
+ Xs, ys = get_data_classif('3gauss', ns)
+ Xt, yt = get_data_classif('3gauss2', nt)
+ Xs_new, _ = get_data_classif('3gauss', ns + 1)
+
+ ##########################################################################
+ # kernel == linear mapping tests
+ ##########################################################################
+
+ # check computation and dimensions if bias == False
+ clf = ot.da.MappingTransport(kernel="linear", bias=False)
+ clf.fit(Xs=Xs, Xt=Xt)
+ assert hasattr(clf, "coupling_")
+ assert hasattr(clf, "mapping_")
+ assert hasattr(clf, "log_")
+
+ assert_equal(clf.coupling_.shape, ((Xs.shape[0], Xt.shape[0])))
+ assert_equal(clf.mapping_.shape, ((Xs.shape[1], Xt.shape[1])))
+
+ # test margin constraints
+ mu_s = unif(ns)
+ mu_t = unif(nt)
+ assert_allclose(np.sum(clf.coupling_, axis=0), mu_t, rtol=1e-3, atol=1e-3)
+ assert_allclose(np.sum(clf.coupling_, axis=1), mu_s, rtol=1e-3, atol=1e-3)
+
+ # test transform
+ transp_Xs = clf.transform(Xs=Xs)
+ assert_equal(transp_Xs.shape, Xs.shape)
+
+ transp_Xs_new = clf.transform(Xs_new)
+
+ # check that the oos method is working
+ assert_equal(transp_Xs_new.shape, Xs_new.shape)
+
+ # check computation and dimensions if bias == True
+ clf = ot.da.MappingTransport(kernel="linear", bias=True)
+ clf.fit(Xs=Xs, Xt=Xt)
+ assert_equal(clf.coupling_.shape, ((Xs.shape[0], Xt.shape[0])))
+ assert_equal(clf.mapping_.shape, ((Xs.shape[1] + 1, Xt.shape[1])))
+
+ # test margin constraints
+ mu_s = unif(ns)
+ mu_t = unif(nt)
+ assert_allclose(np.sum(clf.coupling_, axis=0), mu_t, rtol=1e-3, atol=1e-3)
+ assert_allclose(np.sum(clf.coupling_, axis=1), mu_s, rtol=1e-3, atol=1e-3)
+
+ # test transform
+ transp_Xs = clf.transform(Xs=Xs)
+ assert_equal(transp_Xs.shape, Xs.shape)
+
+ transp_Xs_new = clf.transform(Xs_new)
+
+ # check that the oos method is working
+ assert_equal(transp_Xs_new.shape, Xs_new.shape)
+
+ ##########################################################################
+ # kernel == gaussian mapping tests
+ ##########################################################################
+
+ # check computation and dimensions if bias == False
+ clf = ot.da.MappingTransport(kernel="gaussian", bias=False)
+ clf.fit(Xs=Xs, Xt=Xt)
+
+ assert_equal(clf.coupling_.shape, ((Xs.shape[0], Xt.shape[0])))
+ assert_equal(clf.mapping_.shape, ((Xs.shape[0], Xt.shape[1])))
+
+ # test margin constraints
+ mu_s = unif(ns)
+ mu_t = unif(nt)
+ assert_allclose(np.sum(clf.coupling_, axis=0), mu_t, rtol=1e-3, atol=1e-3)
+ assert_allclose(np.sum(clf.coupling_, axis=1), mu_s, rtol=1e-3, atol=1e-3)
+
+ # test transform
+ transp_Xs = clf.transform(Xs=Xs)
+ assert_equal(transp_Xs.shape, Xs.shape)
+
+ transp_Xs_new = clf.transform(Xs_new)
+
+ # check that the oos method is working
+ assert_equal(transp_Xs_new.shape, Xs_new.shape)
+
+ # check computation and dimensions if bias == True
+ clf = ot.da.MappingTransport(kernel="gaussian", bias=True)
+ clf.fit(Xs=Xs, Xt=Xt)
+ assert_equal(clf.coupling_.shape, ((Xs.shape[0], Xt.shape[0])))
+ assert_equal(clf.mapping_.shape, ((Xs.shape[0] + 1, Xt.shape[1])))
+
+ # test margin constraints
+ mu_s = unif(ns)
+ mu_t = unif(nt)
+ assert_allclose(np.sum(clf.coupling_, axis=0), mu_t, rtol=1e-3, atol=1e-3)
+ assert_allclose(np.sum(clf.coupling_, axis=1), mu_s, rtol=1e-3, atol=1e-3)
+
+ # test transform
+ transp_Xs = clf.transform(Xs=Xs)
+ assert_equal(transp_Xs.shape, Xs.shape)
+
+ transp_Xs_new = clf.transform(Xs_new)
+
+ # check that the oos method is working
+ assert_equal(transp_Xs_new.shape, Xs_new.shape)
+
+ # check everything runs well with log=True
+ clf = ot.da.MappingTransport(kernel="gaussian", log=True)
+ clf.fit(Xs=Xs, Xt=Xt)
+ assert len(clf.log_.keys()) != 0
+
+
+def test_otda():
+
+ n_samples = 150 # nb samples
+ np.random.seed(0)
+
+ xs, ys = ot.datasets.get_data_classif('3gauss', n_samples)
+ xt, yt = ot.datasets.get_data_classif('3gauss2', n_samples)
+
+ a, b = ot.unif(n_samples), ot.unif(n_samples)
+
+ # LP problem
+ da_emd = ot.da.OTDA() # init class
+ da_emd.fit(xs, xt) # fit distributions
+ da_emd.interp() # interpolation of source samples
+ da_emd.predict(xs) # interpolation of source samples
+
+ np.testing.assert_allclose(a, np.sum(da_emd.G, 1))
+ np.testing.assert_allclose(b, np.sum(da_emd.G, 0))
+
+ # sinkhorn regularization
+ lambd = 1e-1
+ da_entrop = ot.da.OTDA_sinkhorn()
+ da_entrop.fit(xs, xt, reg=lambd)
+ da_entrop.interp()
+ da_entrop.predict(xs)
+
+ np.testing.assert_allclose(a, np.sum(da_entrop.G, 1), rtol=1e-3, atol=1e-3)
+ np.testing.assert_allclose(b, np.sum(da_entrop.G, 0), rtol=1e-3, atol=1e-3)
+
+ # non-convex Group lasso regularization
+ reg = 1e-1
+ eta = 1e0
+ da_lpl1 = ot.da.OTDA_lpl1()
+ da_lpl1.fit(xs, ys, xt, reg=reg, eta=eta)
+ da_lpl1.interp()
+ da_lpl1.predict(xs)
+
+ np.testing.assert_allclose(a, np.sum(da_lpl1.G, 1), rtol=1e-3, atol=1e-3)
+ np.testing.assert_allclose(b, np.sum(da_lpl1.G, 0), rtol=1e-3, atol=1e-3)
+
+ # True Group lasso regularization
+ reg = 1e-1
+ eta = 2e0
+ da_l1l2 = ot.da.OTDA_l1l2()
+ da_l1l2.fit(xs, ys, xt, reg=reg, eta=eta, numItermax=20, verbose=True)
+ da_l1l2.interp()
+ da_l1l2.predict(xs)
+
+ np.testing.assert_allclose(a, np.sum(da_l1l2.G, 1), rtol=1e-3, atol=1e-3)
+ np.testing.assert_allclose(b, np.sum(da_l1l2.G, 0), rtol=1e-3, atol=1e-3)
+
+ # linear mapping
+ da_emd = ot.da.OTDA_mapping_linear() # init class
+ da_emd.fit(xs, xt, numItermax=10) # fit distributions
+ da_emd.predict(xs) # interpolation of source samples
+
+ # nonlinear mapping
+ da_emd = ot.da.OTDA_mapping_kernel() # init class
+ da_emd.fit(xs, xt, numItermax=10) # fit distributions
+ da_emd.predict(xs) # interpolation of source samples
+
+
+# if __name__ == "__main__":
+
+# test_sinkhorn_transport_class()
+# test_emd_transport_class()
+# test_sinkhorn_l1l2_transport_class()
+# test_sinkhorn_lpl1_transport_class()
+# test_mapping_transport_class()
diff --git a/test/test_dr.py b/test/test_dr.py
new file mode 100644
index 0000000..915012d
--- /dev/null
+++ b/test/test_dr.py
@@ -0,0 +1,59 @@
+"""Tests for module dr on Dimensionality Reduction """
+
+# Author: Remi Flamary <remi.flamary@unice.fr>
+#
+# License: MIT License
+
+import numpy as np
+import ot
+import pytest
+
+try: # test if autograd and pymanopt are installed
+ import ot.dr
+ nogo = False
+except ImportError:
+ nogo = True
+
+
+@pytest.mark.skipif(nogo, reason="Missing modules (autograd or pymanopt)")
+def test_fda():
+
+ n_samples = 90 # nb samples in source and target datasets
+ np.random.seed(0)
+
+ # generate gaussian dataset
+ xs, ys = ot.datasets.get_data_classif('gaussrot', n_samples)
+
+ n_features_noise = 8
+
+ xs = np.hstack((xs, np.random.randn(n_samples, n_features_noise)))
+
+ p = 1
+
+ Pfda, projfda = ot.dr.fda(xs, ys, p)
+
+ projfda(xs)
+
+ np.testing.assert_allclose(np.sum(Pfda**2, 0), np.ones(p))
+
+
+@pytest.mark.skipif(nogo, reason="Missing modules (autograd or pymanopt)")
+def test_wda():
+
+ n_samples = 100 # nb samples in source and target datasets
+ np.random.seed(0)
+
+ # generate gaussian dataset
+ xs, ys = ot.datasets.get_data_classif('gaussrot', n_samples)
+
+ n_features_noise = 8
+
+ xs = np.hstack((xs, np.random.randn(n_samples, n_features_noise)))
+
+ p = 2
+
+ Pwda, projwda = ot.dr.wda(xs, ys, p, maxiter=10)
+
+ projwda(xs)
+
+ np.testing.assert_allclose(np.sum(Pwda**2, 0), np.ones(p))
diff --git a/test/test_emd_multi.py b/test/test_emd_multi.py
deleted file mode 100644
index ee0a20e..0000000
--- a/test/test_emd_multi.py
+++ /dev/null
@@ -1,48 +0,0 @@
-#!/usr/bin/env python2
-# -*- coding: utf-8 -*-
-"""
-Created on Fri Mar 10 09:56:06 2017
-
-@author: rflamary
-"""
-
-import numpy as np
-import pylab as pl
-import ot
-
-from ot.datasets import get_1D_gauss as gauss
-reload(ot.lp)
-
-#%% parameters
-
-n=5000 # nb bins
-
-# bin positions
-x=np.arange(n,dtype=np.float64)
-
-# Gaussian distributions
-a=gauss(n,m=20,s=5) # m= mean, s= std
-
-ls= range(20,1000,10)
-nb=len(ls)
-b=np.zeros((n,nb))
-for i in range(nb):
- b[:,i]=gauss(n,m=ls[i],s=10)
-
-# loss matrix
-M=ot.dist(x.reshape((n,1)),x.reshape((n,1)))
-#M/=M.max()
-
-#%%
-
-print('Computing {} EMD '.format(nb))
-
-# emd loss 1 proc
-ot.tic()
-emd_loss4=ot.emd2(a,b,M,1)
-ot.toc('1 proc : {} s')
-
-# emd loss multipro proc
-ot.tic()
-emd_loss4=ot.emd2(a,b,M)
-ot.toc('multi proc : {} s')
diff --git a/test/test_gpu.py b/test/test_gpu.py
new file mode 100644
index 0000000..615c2a7
--- /dev/null
+++ b/test/test_gpu.py
@@ -0,0 +1,79 @@
+"""Tests for module gpu for gpu acceleration """
+
+# Author: Remi Flamary <remi.flamary@unice.fr>
+#
+# License: MIT License
+
+import numpy as np
+import ot
+import time
+import pytest
+
+try: # test if cudamat installed
+ import ot.gpu
+ nogpu = False
+except ImportError:
+ nogpu = True
+
+
+@pytest.mark.skipif(nogpu, reason="No GPU available")
+def test_gpu_sinkhorn():
+
+ rng = np.random.RandomState(0)
+
+ def describe_res(r):
+ print("min:{:.3E}, max::{:.3E}, mean::{:.3E}, std::{:.3E}".format(
+ np.min(r), np.max(r), np.mean(r), np.std(r)))
+
+ for n_samples in [50, 100, 500, 1000]:
+ print(n_samples)
+ a = rng.rand(n_samples // 4, 100)
+ b = rng.rand(n_samples, 100)
+ time1 = time.time()
+ transport = ot.da.OTDA_sinkhorn()
+ transport.fit(a, b)
+ G1 = transport.G
+ time2 = time.time()
+ transport = ot.gpu.da.OTDA_sinkhorn()
+ transport.fit(a, b)
+ G2 = transport.G
+ time3 = time.time()
+ print("Normal sinkhorn, time: {:6.2f} sec ".format(time2 - time1))
+ describe_res(G1)
+ print(" GPU sinkhorn, time: {:6.2f} sec ".format(time3 - time2))
+ describe_res(G2)
+
+ np.testing.assert_allclose(G1, G2, rtol=1e-5, atol=1e-5)
+
+
+@pytest.mark.skipif(nogpu, reason="No GPU available")
+def test_gpu_sinkhorn_lpl1():
+
+ rng = np.random.RandomState(0)
+
+ def describe_res(r):
+ print("min:{:.3E}, max:{:.3E}, mean:{:.3E}, std:{:.3E}"
+ .format(np.min(r), np.max(r), np.mean(r), np.std(r)))
+
+ for n_samples in [50, 100, 500]:
+ print(n_samples)
+ a = rng.rand(n_samples // 4, 100)
+ labels_a = np.random.randint(10, size=(n_samples // 4))
+ b = rng.rand(n_samples, 100)
+ time1 = time.time()
+ transport = ot.da.OTDA_lpl1()
+ transport.fit(a, labels_a, b)
+ G1 = transport.G
+ time2 = time.time()
+ transport = ot.gpu.da.OTDA_lpl1()
+ transport.fit(a, labels_a, b)
+ G2 = transport.G
+ time3 = time.time()
+ print("Normal sinkhorn lpl1, time: {:6.2f} sec ".format(
+ time2 - time1))
+ describe_res(G1)
+ print(" GPU sinkhorn lpl1, time: {:6.2f} sec ".format(
+ time3 - time2))
+ describe_res(G2)
+
+ np.testing.assert_allclose(G1, G2, rtol=1e-5, atol=1e-5)
diff --git a/test/test_gpu_sinkhorn.py b/test/test_gpu_sinkhorn.py
deleted file mode 100644
index bfa2cd2..0000000
--- a/test/test_gpu_sinkhorn.py
+++ /dev/null
@@ -1,26 +0,0 @@
-import ot
-import numpy as np
-import time
-import ot.gpu
-
-def describeRes(r):
- print("min:{:.3E}, max::{:.3E}, mean::{:.3E}, std::{:.3E}".format(np.min(r),np.max(r),np.mean(r),np.std(r)))
-
-
-for n in [5000, 10000, 15000, 20000]:
- print(n)
- a = np.random.rand(n // 4, 100)
- b = np.random.rand(n, 100)
- time1 = time.time()
- transport = ot.da.OTDA_sinkhorn()
- transport.fit(a, b)
- G1 = transport.G
- time2 = time.time()
- transport = ot.gpu.da.OTDA_sinkhorn()
- transport.fit(a, b)
- G2 = transport.G
- time3 = time.time()
- print("Normal sinkhorn, time: {:6.2f} sec ".format(time2 - time1))
- describeRes(G1)
- print(" GPU sinkhorn, time: {:6.2f} sec ".format(time3 - time2))
- describeRes(G2) \ No newline at end of file
diff --git a/test/test_gpu_sinkhorn_lpl1.py b/test/test_gpu_sinkhorn_lpl1.py
deleted file mode 100644
index e6cdd31..0000000
--- a/test/test_gpu_sinkhorn_lpl1.py
+++ /dev/null
@@ -1,28 +0,0 @@
-import ot
-import numpy as np
-import time
-import ot.gpu
-
-
-def describeRes(r):
- print("min:{:.3E}, max:{:.3E}, mean:{:.3E}, std:{:.3E}"
- .format(np.min(r), np.max(r), np.mean(r), np.std(r)))
-
-for n in [5000, 10000, 15000, 20000]:
- print(n)
- a = np.random.rand(n // 4, 100)
- labels_a = np.random.randint(10, size=(n // 4))
- b = np.random.rand(n, 100)
- time1 = time.time()
- transport = ot.da.OTDA_lpl1()
- transport.fit(a, labels_a, b)
- G1 = transport.G
- time2 = time.time()
- transport = ot.gpu.da.OTDA_lpl1()
- transport.fit(a, labels_a, b)
- G2 = transport.G
- time3 = time.time()
- print("Normal sinkhorn lpl1, time: {:6.2f} sec ".format(time2 - time1))
- describeRes(G1)
- print(" GPU sinkhorn lpl1, time: {:6.2f} sec ".format(time3 - time2))
- describeRes(G2)
diff --git a/test/test_load_module.py b/test/test_load_module.py
deleted file mode 100644
index a04c5df..0000000
--- a/test/test_load_module.py
+++ /dev/null
@@ -1,10 +0,0 @@
-
-
-import ot
-import doctest
-
-# test lp solver
-doctest.testmod(ot.lp,verbose=True)
-
-# test bregman solver
-doctest.testmod(ot.bregman,verbose=True)
diff --git a/test/test_optim.py b/test/test_optim.py
new file mode 100644
index 0000000..69496a5
--- /dev/null
+++ b/test/test_optim.py
@@ -0,0 +1,67 @@
+"""Tests for module optim fro OT optimization """
+
+# Author: Remi Flamary <remi.flamary@unice.fr>
+#
+# License: MIT License
+
+import numpy as np
+import ot
+
+
+def test_conditional_gradient():
+
+ n_bins = 100 # nb bins
+ np.random.seed(0)
+ # bin positions
+ x = np.arange(n_bins, dtype=np.float64)
+
+ # Gaussian distributions
+ a = ot.datasets.get_1D_gauss(n_bins, m=20, s=5) # m= mean, s= std
+ b = ot.datasets.get_1D_gauss(n_bins, m=60, s=10)
+
+ # loss matrix
+ M = ot.dist(x.reshape((n_bins, 1)), x.reshape((n_bins, 1)))
+ M /= M.max()
+
+ def f(G):
+ return 0.5 * np.sum(G**2)
+
+ def df(G):
+ return G
+
+ reg = 1e-1
+
+ G, log = ot.optim.cg(a, b, M, reg, f, df, verbose=True, log=True)
+
+ np.testing.assert_allclose(a, G.sum(1))
+ np.testing.assert_allclose(b, G.sum(0))
+
+
+def test_generalized_conditional_gradient():
+
+ n_bins = 100 # nb bins
+ np.random.seed(0)
+ # bin positions
+ x = np.arange(n_bins, dtype=np.float64)
+
+ # Gaussian distributions
+ a = ot.datasets.get_1D_gauss(n_bins, m=20, s=5) # m= mean, s= std
+ b = ot.datasets.get_1D_gauss(n_bins, m=60, s=10)
+
+ # loss matrix
+ M = ot.dist(x.reshape((n_bins, 1)), x.reshape((n_bins, 1)))
+ M /= M.max()
+
+ def f(G):
+ return 0.5 * np.sum(G**2)
+
+ def df(G):
+ return G
+
+ reg1 = 1e-3
+ reg2 = 1e-1
+
+ G, log = ot.optim.gcg(a, b, M, reg1, reg2, f, df, verbose=True, log=True)
+
+ np.testing.assert_allclose(a, G.sum(1), atol=1e-05)
+ np.testing.assert_allclose(b, G.sum(0), atol=1e-05)
diff --git a/test/test_ot.py b/test/test_ot.py
new file mode 100644
index 0000000..acd8718
--- /dev/null
+++ b/test/test_ot.py
@@ -0,0 +1,102 @@
+"""Tests for main module ot """
+
+# Author: Remi Flamary <remi.flamary@unice.fr>
+#
+# License: MIT License
+
+import numpy as np
+import ot
+
+
+def test_doctest():
+
+ import doctest
+
+ # test lp solver
+ doctest.testmod(ot.lp, verbose=True)
+
+ # test bregman solver
+ doctest.testmod(ot.bregman, verbose=True)
+
+
+def test_emd_emd2():
+ # test emd and emd2 for simple identity
+ n = 100
+ rng = np.random.RandomState(0)
+
+ x = rng.randn(n, 2)
+ u = ot.utils.unif(n)
+
+ M = ot.dist(x, x)
+
+ G = ot.emd(u, u, M)
+
+ # check G is identity
+ np.testing.assert_allclose(G, np.eye(n) / n)
+ # check constratints
+ np.testing.assert_allclose(u, G.sum(1)) # cf convergence sinkhorn
+ np.testing.assert_allclose(u, G.sum(0)) # cf convergence sinkhorn
+
+ w = ot.emd2(u, u, M)
+ # check loss=0
+ np.testing.assert_allclose(w, 0)
+
+
+def test_emd_empty():
+ # test emd and emd2 for simple identity
+ n = 100
+ rng = np.random.RandomState(0)
+
+ x = rng.randn(n, 2)
+ u = ot.utils.unif(n)
+
+ M = ot.dist(x, x)
+
+ G = ot.emd([], [], M)
+
+ # check G is identity
+ np.testing.assert_allclose(G, np.eye(n) / n)
+ # check constratints
+ np.testing.assert_allclose(u, G.sum(1)) # cf convergence sinkhorn
+ np.testing.assert_allclose(u, G.sum(0)) # cf convergence sinkhorn
+
+ w = ot.emd2([], [], M)
+ # check loss=0
+ np.testing.assert_allclose(w, 0)
+
+
+def test_emd2_multi():
+
+ from ot.datasets import get_1D_gauss as gauss
+
+ n = 1000 # nb bins
+
+ # bin positions
+ x = np.arange(n, dtype=np.float64)
+
+ # Gaussian distributions
+ a = gauss(n, m=20, s=5) # m= mean, s= std
+
+ ls = np.arange(20, 1000, 20)
+ nb = len(ls)
+ b = np.zeros((n, nb))
+ for i in range(nb):
+ b[:, i] = gauss(n, m=ls[i], s=10)
+
+ # loss matrix
+ M = ot.dist(x.reshape((n, 1)), x.reshape((n, 1)))
+ # M/=M.max()
+
+ print('Computing {} EMD '.format(nb))
+
+ # emd loss 1 proc
+ ot.tic()
+ emd1 = ot.emd2(a, b, M, 1)
+ ot.toc('1 proc : {} s')
+
+ # emd loss multipro proc
+ ot.tic()
+ emdn = ot.emd2(a, b, M)
+ ot.toc('multi proc : {} s')
+
+ np.testing.assert_allclose(emd1, emdn)
diff --git a/test/test_plot.py b/test/test_plot.py
new file mode 100644
index 0000000..f7debee
--- /dev/null
+++ b/test/test_plot.py
@@ -0,0 +1,49 @@
+"""Tests for module plot for visualization """
+
+# Author: Remi Flamary <remi.flamary@unice.fr>
+#
+# License: MIT License
+
+import numpy as np
+import matplotlib
+matplotlib.use('Agg')
+
+
+def test_plot1D_mat():
+
+ import ot
+
+ n_bins = 100 # nb bins
+
+ # bin positions
+ x = np.arange(n_bins, dtype=np.float64)
+
+ # Gaussian distributions
+ a = ot.datasets.get_1D_gauss(n_bins, m=20, s=5) # m= mean, s= std
+ b = ot.datasets.get_1D_gauss(n_bins, m=60, s=10)
+
+ # loss matrix
+ M = ot.dist(x.reshape((n_bins, 1)), x.reshape((n_bins, 1)))
+ M /= M.max()
+
+ ot.plot.plot1D_mat(a, b, M, 'Cost matrix M')
+
+
+def test_plot2D_samples_mat():
+
+ import ot
+
+ n_bins = 50 # nb samples
+
+ mu_s = np.array([0, 0])
+ cov_s = np.array([[1, 0], [0, 1]])
+
+ mu_t = np.array([4, 4])
+ cov_t = np.array([[1, -.8], [-.8, 1]])
+
+ xs = ot.datasets.get_2D_samples_gauss(n_bins, mu_s, cov_s)
+ xt = ot.datasets.get_2D_samples_gauss(n_bins, mu_t, cov_t)
+
+ G = 1.0 * (np.random.rand(n_bins, n_bins) < 0.01)
+
+ ot.plot.plot2D_samples_mat(xs, xt, G, thr=1e-5)
diff --git a/test/test_utils.py b/test/test_utils.py
new file mode 100644
index 0000000..1bd37cd
--- /dev/null
+++ b/test/test_utils.py
@@ -0,0 +1,125 @@
+"""Tests for module utils for timing and parallel computation """
+
+# Author: Remi Flamary <remi.flamary@unice.fr>
+#
+# License: MIT License
+
+
+import ot
+import numpy as np
+
+
+def test_parmap():
+
+ n = 100
+
+ def f(i):
+ return 1.0 * i * i
+
+ a = np.arange(n)
+
+ l1 = list(map(f, a))
+
+ l2 = list(ot.utils.parmap(f, a))
+
+ np.testing.assert_allclose(l1, l2)
+
+
+def test_tic_toc():
+
+ import time
+
+ ot.tic()
+ time.sleep(0.5)
+ t = ot.toc()
+ t2 = ot.toq()
+
+ # test timing
+ np.testing.assert_allclose(0.5, t, rtol=1e-2, atol=1e-2)
+
+ # test toc vs toq
+ np.testing.assert_allclose(t, t2, rtol=1e-2, atol=1e-2)
+
+
+def test_kernel():
+
+ n = 100
+
+ x = np.random.randn(n, 2)
+
+ K = ot.utils.kernel(x, x)
+
+ # gaussian kernel has ones on the diagonal
+ np.testing.assert_allclose(np.diag(K), np.ones(n))
+
+
+def test_unif():
+
+ n = 100
+
+ u = ot.unif(n)
+
+ np.testing.assert_allclose(1, np.sum(u))
+
+
+def test_dist():
+
+ n = 100
+
+ x = np.random.randn(n, 2)
+
+ D = np.zeros((n, n))
+ for i in range(n):
+ for j in range(n):
+ D[i, j] = np.sum(np.square(x[i, :] - x[j, :]))
+
+ D2 = ot.dist(x, x)
+ D3 = ot.dist(x)
+
+ # dist shoul return squared euclidean
+ np.testing.assert_allclose(D, D2)
+ np.testing.assert_allclose(D, D3)
+
+
+def test_dist0():
+
+ n = 100
+ M = ot.utils.dist0(n, method='lin_square')
+
+ # dist0 default to linear sampling with quadratic loss
+ np.testing.assert_allclose(M[0, -1], (n - 1) * (n - 1))
+
+
+def test_dots():
+
+ n1, n2, n3, n4 = 100, 50, 200, 100
+
+ A = np.random.randn(n1, n2)
+ B = np.random.randn(n2, n3)
+ C = np.random.randn(n3, n4)
+
+ X1 = ot.utils.dots(A, B, C)
+
+ X2 = A.dot(B.dot(C))
+
+ np.testing.assert_allclose(X1, X2)
+
+
+def test_clean_zeros():
+
+ n = 100
+ nz = 50
+ nz2 = 20
+ u1 = ot.unif(n)
+ u1[:nz] = 0
+ u1 = u1 / u1.sum()
+ u2 = ot.unif(n)
+ u2[:nz2] = 0
+ u2 = u2 / u2.sum()
+
+ M = ot.utils.dist0(n)
+
+ a, b, M2 = ot.utils.clean_zeros(u1, u2, M)
+
+ assert len(a) == n - nz
+ assert len(b) == n - nz2