-
Notifications
You must be signed in to change notification settings - Fork 71
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Added qmc_quad based method for estimation of the constrained normalization factor #839
base: main
Are you sure you want to change the base?
Added qmc_quad based method for estimation of the constrained normalization factor #839
Conversation
We currently have a (soft) requirement that all priors should implement a rescale method (currently it will just return Even if we make the base class raise an error when you attempt to rescale it will still be possible to use some samplers in that case. It's possible that people will implement their own prior subclasses that don't support the rescale, so I'm not opposed to keeping a fallback. It may make everything easier if we change |
I think that actually the existing method won't work if the new prior doesn't implement |
I have updated the PR quite a bit. The core logic of the integration of the normalization factor is now handled by one of two functions: either MC-Integration based on samples from I have also optimized the For the example I gave above, the qmc-based implementation is now actually slower than the I have also improved the robustness against bugs by checking if the chosen keys are sufficient to compute the constrained, and if the PriorDict is constrained in the first place. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is looking good! I just have a few specific comments/questions.
bilby/core/prior/dict.py
Outdated
if np.any(np.isnan(samples[key])): | ||
print("The rescale method appears to be not working. Switching to 'sample_based'.") | ||
integrator = self._integrate_normalization_factor_from_samples | ||
except Exception: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd rather not use a plain Exception
. Do you have an example of a case that failed and what error is raised? I would imagine it would be something like NotImplementedError
or AttributeError
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's probably better completely removed. I thought about user-side errors in the implementation of custom priors, but such cases should probably fail loudly rather than silently.
Maybe catching NotImplementedError
could be added to prepare for later changes that add NotImplementedError
s to the base classes, but that would also render the check if some priors yield None
unnecessary.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This sounds good to me.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I updated the PR so that both cases are accounted for
…putaional overhead and repeateability
…f rescale method is save
8e73e20
to
98bd7c6
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is in great shape, just two last documentation based comments.
The normalization factor, rounded to the number of significant digits based on the standard deviation of | ||
the integration estimate. | ||
|
||
""" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for adding this docstring, the argument description is nice, since we're adding can I suggest also adding a notes section with a seealso directive to point to Halton
and a versionchanged directive set to 2.4.0.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I hope I did this in the right way :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think you could do, e.g., :func:scipy.integrate.qmc_quad
, but I'm not sure how to link to the external package. I would probably go for just :code:scipy.integrate.qmc_quad
. The "Scipy's scipy....
" is kind of redundant and can just be ":code:scipy....
"
This is how it currently renders (you can download the produced as a CI artefact if you can't build the docs locally.)
This PR implements a new method to estimate the normalization factor for constrained priors.
The changes are two-fold:
scipy.integrate.qmd_quad
, a quasi-Monte Carlo-based integration routine that is expected to yield better results than regular Monte Carlo integration. However, the routine requires a rescaling step from the unit cube rather than direct sampling.I have tested the two implementations with a relatively easy scenario: A 2D uniform prior on the [-1,1] cube, constrained to an inscribed circle with different radii:
The new method is significantly faster for high normalization factors, and the relative errors show a similar spread.
The implementation is marked as a draft because of the requirement of a
rescale
-method of the priors. Thus, it could be nice to keep the old method as a fallback. Also, the relative-error termination criterion could be applied just as well to the old implementation.Related issue: #835