| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
…lues for W, B, etc. are used
|
@SteveBronder the latest couple commits here look like mistakes meant for #3271 |
Sorry, something went wrong.
|
@SteveBronder f993bdb didn't fix the issue in stan-dev/stanc3#1586. You need to add a decay to the result of tuple_element_t in is_inner_tuple_type_v to get the intended behavior when the tuple of options contains e.g. const double& |
Sorry, something went wrong.
There was a problem hiding this comment.
Thanks for resolving all the above. I think there was one missed, and a few new things from the changes since then
Sorry, something went wrong.
| * @param theta_0_size Size of user supplied initial theta | ||
| * @return tuple representing laplace options exposed to user. | ||
| */ | ||
| inline auto generate_laplace_options(int theta_0_size) { |
There was a problem hiding this comment.
The idea is this could be exposed to the user, right? We probably want to workshop the name if so
Sorry, something went wrong.
There was a problem hiding this comment.
I'm open to new names!
Sorry, something went wrong.
|
I also ran the tests locally and noticed that nearly as many were being marked as SKIPPED as actually ran -- is that expected? |
Sorry, something went wrong.
Yes. Only a few tests run without the wolfe step, but we skip tests where having turning off the wolfe line search causes a failure. This is expected as the wolfe step stops overshooting from a bad initial position. |
Sorry, something went wrong.
|
fyi jenkins is failing just because of the api change
--- Compiling C++ code ---
clang++-6.0 -std=c++17 -D_REENTRANT -Wno-sign-compare -Wno-ignored-attributes -I stan/lib/stan_math/lib/tbb_2020.3/include -O0 -I src -I stan/src -I stan/lib/rapidjson_1.1.0/ -I lib/CLI11-1.9.1/ -I stan/lib/stan_math/ -I stan/lib/stan_math/lib/eigen_3.4.0 -I stan/lib/stan_math/lib/boost_1.87.0 -I stan/lib/stan_math/lib/sundials_6.1.1/include -I stan/lib/stan_math/lib/sundials_6.1.1/src/sundials -DBOOST_DISABLE_ASSERTS -c -include-pch stan/src/stan/model/model_header.hpp.gch/model_header_4_2.hpp.gch -x c++ -o ../stanc3/test/integration/good/code-gen/laplace_nested_tuple3.o ../stanc3/test/integration/good/code-gen/laplace_nested_tuple3.hpp
../stanc3/test/integration/good/code-gen/laplace_neg_binomial_2_log.hpp:404:24: error: no matching function for call to 'laplace_marginal_tol_neg_binomial_2_log_lpmf'
lp_accum__.add(stan::math::laplace_marginal_tol_neg_binomial_2_log_lpmf<
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
../stanc3/test/integration/good/code-gen/laplace_neg_binomial_2_log.hpp:792:12: note: in instantiation of function template specialization 'laplace_neg_binomial_2_log_model_namespace::laplace_neg_binomial_2_log_model::log_prob_impl<false, false, Eigen::Matrix<double, -1, 1, 0, -1, 1>, Eigen::Matrix<int, -1, 1, 0, -1, 1>, nullptr, nullptr, nullptr>' requested here
return log_prob_impl<propto__, jacobian__>(params_r, params_i, pstream);
^
So I think once we approve this and the stanc3 pr then we can just merge both at the same time |
Sorry, something went wrong.
There was a problem hiding this comment.
comments from meeting with @charlesm93
Sorry, something went wrong.
| * @param max_jitter Maximum jitter to try | ||
| */ | ||
| template <typename LLT, typename B_t> | ||
| inline void llt_with_jitter(LLT& llt_B, B_t& B, double min_jitter = 1e-10, |
There was a problem hiding this comment.
Consider logging when jitter is needed -- might be too verbose if happens every time?
Sorry, something went wrong.
There was a problem hiding this comment.
I think this would be too verbose to run every time.
Sorry, something went wrong.
| } | ||
| if (llt_B.info() != Eigen::Success) { | ||
| throw std::domain_error( | ||
| "laplace_marginal_density: Cholesky (Diag) failed"); |
There was a problem hiding this comment.
Fix string for general usage
Sorry, something went wrong.
| + covariance * state.prev().theta_grad(); | ||
| state.wolfe_info.init_dir_ = state.prev_g.dot(state.wolfe_info.p_); | ||
| // Flip direction if not ascending | ||
| state.wolfe_info.flip_direction(); |
There was a problem hiding this comment.
Test cutting this out
Sorry, something went wrong.
There was a problem hiding this comment.
@charlesm93 So actually there are a few packages that check this and if it the direction is not correct they throw an error
LBFGSpp just hard throws if the descent direction is not correct
https://github.com/yixuan/LBFGSpp/blob/master/include/LBFGSpp/LineSearchBacktracking.h#L62
Ceres conjugate gradient solver flips the direction
https://github.com/ceres-solver/ceres-solver/blob/master/internal/ceres/line_search_direction.cc#L87
So I'm not sure what we should do here. We could just leave it?
Sorry, something went wrong.
There was a problem hiding this comment.
I'm going to leave this.
In the wolfe line search we are doing maximization and want the low bracket to have a positive gradient and the high bracket to have a negative gradient so we are searching a space that looks like /\. If we don't flip this then we end up in a starting position that can look like \(/|\) which would goof up the search. So I'm going to leave this
Sorry, something went wrong.
| state.wolfe_status = internal::wolfe_line_search( | ||
| state.wolfe_info, update_fun, options.line_search, msgs); | ||
| } | ||
| if (run_convergence_check) { |
There was a problem hiding this comment.
Delete
Sorry, something went wrong.
| } else if (options.line_search.max_iterations == 0) { | ||
| state.curr().update(scratch); | ||
| state.wolfe_status.accept_ = true; | ||
| finish_update = false; |
There was a problem hiding this comment.
Delete
Sorry, something went wrong.
| if (!finite_ok) { // f or g is NaN/Inf → shrink | ||
| high.alpha() *= 0.5; | ||
| high_has_eval = false; | ||
| if (high.alpha() < opt.min_alpha) { | ||
| break; | ||
| } | ||
| continue; | ||
| } |
There was a problem hiding this comment.
Delete
Sorry, something went wrong.
| best = high; | ||
| } | ||
| const bool dir_pos = high.dir() > 0; | ||
| if (armijo && !wolfe && dir_pos) { // [2] |
There was a problem hiding this comment.
Delete !wolfe since if wolfe is true we would have completed earlier
Sorry, something went wrong.
| // [3,4,5] | ||
| found_right = true; |
There was a problem hiding this comment.
Check this is correct because we are looking for a low with directional derivative > 0 and high with directional derivative < 0.
Sorry, something went wrong.
There was a problem hiding this comment.
This can be correct if we are trying to exit early here and choose to start with a bisection and hope later in the bisection scheme we either find a good point or a point where we can do the cubic interpolation (`log.g > 0 and high.g < 0)
Sorry, something went wrong.
| if (!high_has_eval) { | ||
| wolfe_check = update_with_tick(scratch, curr, prev, high, p); | ||
| if (wolfe_check.stop_ != WolfeReturn::Continue) { | ||
| return wolfe_check; | ||
| } | ||
| high_has_eval = true; | ||
| } |
There was a problem hiding this comment.
Check if necessary
Sorry, something went wrong.
| // Choose trial alpha: cubic when bracket is good, else bisection. | ||
| double alpha_mid = use_cubic ? cubic_or_bisect_max(low, high, opt) | ||
| : 0.5 * (low.alpha() + high.alpha()); |
There was a problem hiding this comment.
| // Choose trial alpha: cubic when bracket is good, else bisection. | |
| double alpha_mid = use_cubic ? cubic_or_bisect_max(low, high, opt) | |
| : 0.5 * (low.alpha() + high.alpha()); | |
| // Choose trial alpha: cubic when bracket is good, else bisection. | |
| double alpha_mid = cubic_or_bisect_max(low, high, opt); |
Sorry, something went wrong.
|
I've started a re-run of downstream against the updated stanc3 here: https://jenkins.flatironinstitute.org/blue/organizations/jenkins/Stan%2FStan/detail/downstream_tests/780/pipeline I don't think this will actually update the build status here (might stay a red x), but it should be sufficient if it passes |
Sorry, something went wrong.
|
So we are going to merge this PR, then stanc. Note that once this is merged the CI will fail for any Stan pull requests for about an hour or so, but we can just rerun that stuff. |
Sorry, something went wrong.
| Back | FazBrowse Home | New Git URL |
Summary
This PR makes the following changes for the laplace approximation:
The graphic below shows the difference in estimates of the log likelihood for laplace relative to integrate_1d on the roach test data plotted along the mu and sigma estimates. There is still a bias relative to integrate_1d as mu becomes negative and sigma becomes larger, but it is much nicer than before.
Tests for the wolfe line search are added to test/unit/math/laplace/wolfe_line_search.hpp.
In the last iteration of the laplace approximation we were returning the negative block diagonal hessian and derived matrices from the previous search. This is fine if the line search in that last step failed. But if the line search succeeds then we need to go back and recalculate the negative block diagonal hessian and it's derived quantities.
Previously we had one block_hessian function that calculated both the block hessian or the diagonal hessian at runtime. But this function is only used in places where we know at compile time whether we want a block or diagonal hessian. So I split out the two functions to avoid unnecessary runtime branching.
For an initial step size estimate before each line search we use the Barzilai-Borwein method to get an estimate.
Previously we calculated them eargerly in each laplace iteration. But they are not needed within the inner loop so we wait till we finish the inner search then calculate their adjoints once afterwards.
We were calculating the covariance matrix from inside of laplace_density_est, but this required us to then return it from that function and imo looked weird. So I pulled it out and now laplace_marginal_density_est is passed the covariance matrix.
There were a few places where we could use log_sum_exp etc. so I made those changes.
The finite difference method in Stan was previously using stepsize optimzied a 2nd order method. But the code is a 6th order method. I modified finite_diff_stepsize to use epsilon^(1/7) instead of cbrt(epsilon). With this change all of the laplace tests pass with a much higher tolerance for precision.
Tests
All the AD tests now have a tighter tolerance for the laplace approximation.
There are also tests for the wolfe line search in test/unit/math/laplace/wolfe_line_search.hpp.
Release notes
Improve laplace approximation with wolfe line search and bug fixes.
Checklist
Copyright holder: Steve Bronder
The copyright holder is typically you or your assignee, such as a university or company. By submitting this pull request, the copyright holder is agreeing to the license the submitted work under the following licenses:
- Code: BSD 3-clause (https://opensource.org/licenses/BSD-3-Clause)
- Documentation: CC-BY 4.0 (https://creativecommons.org/licenses/by/4.0/)
the basic tests are passing
the code is written in idiomatic C++ and changes are documented in the doxygen
the new changes are tested