Repository navigation
Use a relative tolerance in is_constant - #407
Conversation
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## master #407 +/- ##
=======================================
Coverage 92.65% 92.65%
=======================================
Files 31 31
Lines 3240 3242 +2
=======================================
+ Hits 3002 3004 +2
Misses 238 238 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
|
This is how benchmark results would change (along with a 95% confidence interval in relative change) if 86b2c4e is merged into master:
Further explanation regarding interpretation and methodology can be found in the documentation. |
c0984f2 to
34d70fd
Compare
There was a problem hiding this comment.
Thank you. The function is_constant is an exact copy of the function in posterior.
I assume you want to have the changes taking effect immediately, so I approve the PR. In general, I would recommend to use directly posterior::is_constant. But we can make this in one go for loo v3.0.0 (related Issue #408).
This PR was assisted by Claude
Summary
loo has its own
is_constant()(R/helpers.R) with an absolute tolerance:abs(max(x) - min(x)) < .Machine$double.eps. Values of small magnitude are then treated as constant, so the result depends on the units ofx. This PR makes the tolerance relative to the largest absolute value inx, as stan-dev/posterior#469 did forposterior::is_constant().Problem
E_loo()usesis_constant()in the function-specific Pareto-k (.E_loo_khat_i()). Whenxis treated as constant,pareto_kis the k-hat of the ratios alone, and the k-hat ofh * ris not computed. For small-magnitudex,pareto_ktherefore changes with the scale ofx:Change
is_constant()inR/helpers.R:xis constant ifmax(x) - min(x) <= tol * max(abs(x)), or if all values are equal (also all 0 or all-Inf). The code is the same as in posterior#469.c(-Inf, 2), is not constant, the same as on master.xwithNAgivesNA, the same as on master.c(1, 1 + .Machine$double.eps).E_loo()also callsposterior::pareto_khat()onh * r. With a posterior without stan-dev/posterior#469, that call returnsNAfor small-magnitude values, soE_loo()needs both changes to give apareto_kthat does not depend on the scale ofx.The other constant check in loo, the tail check in
do_psis_i()(R/psis.R), works on log ratios shifted by their maximum. Log ratios do not change when the weights are scaled, so that check is not changed.Tests
tests/testthat/test_0_helpers.R:is_constant uses a tolerance relative to the magnitude of x: zeros, small constant values,-Inf, 1-ulp differences, small values that differ, infinite spread,NA.tests/testthat/test_E_loo.R:E_loo pareto_k does not depend on the scale of x, fors = 1e-20and1e-200. The test is skipped when the installed posterior has the absolute tolerance (posterior 1.7.1 on CRAN), becauseposterior::pareto_khat()then returnsNAforh * r.With posterior master (which has #469), the new tests give 6 failed expectations without this change and pass with it. With posterior 1.7.1 from CRAN, the
is_constant()tests pass and theE_loo()test is skipped.Tested versions
masterfd910fef.master48243f8.Copyright and Licensing
By submitting this pull request, the copyright holder is agreeing to license the submitted work under the following licenses: