separating concerns in RStan (and Stan)

40 views
Skip to first unread message

Bob Carpenter

unread,
Sep 29, 2013, 6:49:30 PM9/29/13
to stan...@googlegroups.com
(This is in response to a feature request I put in for
RStan to separate out a model object.)

The reason to separate model and fit is that they're
different concepts. The benefit of modularity is
in testing, documentation, and independent use.

I would like to see a model object in R that's a thin
wrapper around the model class in C++. This is just
used to provide the functions provided by the C++ class.
This is Stan-specific.

A bunch of Markov chains with variable names is a different
concept, and it's independent of how it's generated. This
concept is not Stan specific. So I still think it'd be nice
to allow other programs to use the R-hat and n_eff calcs
and nice summary output and graphics.

The fit object for ordinary MCMC sampling would then be a combination of
these two things. A fit object for optimization could be
something else. A fit object for variational Bayes could be
yet a different thing.

I do realize this can cause some redundancy in storing
variable names, but I think it's worth it for the separation.
(I don't know if R lets you store references or it it'll just
make a copy; either way, even a copy of all the names and
dimensions wouldn't be much overhead.)

This is not for RStan 2.0 by the way. I think it might make most
sense to do this when we add variational inference or a different
kind of sampler, etc. That'll give us an even better idea of
the functionality we need.

- Bob


Ben Goodrich

unread,
Sep 29, 2013, 6:58:06 PM9/29/13
to stan...@googlegroups.com
On Sunday, September 29, 2013 6:49:30 PM UTC-4, Bob Carpenter wrote:
(This is in response to a feature request I put in for
RStan to separate out a model object.)

The reason to separate model and fit is that they're
different concepts.  The benefit of modularity is
in testing, documentation, and independent use.

I would like to see a model object in R that's a thin
wrapper around the model class in C++.  This is just
used to provide the functions provided by the C++ class.
This is Stan-specific.

There is exactly that already. It is called the stanmodel class and its documentation can be found from

help("stanmodel-class")

And an instance of class stanmodel is a slot of the stanfit class

> showClass("stanfit")
Class "stanfit" [package "rstan"]

Slots:
                                                                                                     
Name:   model_name  model_pars    par_dims        mode         sim       inits   stan_args   stanmodel
Class:   character   character        list     integer        list        list        list   stanmodel
                             
Name:         date       .MISC
Class:   character environment


 
The fit object for ordinary MCMC sampling would then be a combination of
these two things.   A fit object for optimization could be
something else.  A fit object for variational Bayes could be
yet a different thing.

These could all be subclasses of the stanfit class.
 
I do realize this can cause some redundancy in storing
variable names, but I think it's worth it for the separation.
(I don't know if R lets you store references or it it'll just
make a copy;  either way, even a copy of all the names and
dimensions wouldn't be much overhead.)

Most of the time, copies only happen on modification, which would be pretty rare in typical RStan useage.

Ben

Bob Carpenter

unread,
Sep 29, 2013, 7:13:25 PM9/29/13
to stan...@googlegroups.com
Thanks for the explanation. I really do have to get deeper into
RStan code and stop asking you so many questions about it. I'm
just cluttering up our dev list!

- Bob
> --
> 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/groups/opt_out.

Allen Riddell

unread,
Sep 30, 2013, 9:03:20 AM9/30/13
to stan...@googlegroups.com
Hi,

Even after spending plenty of time in the rstan code I find it challenging
keeping things straight. Please correct me if I've got the details wrong here.

There's a stan_fit C++ class, an R stan_fit class (I found myself wishing these
didn't have the same name). Then there's an R stan_model class and there's also
a stan_model<.......> C++ class.

There's other small sources of confusion such as, log_prob of the *model* is
exposed in the stan_fit C++ object.

In PyStan there's only a single stan_fit class. It *is* the C++ and Python class
simultaneously since Cython lets you tack on Python objects to C++ instances.
This turns out to be have been a mistake for parallel processing, so I'm going
to have to rewrite things along RStan lines. But at least the separation between
the classes will be clear since Python uses CamelCase. The Python classes are
StanModel and StanFit; the C++ classes are stan_model<....> and stan_fit.

Best,

Allen

Allen Riddell

unread,
Sep 30, 2013, 9:10:34 AM9/30/13
to stan...@googlegroups.com
I spoke too soon. It's stanfit/stanmodel in R and stan_fit/stan_model in C++,
I think. And I realize that log_prob of the model is not a method, but rather
its own function (stan::model::log_prob_propto).

-a

Bob Carpenter

unread,
Sep 30, 2013, 11:24:08 AM9/30/13
to stan...@googlegroups.com


On 9/30/13 9:03 AM, Allen Riddell wrote:
> Hi,
>
> Even after spending plenty of time in the rstan code I find it challenging
> keeping things straight. Please correct me if I've got the details wrong here.

I hope Jiqiang can help with code details. Everything below
from me is just a design comment (with a hedge about C++ and
Python coding conventions, neither of which I know).

> There's a stan_fit C++ class, an R stan_fit class (I found myself wishing these
> didn't have the same name). Then there's an R stan_model class and there's also
> a stan_model<.......> C++ class.

I like the name parallelism as long as the R class is just
a thin wrapper around the C++ class, perhaps with some
utility methods attached related to R.

> There's other small sources of confusion such as, log_prob of the *model* is
> exposed in the stan_fit C++ object.

This is something that makes most sense to me to have
on the model class. The fit holds a reference to the model
class, so the way I'd like to see it used is to get the model
from the fit, then evaluate the log prob with the model.

But R has what seem to me a number of unusual conventions.
It's more conventional to have a very large function with
all kinds of configuation defaults and dependencies than a bunch
of modular building blocks. And in many ways this makes sense
for the call to the sampler, which has all kinds of config attached
to it, all of which has a default behavior.

> In PyStan there's only a single stan_fit class. It *is* the C++ and Python class
> simultaneously since Cython lets you tack on Python objects to C++ instances.
> This turns out to be have been a mistake for parallel processing, so I'm going
> to have to rewrite things along RStan lines. But at least the separation between
> the classes will be clear since Python uses CamelCase. The Python classes are
> StanModel and StanFit; the C++ classes are stan_model<....> and stan_fit.

I did Java for 10 years, so I kind of miss camel case.
Most C++ doesn't even use capital letters.

- Bob

Jiqiang Guo

unread,
Sep 30, 2013, 6:41:37 PM9/30/13
to stan...@googlegroups.com
I would be happy to answer specific questions.  I think the names are fine.  I always find it hard to give names and you cannot extrapolate much from them.  

And it might be better not to look at rstan for implementing pystan.  Directly taking a look at stan would be better as rstan is mimicking stan (specifically command.hpp).  Practically, I was just trying to make it work given R and Rcpp's functionality. 

--
Jiqiang  

Bob Carpenter

unread,
Oct 1, 2013, 4:08:57 AM10/1/13
to stan...@googlegroups.com


On 9/30/13 6:41 PM, Jiqiang Guo wrote:
> I would be happy to answer specific questions.

Thanks.

> I think the names are fine. I always find it hard to give names and you
> cannot extrapolate much from them.

I just wrote a section on why naming is important for
the Stan 2.0 manual :-) But like doc, they can be
misleading. (Like the user who was using "prec" for
a covariance matrix.)

> And it might be better not to look at rstan for implementing pystan. Directly taking a look at stan would be better as
> rstan is mimicking stan (specifically command.hpp).

Having a look at implementations can be really helpful!

> Practically, I was just trying to make it work given R and Rcpp's
> functionality.

It's pretty much impossible to see into the future. The best we
can do is continually improve the code as we understand it better.

At least that was the spirit in which I sent the previous few
e-mails. We just went through a HUGE refactor on Stan itself.
And there are still a bunch of things that aren't quite organized
right yet. Maybe by 3.0 ...

- Bob

Ben Goodrich

unread,
Oct 1, 2013, 8:30:25 AM10/1/13
to stan...@googlegroups.com
On Tuesday, October 1, 2013 4:08:57 AM UTC-4, Bob Carpenter wrote:
I just wrote a section on why naming is important for
the Stan 2.0 manual :-)  But like doc, they can be
misleading.  (Like the user who was using "prec" for
a covariance matrix.)

Another thing that is confusing at the moment, is that if someone wants to use a parameterized precision matrix, they have to declare it as a cov_matrix:

parameters {
  cov_matrix
[K] Sigma_inv;
}
model
{
 
...
  y
~ multi_normal_prec(mu, Sigma_inv);
 
...
}

Ben

Bob Carpenter

unread,
Oct 2, 2013, 3:45:19 PM10/2/13
to stan...@googlegroups.com


On 10/1/13 8:30 AM, Ben Goodrich wrote:
> Another thing that is confusing at the moment, is that if someone wants to use a parameterized precision matrix, they
> have to declare it as a cov_matrix:
>
> |
> parameters {
> cov_matrix[K] Sigma_inv;
> }
> model {
> ...
> y ~ multi_normal_prec(mu, Sigma_inv);
> ...
> }
> |

That was indeed a bad choice on my part for the variable
type. And it looks like I may have made the same bad decision
for the cholesky_cov we're about to introduce.

Do you think we should change it to positive_definite_symmetric
and deprecate the use of cov_matrix?

- Bob

Marcus Brubaker

unread,
Oct 2, 2013, 3:57:54 PM10/2/13
to stan...@googlegroups.com
I would suggest spd_matrix as the type name since the full thing seems painful.  (Also, linguistically symmetric usually comes first.  Not sure there's a good reason, I've just never really seen "positive definite symmetric" before.)

Perhaps cov_matrix (and maybe an added prec_matrix?) could be added as aliases to reduce confusion for users?

Cheers,
Marcus


--
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+unsubscribe@googlegroups.com.

Bob Carpenter

unread,
Oct 2, 2013, 3:59:36 PM10/2/13
to stan...@googlegroups.com


On 10/2/13 3:57 PM, Marcus Brubaker wrote:
> I would suggest spd_matrix as the type name since the full thing seems painful. (Also, linguistically symmetric usually
> comes first. Not sure there's a good reason, I've just never really seen "positive definite symmetric" before.)

Good suggestion.

> Perhaps cov_matrix (and maybe an added prec_matrix?) could be added as aliases to reduce confusion for users?

I'm worried that would be more confusing. I don't
like having several aliases for the same thing.

- Bob

Ben Goodrich

unread,
Oct 2, 2013, 9:12:00 PM10/2/13
to stan...@googlegroups.com
I like spd_matrix.

Ben
To unsubscribe from this group and stop receiving emails from it, send an email to stan-dev+u...@googlegroups.com.
Reply all
Reply to author
Forward
0 new messages