Skip to content

pm.Uniform bounds not respected when using a transform #4721

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
impact27 opened this issue May 26, 2021 · 3 comments
Closed

pm.Uniform bounds not respected when using a transform #4721

impact27 opened this issue May 26, 2021 · 3 comments

Comments

@impact27
Copy link

impact27 commented May 26, 2021

If you have questions about a specific use case, or you are not sure whether this is a bug or not, please post it to our discourse channel: https://discourse.pymc.io

Description of your problem

pm.Uniform is not bounded when using another transform.

This code gives negatives DRi to my Operator.

import pymc3 as pm
import theano.tensor as tt
import pymc3.distributions.transforms as tr
from theano.graph.op import Op
import theano
import numpy as np

tr_order = tr.Ordered()
tr_bounds = tr.interval(0, 0.5)

class MyOp(Op):
    itypes = [tt.dvector]
    otypes = [tt.dscalar]

    def perform(self, node, inputs, outputs):
        di, = inputs
        assert np.all(di > 0)
        outputs[0][0] = np.array(np.sum(di))

    def grad(self, inputs, g):
        assert len(g) == 1
        di, = inputs
        return [
            0 * di + g[0]
            ]
theano.gradient.verify_grad(
    MyOp(), (
        np.array([0.1, 0.4]),
    ),
    rng=np.random)
#%%
myop = MyOp()
with pm.Model() as model:
    DRi = pm.Uniform("DRi", lower=0, upper=0.5, shape=2,
                     # transform=tr.Chain([tr_bounds, tr_order]),
                     transform=tr_order,
                      testval=[0.1, 0.4]
                     )
    pm.Normal("A",
              mu=myop(DRi),
              sigma=1,
              observed=np.random.uniform(0, 0.5, size=10))
    trace = pm.sample(return_inferencedata=True, cores=1)

If I explicitely add the bounds transform transform=tr.Chain([tr_bounds, tr_order]), this works as expected.

Please provide the full traceback.

Backtrace when the node is created(use Theano flag traceback__limit=N to make it longer):
  File "C:\ProgramData\Anaconda3\lib\site-packages\IPython\core\async_helpers.py", line 68, in _pseudo_sync_runner
    coro.send(None)
  File "C:\ProgramData\Anaconda3\lib\site-packages\IPython\core\interactiveshell.py", line 3146, in run_cell_async
    has_raised = await self.run_ast_nodes(code_ast.body, cell_name,
  File "C:\ProgramData\Anaconda3\lib\site-packages\IPython\core\interactiveshell.py", line 3338, in run_ast_nodes
    if (await self.run_code(code, result,  async_=asy)):
  File "C:\ProgramData\Anaconda3\lib\site-packages\IPython\core\interactiveshell.py", line 3418, in run_code
    exec(code_obj, self.user_global_ns, self.user_ns)
  File "<ipython-input-10-1bcd24a039ad>", line 1, in <module>
    runcell(1, 'C:/Users/quentin.peter/Desktop/aSyn_Kd_sizing/untitled0.py')
  File "c:\users\quentin.peter\spyder-kernels\spyder_kernels\customize\spydercustomize.py", line 730, in runcell
    exec_code(cell_code, filename, ns_globals, ns_locals,
  File "c:\users\quentin.peter\spyder-kernels\spyder_kernels\customize\spydercustomize.py", line 473, in exec_code
    exec(compiled, ns_globals, ns_locals)
  File "C:\Users\quentin.peter\Desktop\aSyn_Kd_sizing\untitled0.py", line 47, in <module>
    mu=myop(DRi),

HINT: Use the Theano flag 'exception_verbosity=high' for a debugprint and storage map footprint of this apply node.

Please provide any additional information below.
Should there be an error when the bounds are not enforced?

Versions and main components

  • PyMC3 Version: 3.11.2
  • Aesara Version: NA
  • Python Version: 3.8.5
  • Operating system: windows
  • How did you install PyMC3: (conda/pip) pip
@ricardoV94
Copy link
Member

That is the expected behavior. You are overwriting the default interval transform when setting tr_order. The chain is exactly what you should be doing in this case.

@impact27
Copy link
Author

But then what are the lower=0, upper=0.5 arguments doing? Can I just omit them?

@ricardoV94
Copy link
Member

ricardoV94 commented May 27, 2021

The lower/upper determine the normalization constant and logp bounds. A uniform(0, 1) (default parameters) and uniform(0, 0.5), both with an interval transform(0, 0.5) will have a different normalization constant (and only the later "integrates to 1"). This is usually not important for mcmc sampling as a proportional posterior is sufficient. An interval transform larger than the lower/upper parameters (e.g interval (0, 2)) on the other hand would create issues because the samplers can now propose values that have 0 probability in the uniform).

By the way this kind of discussion is better placed in our forum https://discourse.pymc.io/ as we try to keep github issue for development issues. Feel free to open an thread there and tag me if you have further questions.

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

No branches or pull requests

2 participants