Skip to content

[MRG] Have Travis actually execute doctests #90

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 13 commits into from
Jul 2, 2019

Conversation

rtavenar
Copy link
Contributor

@rtavenar rtavenar commented Jul 1, 2019

Hi there,

As it is coded at the moment, doctests are not checked by Travis, since the call in test_ot does not raise any error. This PR is an attempt to fix that.

@rtavenar
Copy link
Contributor Author

rtavenar commented Jul 1, 2019

At the moment, I have:

  • moved GPU doctests to test_gpu (+added an ignore flag on the ot/gpu folder) since otherwise doctest would fail on importing the module if GPU is not supported
  • edited travis.yml file so that doctests are executed
  • fixed obvious bugs in doctests

I have not fixed bugs related to numpy array formatting, let me know which version of formatting I should use or if there is a clever way to deal with those in doctests.

Also, there are the following tests that do not pass and that would need checking:

284         log dictionary return only if log==True in parameters
285 
286     Examples
287     --------
288 
289     >>> import ot
290     >>> a=[.5, .15]
291     >>> b=[.5, .5]
292     >>> M=[[0., 1.],[1., 0.]]
293     >>> ot.sinkhorn_knopp_unbalanced(a, b, M, 1., 1.)
UNEXPECTED EXCEPTION: AttributeError("module 'ot' has no attribute 'sinkhorn_knopp_unbalanced'")
Traceback (most recent call last):

  File "/usr/local/Cellar/python/3.7.3/Frameworks/Python.framework/Versions/3.7/lib/python3.7/doctest.py", line 1329, in __run
    compileflags, 1), test.globs)

  File "<doctest ot.unbalanced.sinkhorn_knopp_unbalanced[4]>", line 1, in <module>

AttributeError: module 'ot' has no attribute 'sinkhorn_knopp_unbalanced'

Should I add this as a member in __init__.py ?

228     >>> numItermax = 300000
229     >>> a = ot.utils.unif(n_source)
230     >>> b = ot.utils.unif(n_target)
231     >>> rng = np.random.RandomState(0)
232     >>> X_source = rng.randn(n_source, 2)
233     >>> Y_target = rng.randn(n_target, 2)
234     >>> M = ot.dist(X_source, Y_target)
235     >>> method = "ASGD"
236     >>> asgd_pi = ot.stochastic.solve_semi_dual_entropic(a, b, M, reg, method, numItermax)
237     >>> print(asgd_pi)
Expected nothing
Got:
    [[2.55489470e-02 9.96268666e-02 1.76769854e-02 4.34379685e-06]
     [1.21589227e-01 1.25320316e-02 1.30343724e-03 7.43244699e-03]
     [3.55891217e-03 7.61047795e-02 6.31933164e-02 1.34770804e-07]
     [2.61300196e-02 3.34012346e-02 8.29155469e-02 4.10341751e-04]
     [9.79012843e-03 7.47427885e-04 1.07693028e-02 1.21550284e-01]
     [2.15528997e-02 8.98205807e-04 1.86239266e-03 1.18543645e-01]
     [4.15119582e-02 2.65801363e-02 7.23542541e-02 2.41079424e-03]]

/Users/tavenard_r/Documents/costel/src/POT/ot/stochastic.py:237: DocTestFailure
______________________________________________________________________________________________________________ [doctest] ot.stochastic.batch_grad_dual ______________________________________________________________________________________________________________
510     >>> batch_size = 3
511     >>> log = True
512     >>> a = ot.utils.unif(n_source)
513     >>> b = ot.utils.unif(n_target)
514     >>> rng = np.random.RandomState(0)
515     >>> X_source = rng.randn(n_source, 2)
516     >>> Y_target = rng.randn(n_target, 2)
517     >>> M = ot.dist(X_source, Y_target)
518     >>> sgd_dual_pi, log = ot.stochastic.solve_dual_entropic(a, b, M, reg, batch_size, numItermax, lr, log)
519     >>> print(log['alpha'], log['beta'])
Expected nothing
Got:
    [0.65417474 1.28464039 0.75387716 0.15738988 0.55418466 1.06094533
     0.19524193] [0.50659034 0.58415035 1.29294164 2.27677175]

/Users/tavenard_r/Documents/costel/src/POT/ot/stochastic.py:519: DocTestFailure
___________________________________________________________________________________________________________ [doctest] ot.stochastic.c_transform_entropic ____________________________________________________________________________________________________________
307     >>> numItermax = 300000
308     >>> a = ot.utils.unif(n_source)
309     >>> b = ot.utils.unif(n_target)
310     >>> rng = np.random.RandomState(0)
311     >>> X_source = rng.randn(n_source, 2)
312     >>> Y_target = rng.randn(n_target, 2)
313     >>> M = ot.dist(X_source, Y_target)
314     >>> method = "ASGD"
315     >>> asgd_pi = ot.stochastic.solve_semi_dual_entropic(a, b, M, reg, method, numItermax)
316     >>> print(asgd_pi)
Expected nothing
Got:
    [[2.54106554e-02 9.97268805e-02 1.77153111e-02 4.29584338e-06]
     [1.21547758e-01 1.26085817e-02 1.31292434e-03 7.38787857e-03]
     [3.53484453e-03 7.60777888e-02 6.32443764e-02 1.33102110e-07]
     [2.59763391e-02 3.34190138e-02 8.30561694e-02 4.05620586e-04]
     [9.83147177e-03 7.55426727e-04 1.08972134e-02 1.21373031e-01]
     [2.16515127e-02 9.08136849e-04 1.88517429e-03 1.18412319e-01]
     [4.13068530e-02 2.66194449e-02 7.25455335e-02 2.38531153e-03]]

/Users/tavenard_r/Documents/costel/src/POT/ot/stochastic.py:316: DocTestFailure
_________________________________________________________________________________________________________ [doctest] ot.stochastic.coordinate_grad_semi_dual _________________________________________________________________________________________________________
058     >>> numItermax = 300000
059     >>> a = ot.utils.unif(n_source)
060     >>> b = ot.utils.unif(n_target)
061     >>> rng = np.random.RandomState(0)
062     >>> X_source = rng.randn(n_source, 2)
063     >>> Y_target = rng.randn(n_target, 2)
064     >>> M = ot.dist(X_source, Y_target)
065     >>> method = "ASGD"
066     >>> asgd_pi = ot.stochastic.solve_semi_dual_entropic(a, b, M, reg, method, numItermax)
067     >>> print(asgd_pi)
Expected nothing
Got:
    [[2.55691325e-02 9.95968638e-02 1.76867732e-02 4.37336996e-06]
     [1.21563085e-01 1.25156756e-02 1.30284921e-03 7.47553294e-03]
     [3.56135291e-03 7.60739345e-02 6.32217198e-02 1.35674205e-07]
     [2.61398154e-02 3.33773232e-02 8.29270403e-02 4.12964016e-04]
     [9.74052071e-03 7.42829745e-04 1.07122029e-02 1.21661590e-01]
     [2.14460994e-02 8.92780448e-04 1.85272634e-03 1.18665537e-01]
     [4.15211350e-02 2.65570239e-02 7.23531567e-02 2.42582723e-03]]

/Users/tavenard_r/Documents/costel/src/POT/ot/stochastic.py:67: DocTestFailure
__________________________________________________________________________________________________________ [doctest] ot.stochastic.sag_entropic_transport ___________________________________________________________________________________________________________
139     >>> numItermax = 300000
140     >>> a = ot.utils.unif(n_source)
141     >>> b = ot.utils.unif(n_target)
142     >>> rng = np.random.RandomState(0)
143     >>> X_source = rng.randn(n_source, 2)
144     >>> Y_target = rng.randn(n_target, 2)
145     >>> M = ot.dist(X_source, Y_target)
146     >>> method = "ASGD"
147     >>> asgd_pi = ot.stochastic.solve_semi_dual_entropic(a, b, M, reg, method, numItermax)
148     >>> print(asgd_pi)
Expected nothing
Got:
    [[2.53339520e-02 9.98586476e-02 1.76602698e-02 4.27351445e-06]
     [1.21514908e-01 1.26600440e-02 1.31245306e-03 7.36973751e-03]
     [3.52680737e-03 7.62352226e-02 6.30949803e-02 1.32509197e-07]
     [2.59514121e-02 3.35322774e-02 8.29691078e-02 4.04345580e-04]
     [9.84960357e-03 7.60114347e-04 1.09163422e-02 1.21331083e-01]
     [2.16902366e-02 9.13721224e-04 1.88837841e-03 1.18364807e-01]
     [4.12767387e-02 2.67158275e-02 7.24862142e-02 2.37836243e-03]]

/Users/tavenard_r/Documents/costel/src/POT/ot/stochastic.py:148: DocTestFailure
________________________________________________________________________________________________________ [doctest] ot.stochastic.sgd_entropic_regularization ________________________________________________________________________________________________________
599     >>> batch_size = 3
600     >>> log = True
601     >>> a = ot.utils.unif(n_source)
602     >>> b = ot.utils.unif(n_target)
603     >>> rng = np.random.RandomState(0)
604     >>> X_source = rng.randn(n_source, 2)
605     >>> Y_target = rng.randn(n_target, 2)
606     >>> M = ot.dist(X_source, Y_target)
607     >>> sgd_dual_pi, log = ot.stochastic.solve_dual_entropic(a, b, M, reg, batch_size, numItermax, lr, log)
608     >>> print(log['alpha'], log['beta'])
Expected nothing
Got:
    [0.64640722 1.26827311 0.7740418  0.15379161 0.55547374 1.04208024
     0.19900565] [0.51303392 0.58323389 1.28687355 2.25593202]

/Users/tavenard_r/Documents/costel/src/POT/ot/stochastic.py:608: DocTestFailure
____________________________________________________________________________________________________________ [doctest] ot.stochastic.solve_dual_entropic ____________________________________________________________________________________________________________
695     >>> batch_size = 3
696     >>> log = True
697     >>> a = ot.utils.unif(n_source)
698     >>> b = ot.utils.unif(n_target)
699     >>> rng = np.random.RandomState(0)
700     >>> X_source = rng.randn(n_source, 2)
701     >>> Y_target = rng.randn(n_target, 2)
702     >>> M = ot.dist(X_source, Y_target)
703     >>> sgd_dual_pi, log = ot.stochastic.solve_dual_entropic(a, b, M, reg, batch_size, numItermax, lr, log)
704     >>> print(log['alpha'], log['beta'])
Expected nothing
Got:
    [0.6459203  1.25256745 0.77168788 0.16400835 0.54905627 1.0560163
     0.20497883] [0.50990995 0.5803749  1.2790953  2.27485523]

/Users/tavenard_r/Documents/costel/src/POT/ot/stochastic.py:704: DocTestFailure
_________________________________________________________________________________________________________ [doctest] ot.stochastic.solve_semi_dual_entropic __________________________________________________________________________________________________________
401     >>> numItermax = 300000
402     >>> a = ot.utils.unif(n_source)
403     >>> b = ot.utils.unif(n_target)
404     >>> rng = np.random.RandomState(0)
405     >>> X_source = rng.randn(n_source, 2)
406     >>> Y_target = rng.randn(n_target, 2)
407     >>> M = ot.dist(X_source, Y_target)
408     >>> method = "ASGD"
409     >>> asgd_pi = ot.stochastic.solve_semi_dual_entropic(a, b, M, reg, method, numItermax)
410     >>> print(asgd_pi)
Expected nothing
Got:
    [[2.56160093e-02 9.95898692e-02 1.76468652e-02 4.39912542e-06]
     [1.21562094e-01 1.24917930e-02 1.29752011e-03 7.50573569e-03]
     [3.57141868e-03 7.61439936e-02 6.31415940e-02 1.36608488e-07]
     [2.62132630e-02 3.34075088e-02 8.28205702e-02 4.15800902e-04]
     [9.71011104e-03 7.39103615e-04 1.06351665e-02 1.21772762e-01]
     [2.13756023e-02 8.88154937e-04 1.83909771e-03 1.18754288e-01]
     [4.16190236e-02 2.65690541e-02 7.22276750e-02 2.44139012e-03]]

Could someone check if those values are reasonable?

1552 
1553     Examples
1554     --------
1555 
1556     >>> n_s = 2
1557     >>> n_t = 4
1558     >>> reg = 0.1
1559     >>> X_s = np.reshape(np.arange(n_s), (n_s, 1))
1560     >>> X_t = np.reshape(np.arange(0, n_t), (n_t, 1))
1561     >>> empirical_sinkhorn_divergence(X_s, X_t, reg)
Expected:
    array([2.99977435])
Got:
    array([1.49988718])

This test definitely fails: is it the test that is wrong or the value returned by POT?

@rtavenar
Copy link
Contributor Author

rtavenar commented Jul 2, 2019

OK, things should be (close to) OK now, with tests executed and passing.

By the way, there was a bug in unbalanced.py (Python 2) due to division by an integer. This is now fixed. Let me know what I can do to improve.

@rflamary
Copy link
Collaborator

rflamary commented Jul 2, 2019

This is awesome, thank you @rtavenar

I see no problem in the code and will do the merge.

@rflamary rflamary changed the title [WIP] Have Travis actually execute doctests [MRG] Have Travis actually execute doctests Jul 2, 2019
@rflamary rflamary merged commit 8b3927b into PythonOT:master Jul 2, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants