Bob I looked into this and I’m also a bit confused by the code on how the jacobian get’s called. In a generic stan model we’ll have something like the below defined in the model class
template <bool propto__, bool jacobian__, typename T__>
T__ log_prob(std::vector<T__> ¶ms_r__, std::vector<int> ¶ms_i__,
std::ostream *pstream__ = 0) const {
typedef T__ local_scalar_t__;
T__ lp__(0.0);
stan::math::accumulator<T__> lp_accum__;
static const char *function__ = "test_model_namespace::log_prob";
(void)function__; // suppress unused var warning
stan::io::reader<local_scalar_t__> in__(params_r__, params_i__);
try {
current_statement__ = 1;
validate_non_negative_index("b", "K", K);
Eigen::Matrix<local_scalar_t__, -1, 1> b;
b = Eigen::Matrix<local_scalar_t__, -1, 1>(K);
current_statement__ = 1;
b = in__.vector(K);
local_scalar_t__ Intercept;
current_statement__ = 2;
Intercept = in__.scalar();
{
current_statement__ = 3;
lp_accum__.add(student_t_lpdf<false>(Intercept, 3, 0, 10));
current_statement__ = 4;
lp_accum__.add(bernoulli_logit_glm_lpmf<false>(Y_opencl__, X_opencl__,
Intercept, b));
}
} catch (const std::exception &e) {
stan::lang::rethrow_located(e, locations_array__[current_statement__]);
// Next line prevents compiler griping about no return
throw std::runtime_error("*** IF YOU SEE THIS, PLEASE REPORT A BUG ***");
}
lp_accum__.add(lp__);
return lp_accum__.sum();
} // log_prob()
Where the whole model inherits from model_base_crtp<test_model>
. In the case of log_prob<false, true>(...)
(i.e. the jacobian) log_prob
differs to log_prob_jacobian
, but in model_base_crtp
that’s defined as
inline double log_prob_jacobian(std::vector<double>& theta,
std::vector<int>& theta_i,
std::ostream* msgs) const override {
return static_cast<const M*>(this)->template log_prob<false, true>(
theta, theta_i, msgs);
}
So it’s just calling the above function, but the function above doesn’t do anything with jacobian__
so I’m not following how it is used.
@Adam_Haber I think for your use case, instead of dealing with the above, take the test for lkj_corr_test and write one that checks over the support and logs it somewhere. You can also modify the cpp to write a log of the intermediate values. Then you can do the same thing for tensorflow and compare them.