Hello,
So imagine I am trying to use a Uniform distribution (sigma
) in my guide, and this uniform distribution should be bound by [low, high].
sigma_low = pyro.param('sigma_low',lambda: torch.tensor(0.),constraint=constraints.interval(0,1))
sigma_high = pyro.param('sigma_high',lambda: torch.tensor(1.),constraint=constraints.interval(0,1))
sigma = pyro.sample('sigma',dist.Uniform(sigma_low,sigma_high).expand([n]).to_event(1))
But I often get errors saying the sigma_low can not be higher than sigma_high, which makes sense. But I am wondering how I can add this further constraint in the guide.
Would be appreciated some hints here.
Thanks a lot,
Frank
Hi. Do low
and high
have to be bounded by 0 and 1? If not you can try ordered_vector.
Hi @ordabayev,
Thanks so much for the reply and I am sorry for not being able to understand it immediately. Would you mind sharing a simple example of how to utilize the ordered_vector?
For me, I am hoping to model sigma
as a uniform distribution bounded by 0 and 1, so I am trying to use the sigma_low
and sigma_high
to achieve that. Are there better ways to achieve what I am looking for in the guide function?
Thanks again,
Frank
If you want to just have sigma
variable from a Uniform distribution bounded by 0 and 1 then you can just have:
sigma = pyro.sample('sigma', dist.Uniform(0, 1))
Unless I’m missing something.
Hi @ordabayev,
Sorry for the confusion, I meant to say, sigma
is a variational distribution in the guide function, defined by two parameters, which are its lower bound and higher bound. And through variational inference, we are learning these two parameters. However, this sigma
has to be within [0,1], so I am trying to figure out how I can enforce this constraint in my guide function.
Thanks again,
Frank
you can just use elementary transformations. e.g. let delta=high-low
and x=high/low
then put a (0,1)
constraint on delta
and a (1, \infty)
constraint on x
. then you can solve for high
and low
and get low=delta/(x-1)
and high=delta * x/(x-1)
. alternatively you can define y=x-1
and put a positivity constraint on y
and write low=delta/y
and high=delta * (y+1)/y
Hi @martinjankowiak,
Thanks so much for the instructions, I guess the actual code for your suggestion should be like below:
delta = pyro.param('delta',lambda:torch.tensor(0.),constrain=constrains.interval(0,1))
x = pyro.param('x',lambda:torch.tensor(1.),constrain=constrains.interval(1,float('inf')))
low = 1/(x-1)*delta
high = x/(x-1)*delta
sigma = pyro.sample('sigma',dist.Uniform(low,high))
But I wonder how it can guarantee that both low
and high
are within [0,1] itself? For example, if high=1.2, low=0.5, it should comply with the constrain defined above but the high
can not be 1.2 right?
Very appreciated for your help here,
Frank
whoops sorry i meant the following; the point is you can use elementary transformations and elementary constraints to achieve this:
-
d
in (0, 1)
-
x
in (0, 1)
low = x * (1 - d)
high = low + d
btw it may not be a great idea to have a guide like this because variational inference may not be well defined if the support of the model and guide differ at a particular sample site (here presumably sigma
). it might be better to e.g. use a Beta
distribution which assigns mass to all of the interval (0, 1)
but also allows concentration near any point of that interval.
Hi @martinjankowiak,
Thanks again for the prompt response!
I agree I think beta distribution might be a better idea here given sigma
must be within [0,1], and I probably should use it instead. But just go back to this uniform example for a second, it seems that d (0,1) and x (0,1) still can not exactly achieve the goal, doesn’t it?
Say high=0.8, and low=0.4, which are two valid bound values, then x=high/low=2, which violates the constraint for x?
Sorry for keeping bugging you but I am just hoping to get a better understanding of it.
Many thanks
Frank
i changed the definition of x
and d
. choose d
and x
for 1000 pairs of values satisfying unit interval constraints and compute low
and high
and you’ll see
1 Like
import torch
for _ in range(10**4):
d = torch.rand(1).item()
x = torch.rand(1).item()
l = x * (1 - d)
h = l + d
assert l > 0.0 and l < 1.0
assert h > 0.0 and h < 1.0
assert l < h
1 Like
Thanks so much for the code and clarifications!