On 11/15/13, 5:35 PM, Ben Goodrich wrote:
> So, we have a several examples of Matt-trickish things where the optimal thing to do would be to put a prior on
> primitive parameters and transform them to imply a particular prior on substantive parameters. Currently, we are forcing
> users to do all these tricks in the .stan file, which can be tedious and / or error prone.
Agreed.
> We could write convenience
> functions to do the transformations (and maybe optimize the derivatives internally), but it would still be up to the
> user to put the appropriate prior on the primitive parameters, which would still be tedious and error-prone.
But in this case, those would be standardized and
could get matching functions or it could all be rolled
into a single function.
> Is there some way we can design things so that particular transformation functions get to change the log-posterior? So,
Yes, it's possible. It's basically how the
log probability functions. The parser recognizes
a function ending in "_log" (a very bad choice in
retrospect) and adds an argument for lp__, which
is passed by non-constant reference.
Scope of where these functions are allowed is restricted
to the blocks where there is a log probability to
modify --- transformed parameters and model.
> something like
>
> |
> parameters {
> vector[K] z;
> }
> model {
> vector[K] s;
> s <- normalize2uniform(z);
> }
> |
>
> would be equivalent to
>
> |
> parameters {
> vector[K] z;
> }
> model {
> vector[K] s;
> s <- z / sqrt(dot_self(z))
> z ~ normal(0.0, 1.0);
> }
I'm afraid I can't quite follow the intent of this
transform. What's going to happen with the s?
But whatever it's intent, we could code the
first thing so that it behaves like the second in just
the way you suggest.
I was thinking we'd transform something like:
parameters {
real mu;
real sigma;
real y;
}
model {
y ~ normal(mu,sigma);
}
to be equivalent to this:
parameters {
real mu;
real sigma;
real y_unit;
}
transformed parameters {
real y;
y <- mu + sigma * y_unit;
}
model {
y_unit ~ normal(0,1);
}
But that I'm not so sure how to do because it's not
just adding a function, and it drops an implicit y_raw
value on users. And I believe there will be ordering
issues that are complicated if there are multiple instances.
> I guess either Stan would need to know that it needs to pass the log-posterior by value to functions like
> normalize2uniform or we would have to rearrange the scope so that such functions could modify lp__ .
I think you meant by non-constant reference rather than by
value. Most arguments are passed by constant reference. All
we have to do is drop the "const" in the definition and it can
modify its inputs. So far, I've tried to stay away from doing
that explicitly because I think reference vs. value is a complicated
enough concept that it'll confuse users. Passing by const
reference gives us the efficiency of pass by ref with the
transparency of pass-by-value.
- Bob