Can Someone Run a Quick Test For Me?

41 views
Skip to first unread message

Michael Betancourt

unread,
Jul 24, 2014, 5:50:51 PM7/24/14
to stan...@googlegroups.com
Using any Stan model can you hack any method to print out the results of lp in each of these calls?

stan::model::gradient(model_, cont_params_, lp, init_grad, &std::cout);
lp = model_.template log_prob<true, true>(cont_params_, &std::cout);
lp = model_.template log_prob<true, false>(cont_params_, &std::cout);
lp = model_.template log_prob<false, true>(cont_params_, &std::cout);
lp = model_.template log_prob<false, false>(cont_params_, &std::cout);

The absolute values don’t matter — I’m just looking for the comparison.

Bob Carpenter

unread,
Jul 24, 2014, 6:25:22 PM7/24/14
to stan...@googlegroups.com
Sure --- I can do that --- just give me a second.

- Bob
> The absolute values don't matter -- I'm just looking for the comparison.
>
> --
> You received this message because you are subscribed to the Google Groups "stan development mailing list" group.
> To unsubscribe from this group and stop receiving emails from it, send an email to stan-dev+u...@googlegroups.com.
> For more options, visit https://groups.google.com/d/optout.
>

Bob Carpenter

unread,
Jul 24, 2014, 7:02:22 PM7/24/14
to stan...@googlegroups.com
I used a model with a constraint so there was a non-empty
Jacobian and ran with both double and var inputs where
appropriate. I attached the model and C++ with added main()
to run it.

Recall that the template params are

<propto,apply_jacobian>


~/temp2$ ./formichael

DOUBLE
stan::model::gradient, lp = -4.46842
<true,true> lp = 1
<true,false> lp = 0
<false,true> lp = -8.14418
<false,false> lp = -9.14418

VAR
<true,true> lp = -4.46842:0
<true,false> lp = -5.46842:0
<false,true> lp = -8.14418:0
<false,false> lp = -4.46842:0


It looks like gradient and the var-based <true,true> match,
as expected.

Propto with all doubles causes everything to drop out other
than the Jacobian (when activated).

I'm worried about the mismatch in <false,false> (which should
not drop constants and should not include the jacobian, but it
turns out to be equivalent to the <true,true> case.

This is why I was thinking it'd make sense to include as a unit
test the cases that are expected to be the same.

- Bob

formichael.cpp
formichael.stan

Michael Betancourt

unread,
Jul 24, 2014, 7:12:00 PM7/24/14
to stan...@googlegroups.com
> DOUBLE
> stan::model::gradient, lp = -4.46842
> <true,true> lp = 1
> <true,false> lp = 0
> <false,true> lp = -8.14418
> <false,false> lp = -9.14418
>
> VAR
> <true,true> lp = -4.46842:0
> <true,false> lp = -5.46842:0
> <false,true> lp = -8.14418:0
> <false,false> lp = -4.46842:0
>
>
> It looks like gradient and the var-based <true,true> match,
> as expected.
>
> Propto with all doubles causes everything to drop out other
> than the Jacobian (when activated).
>
> I'm worried about the mismatch in <false,false> (which should
> not drop constants and should not include the jacobian, but it
> turns out to be equivalent to the <true,true> case.

Why don’t the double and var values match?

I also don’t understand the <true,false> case — why is that always returning zero?

It seems like propto=true isn’t just dropping the normalizing constants it’s also
dropping the likelihood itself. Unless I’m misunderstanding how log_prob is
supposed to work?

> This is why I was thinking it'd make sense to include as a unit
> test the cases that are expected to be the same.

Sure, I just need to understand the expected behavior first. Which I clearly don’t.

Marcus Brubaker

unread,
Jul 24, 2014, 7:17:52 PM7/24/14
to stan...@googlegroups.com
The <true,false> case being zero for double makes sense.  Terms in PDFs are dropped when propto=true and the data type that they'd produce is a double.  Calling the double version with propto=true means that *everything* results in a double, so basically it removes the ability of the PDFs to tell what's a constant.

Cheers,
Marcus



On Thu, Jul 24, 2014 at 7:11 PM, Michael Betancourt <betan...@gmail.com> wrote:
> DOUBLE
> stan::model::gradient, lp = -4.46842
> <true,true> lp = 1
> <true,false> lp = 0
> <false,true> lp = -8.14418
> <false,false> lp = -9.14418
>
> VAR
> <true,true> lp = -4.46842:0
> <true,false> lp = -5.46842:0
> <false,true> lp = -8.14418:0
> <false,false> lp = -4.46842:0
>
>
> It looks like gradient and the var-based <true,true> match,
> as expected.
>
> Propto with all doubles causes everything to drop out other
> than the Jacobian (when activated).
>
> I'm worried about the mismatch in <false,false> (which should
> not drop constants and should not include the jacobian, but it
> turns out to be equivalent to the <true,true> case.

Why don't the double and var values match?

I also don't understand the <true,false> case -- why is that always returning zero?


It seems like propto=true isn't just dropping the normalizing constants it's also
dropping the likelihood itself.  Unless I'm misunderstanding how log_prob is
supposed to work?

> This is why I was thinking it'd make sense to include as a unit
> test the cases that are expected to be the same.

Sure, I just need to understand the expected behavior first.  Which I clearly don't.

Michael Betancourt

unread,
Jul 24, 2014, 7:22:46 PM7/24/14
to stan...@googlegroups.com
Never mind — I get it. In the double version everything is a “constant” and hence dropped.

When you call gradient only terms that don’t depend on the input parameters are dropped.

Marcus Brubaker

unread,
Jul 24, 2014, 7:24:40 PM7/24/14
to stan...@googlegroups.com
It may be worth checking for and somehow indicating an error if someone tries to call log_prob with doubles and propto=true.  It will never make sense to do it with PDFs implemented the way they are right now.

Cheers,
Marcus


On Thu, Jul 24, 2014 at 7:22 PM, Michael Betancourt <betan...@gmail.com> wrote:
Never mind -- I get it.  In the double version everything is a "constant" and hence dropped.


When you call gradient only terms that don't depend on the input parameters are dropped.

On Jul 25, 2014, at 12:11 AM, Michael Betancourt <betan...@gmail.com> wrote:

>> DOUBLE
>> stan::model::gradient, lp = -4.46842
>> <true,true> lp = 1
>> <true,false> lp = 0
>> <false,true> lp = -8.14418
>> <false,false> lp = -9.14418
>>
>> VAR
>> <true,true> lp = -4.46842:0
>> <true,false> lp = -5.46842:0
>> <false,true> lp = -8.14418:0
>> <false,false> lp = -4.46842:0
>>
>>
>> It looks like gradient and the var-based <true,true> match,
>> as expected.
>>
>> Propto with all doubles causes everything to drop out other
>> than the Jacobian (when activated).
>>
>> I'm worried about the mismatch in <false,false> (which should
>> not drop constants and should not include the jacobian, but it
>> turns out to be equivalent to the <true,true> case.
>
> Why don't the double and var values match?
>
> I also don't understand the <true,false> case -- why is that always returning zero?

>
> It seems like propto=true isn't just dropping the normalizing constants it's also
> dropping the likelihood itself.  Unless I'm misunderstanding how log_prob is
> supposed to work?
>
>> This is why I was thinking it'd make sense to include as a unit
>> test the cases that are expected to be the same.
>
> Sure, I just need to understand the expected behavior first.  Which I clearly don't.

Bob Carpenter

unread,
Jul 24, 2014, 7:27:22 PM7/24/14
to stan...@googlegroups.com
We could do that with some fancy enable-if-ing.

- Bob

Michael Betancourt

unread,
Jul 24, 2014, 7:27:38 PM7/24/14
to stan...@googlegroups.com
The only thing that’s weird in hindsight is that Jacobians are never treated as
constants, even if all the inputs are doubles.  It’s not wrong, we just have to
be careful to note the scope of propto and how Jacobians are slightly different
from the rest of the log_prob calculation.

Michael Betancourt

unread,
Jul 24, 2014, 7:28:21 PM7/24/14
to stan...@googlegroups.com
Seriously, I’m enable_if’ing everything these days.

Alp Kucukelbir

unread,
Jul 27, 2014, 5:03:45 PM7/27/14
to stan...@googlegroups.com
Michael, Bob:

This was super-helpful. I wasn't even aware of the distinction between the "DOUBLE" and "VAR" cases described above.

OK so my question to everyone now is this: I want to get the version of log_prob that corresponds to Bob's "VAR<true, true>" case. But I don't want to compute a gradient (at that point in the code).

Can I do this with double (in Eigen Vector/Matrix/whatever) inputs? Or do I need to convert my inputs to stan::agrad::var objects? (If the latter, how should I go about doing that efficiently/safely?)

Thanks!
Alp

Bob Carpenter

unread,
Jul 27, 2014, 6:49:15 PM7/27/14
to stan...@googlegroups.com

On Jul 27, 2014, at 5:03 PM, Alp Kucukelbir <akucu...@gmail.com> wrote:

> Michael, Bob:

We're not the only ones who understand this bit of the code!

> This was super-helpful. I wasn't even aware of the distinction between the "DOUBLE" and "VAR" cases described above.

If propto=true, Stan drops constants, defined as any term in the log prob
that doesn't involve a var or fvar (fvar is the type for forward-mode
autodiff, which lets us do higher-order derivatives).

> OK so my question to everyone now is this: I want to get the version of log_prob that corresponds to Bob's "VAR<true, true>" case. But I don't want to compute a gradient (at that point in the code).
>
> Can I do this with double (in Eigen Vector/Matrix/whatever) inputs?

No. See the definition of propto above.

> Or do I need to convert my inputs to stan::agrad::var objects? (If the latter, how should I go about doing that efficiently/safely?)

Use the double-based log_prob_propto function in model/util.hpp.

It only does the forward-pass part of reverse-mode. We could probably
rewrite it to just use forward-mode, which should be more efficient.

- Bob

Michael Betancourt

unread,
Jul 27, 2014, 7:13:48 PM7/27/14
to stan...@googlegroups.com
Where in the algorithm do you need this?  My concern is that if you need the log posterior
then you have to worry about the correct normalization which is going to be tricky.

Alp Kucukelbir

unread,
Jul 27, 2014, 7:23:27 PM7/27/14
to stan...@googlegroups.com
I don't believe I will need the normalization at this point, as I'm computing a lower bound.

I've implemented a "hacky" version in src/stan/vb/bbvb.hpp, function calc_ELBO. (This is on the feature/bbvb branch.)

I will to look into Bob's suggestion of doing this without casting everything to a stan::agrad::var.
> --
> You received this message because you are subscribed to a topic in the Google Groups "stan development mailing list" group.
> To unsubscribe from this topic, visit https://groups.google.com/d/topic/stan-dev/lw1EOeM9yA0/unsubscribe.
> To unsubscribe from this group and all its topics, send an email to stan-dev+u...@googlegroups.com.

Bob Carpenter

unread,
Jul 27, 2014, 11:57:03 PM7/27/14
to stan...@googlegroups.com

On Jul 27, 2014, at 7:23 PM, Alp Kucukelbir <akucu...@gmail.com> wrote:

> I don't believe I will need the normalization at this point, as I'm computing a lower bound.
>
> I've implemented a "hacky" version in src/stan/vb/bbvb.hpp, function calc_ELBO. (This is on the feature/bbvb branch.)
>
> I will to look into Bob's suggestion of doing this without casting everything to a stan::agrad::var.

It does the promotion to stan::agrad::var behind the scenes. It
just avoids the backward pass that applies the chain rule.

If you can, you want to combine the computation of the log prob
and the gradient.

The only way to get around this performance hit would be to rewrite
all of our probability functions to do templating for dropping terms
in a more refined way than just looking at the types. Not impossible,
but a lot of work.

- Bob

Alp Kucukelbir

unread,
Jul 28, 2014, 7:57:50 AM7/28/14
to stan...@googlegroups.com

> It does the promotion to stan::agrad::var behind the scenes. It
> just avoids the backward pass that applies the chain rule.

I was treating the excellent stan::agrad library as a blackbox up to now... do I need to understand these subtleties at this point?

> If you can, you want to combine the computation of the log prob
> and the gradient.

That may be possible, actually... let me first get the algorithm running. Then I'll see if I can combine the two computations.

> The only way to get around this performance hit would be to rewrite
> all of our probability functions to do templating for dropping terms
> in a more refined way than just looking at the types. Not impossible,
> but a lot of work.

No worries, especially at this stage!

Cheers,
Alp

Bob Carpenter

unread,
Jul 28, 2014, 12:23:07 PM7/28/14
to stan...@googlegroups.com

On Jul 28, 2014, at 7:57 AM, Alp Kucukelbir <akucu...@gmail.com> wrote:

>
>> It does the promotion to stan::agrad::var behind the scenes. It
>> just avoids the backward pass that applies the chain rule.
>
> I was treating the excellent stan::agrad library as a blackbox up to now... do I need to understand these subtleties at this point?

Like all coding, it helps to understand how your code gets
compiled and executed if you want to optimize it.

>> If you can, you want to combine the computation of the log prob
>> and the gradient.
>
> That may be possible, actually... let me first get the algorithm running. Then I'll see if I can combine the two computations.

Good plan.

- Bob
Reply all
Reply to author
Forward
0 new messages