Skip to content

Cannot compute test value because of floatX() in Uniform #2589

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

Closed
michaelosthege opened this issue Sep 22, 2017 · 5 comments
Closed

Cannot compute test value because of floatX() in Uniform #2589

michaelosthege opened this issue Sep 22, 2017 · 5 comments
Labels

Comments

@michaelosthege
Copy link
Member

When Uniform RVs are instantiated through the pmodel.Var("name", Uniform.dist(...))-API, they can break if the lower/upper bounds are some magic numbers (such as 0).

The following code demonstrates that this is because of the floatx(.) conversion which is only done in the Uniform.__init__:

import unittest
import theano
import theano.tensor as tt
import pymc3
import pymc3.distributions.continuous


class Uniform(pymc3.Continuous):
    R"""..."""

    def __init__(self, lower=0, upper=1, transform='interval',
                 *args, **kwargs):
        if transform == 'interval':
            transform = pymc3.distributions.continuous.transforms.interval(lower, upper)
        super(Uniform, self).__init__(transform=transform, *args, **kwargs)

        #self.lower = lower = pymc3.distributions.continuous.floatX(tt.as_tensor_variable(lower))
        #self.upper = upper = pymc3.distributions.continuous.floatX(tt.as_tensor_variable(upper))
        self.lower = lower = tt.as_tensor_variable(lower)
        self.upper = upper = tt.as_tensor_variable(upper)
        self.mean = (upper + lower) / 2.
        self.median = self.mean

    def random(self, point=None, size=None, repeat=None):
        return pymc3.distributions.continuous.Uniform.random(self, point, size, repeat)

    def logp(self, value):
        return pymc3.distributions.continuous.Uniform.logp(self, value)

    def _repr_latex_(self, name=None, dist=None):
        return pymc3.distributions.continuous.Uniform._repr_latex_(self, name, dist)

Uniform_type = Uniform         # this is all fine
#Uniform_type = pymc3.Uniform    # this breaks

class TestDistAPI(unittest.TestCase):

    def test_1(self):
        print("test 1")
        u = Uniform_type.dist(lower=0.0, upper=1.4, testval=0.5)
        with pymc3.Model() as pmodel:
            pmodel.Var("u", u)
        return

    def test_2(self):
        print("test 2")
        u = Uniform_type.dist(lower=0.01, upper=1.4, testval=0.5)
        with pymc3.Model() as pmodel:
            pmodel.Var("u", u)
        return

    def test_3(self):
        print("test 3")
        with pymc3.Model() as pmodel:
            Uniform_type("u", lower=0, upper=1.4, testval=0.5)
        return


if __name__ == "__main__":
    print(theano.config.compute_test_value)
    ## >>> 'off'
    unittest.main(exit=False)

The execution order of the three test methods is relevant! This is probably because if test_3 runs first, theano caches the 0-constant and the other tests work fine, but if test_1 runs first, it breaks. test_2 shows that some constants don't cause trouble.

The failures can NOT be prevented via theano.config.compute_test_value (it already is off in my case).

Why is there the floatX(.) conversion in continuous.py#L158 ?
Can we remove it? (It's also appears in L109 by the way.)

@michaelosthege michaelosthege changed the title Cannot comput test value because of floatX() in Uniform Cannot compute test value because of floatX() in Uniform Sep 22, 2017
@junpenglao
Copy link
Member

Thanks for the detail investigation @michaelosthege.
What os you are using? I am on Linux and cannot reproduce the error (all test run fine)

@junpenglao
Copy link
Member

The failures can NOT be prevented via theano.config.compute_test_value (it already is off in my case).

Actually for me it failed if theano.config.compute_test_value='off', but works fine if theano.config.compute_test_value='raise'

@michaelosthege
Copy link
Member Author

I am testing on three setups and have not made observations that would suggest it being OS-specific:

  • Python 3.5 on Windows 10 x64
  • Python 3.5 on Ubuntu on Windows 10 (Windows Subsystem for Linux)
  • Python 3.5 on Ubuntu 17.04 (freshly installed a few hours ago)

This issue may be related: #562
In the example I posted there, I tried to set theano_config of the pymc3.Model() because that one actually overrides whatever theano.config you set elsewhere.

I just ran this on the recently installed Ubuntu 17.04 and it promptly failed:

import pymc3

u = pymc3.DiscreteUniform.dist(0, 4, testval=3)
g = pymc3.Gamma.dist(alpha=12, beta=2, testval=8.2)
with pymc3.Model() as pmodel:
    pmodel.Var("u", u)
    pmodel.Var("g", g)

@junpenglao
Copy link
Member

junpenglao commented Sep 22, 2017

It run fine with me...

pmodel.test_point
Out[14]: {'g_log__': array(2.1041341542702074), 'u': array(3)}

I am on pymc3 master, and

CPython 3.5.2
IPython 6.1.0

numpy 1.13.1
pandas 0.20.3
theano 0.10.0dev1.dev-d51233517debf3a1231a33058d65e8f969db923d

compiler   : GCC 5.4.0 20160609
system     : Linux
release    : 4.4.0-96-generic
machine    : x86_64
processor  : x86_64
CPU cores  : 8
interpreter: 64bit

@michaelosthege
Copy link
Member Author

michaelosthege commented Sep 22, 2017

On an empty environment, I did pip install pymc3 and then pip install git+https://github.com/pymc-devs/pymc3 -U --no-deps to switch to master.

(venv35) xxxxxx@xxxxxx:~$ pip list
certifi (2016.2.28)
cycler (0.10.0)
enum34 (1.1.6)
h5py (2.7.1)
joblib (0.11)
matplotlib (2.0.2)
numpy (1.13.1)
pandas (0.20.3)
patsy (0.4.1)
pip (9.0.1)
pymc3 (3.1)
pyparsing (2.2.0)
python-dateutil (2.6.1)
pytz (2017.2)
scipy (0.19.1)
setuptools (36.4.0)
six (1.11.0)
Theano (0.9.0)
tqdm (4.17.1)
wheel (0.29.0)
(venv35) xxxxxx@xxxxxx:~$ python
Python 3.5.4 |Continuum Analytics, Inc.| (default, Aug 14 2017, 13:26:58)
[GCC 4.4.7 20120313 (Red Hat 4.4.7-1)] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>>

Nevertheless, if I run the snipped from my previous post as test.py:

(venv35) xxxxxx@xxxxxx:~$ python test.py
Traceback (most recent call last):
  File "/home/xxxxxx/miniconda3/envs/venv35/lib/python3.5/site-packages/theano/gof/op.py", line 625, in __call__
    storage_map[ins] = [self._get_test_value(ins)]
  File "/home/xxxxxx/miniconda3/envs/venv35/lib/python3.5/site-packages/theano/gof/op.py", line 581, in _get_test_value
    raise AttributeError('%s has no test value %s' % (v, detailed_err_msg))
AttributeError: Elemwise{Cast{int32}}.0 has no test value
Backtrace when that variable is created:

  File "test.py", line 3, in <module>
    u = pymc3.DiscreteUniform.dist(0, 4, testval=3)
  File "/home/xxxxxx/miniconda3/envs/venv35/lib/python3.5/site-packages/pymc3/distributions/distribution.py", line 47, in dist
    dist.__init__(*args, **kwargs)
  File "/home/xxxxxx/miniconda3/envs/venv35/lib/python3.5/site-packages/pymc3/distributions/discrete.py", line 443, in __init__
    self.upper = tt.floor(upper).astype('int32')


During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "test.py", line 6, in <module>
    pmodel.Var("u", u)
  File "/home/xxxxxx/miniconda3/envs/venv35/lib/python3.5/site-packages/pymc3/model.py", line 752, in Var
    total_size=total_size, model=self)
  File "/home/xxxxxx/miniconda3/envs/venv35/lib/python3.5/site-packages/pymc3/model.py", line 1123, in __init__
    self.logp_elemwiset = distribution.logp(self)
  File "/home/xxxxxx/miniconda3/envs/venv35/lib/python3.5/site-packages/pymc3/distributions/discrete.py", line 464, in logp
    return bound(-tt.log(upper - lower + 1),
  File "/home/xxxxxx/miniconda3/envs/venv35/lib/python3.5/site-packages/theano/tensor/var.py", line 147, in __sub__
    return theano.tensor.basic.sub(self, other)
  File "/home/xxxxxx/miniconda3/envs/venv35/lib/python3.5/site-packages/theano/gof/op.py", line 639, in __call__
    (i, ins, node, detailed_err_msg))
ValueError: Cannot compute test value: input 0 (Elemwise{Cast{int32}}.0) of Op Elemwise{sub,no_inplace}(Elemwise{Cast{int32}}.0, Elemwise{Cast{int32}}.0) missing default value.
Backtrace when that variable is created:

  File "test.py", line 3, in <module>
    u = pymc3.DiscreteUniform.dist(0, 4, testval=3)
  File "/home/xxxxxx/miniconda3/envs/venv35/lib/python3.5/site-packages/pymc3/distributions/distribution.py", line 47, in dist
    dist.__init__(*args, **kwargs)
  File "/home/xxxxxx/miniconda3/envs/venv35/lib/python3.5/site-packages/pymc3/distributions/discrete.py", line 443, in __init__
    self.upper = tt.floor(upper).astype('int32')

But it is definitely important that you run it on a fresh session, because if theano already created a similar constant tensor before, it is cached. (This may also explain why unittests rarely catch these issues.)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

3 participants