Skip to content
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

Replace incomplete_beta with betainc and speedup logcdf tests #4736

Closed
wants to merge 6 commits into from

Conversation

ricardoV94
Copy link
Member

@ricardoV94 ricardoV94 commented Jun 4, 2021

Implement Betainc

This PR replaces the incomplete_beta method in dist_math by an aesara op betainc that wraps the scipy.special.betainc method. Supersedes #4519; Closes #4420.

This provides a large increase in speed (and graph compilation) even without providing the c_code implementation directly (this can always be added later). I did some comparisons here. On my machine, the compilation time of a simple input/output function for the incomplete_beta was around 10 seconds, and it's pretty much instantaneous for the betainc as would be expected. Run time is ~2 orders of magnitude faster for the main op (even though it's calling scipy via Python), and ~4-5 orders of magnitude faster for the gradient.

It also allows the evaluation of the logcdf for multiple values in Beta, StudentT, Binomial, NegativeBinomial (and zero inflated variants). I removed the previous limitation warning when trying to evaluate these methods for multiple values. These changes are critical for any practical implementation of Truncated Versions of these distributions.

The derivative algorithm was adapted from this paper and requires the use of two extra "pseudo aesara ops" that simply wrap the equivalent python function. This does not allow for further graph optimizations, but I doubt aesara could do much with the previous scan implementation either. I did some extensive comparison with the STAN implementation, and these derivatives seem to be both faster and more accurate than theirs, although it's not easy to find a good numerical reference. Some discussion can be found in stan-dev/math#2417

The one downside is the constant warning that the op has no c-implementation whenever the logp/logcdf makes use of it.

Speedup logcdf tests

The logcdf tests are refactored to avoid recreating the logcdf graph for every parameter / value evaluation. This supersedes #4734. The old incomplete_beta was found to be defective when attempting #4734, and so I decided to merge the two PRs into this one instead.

This allows to remove most of the custom n_samples limitations, and makes the test suite run considerably faster.

A temporary work-around for the HyperGeometric tests was added, related to an optimization issue on Aesara side pymc-devs/pytensor#461

Finally, closes #4467

@ricardoV94
Copy link
Member Author

ricardoV94 commented Jun 4, 2021

Failing test was related to the minimum scipy version 1.2.0 not including betabinom, and one of tests now calls it, incidentally, to draw the initval. This is somewhat related to #4737

I raised the requirement to 1.4.1, is this okay? There were some concerns about raising it to 1.6.0, because Colab is still on 1.4.1, but this should be fine in that regard.

@ricardoV94
Copy link
Member Author

Looking at the pytest workflow, this PR seems to shave about 20-25 minutes from ~1h05m to 40m

Copy link
Contributor

@brandonwillard brandonwillard left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is the wrong place for an Aesara implementation of a scipy.special Op. Such Ops should be submitted as a PR to Aesara, so they can go alongside all the other scipy.special Ops; otherwise, we'll have more of the same unnecessary overlap in testing and maintenance that we've been trying to avoid.

Regardless, this is a very exciting update!

@ricardoV94
Copy link
Member Author

I can open a PR for the betainc in Aesara. When I opened the PR for the first time nobody mentioned that interest :)

else:
dK = np.log1p(-x) + scipy.special.digamma(p + q) - scipy.special.digamma(q)

for n in range(1, max_iters + 1):
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is the plain python for loop going to be slow here, or is the function is meant to run in python/numpy/scipy

Copy link
Member Author

@ricardoV94 ricardoV94 Jun 5, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Main Python loop for now. It's not really possible to vectorize as it is an iterative loop. It's still about ~4-5 orders of magnitude faster than the old C derivatives obtained by autodiff from the scan implementation of the incomplete_beta.

It's also very simple code to port to C or to Numba but I didn't want to do it just yet.

I have some speed comparisons here https://www.github.com/ricardoV94/derivatives_betainc/tree/master/comparison_aesara.ipynb

@brandonwillard
Copy link
Contributor

I can open a PR for the betainc in Aesara. When I opened the PR for the first time nobody mentioned that interest :)

Sorry, I've been too busy to keep up on PRs, but, if you request a review, I'll usually get to it by the weekend.

@ricardoV94
Copy link
Member Author

ricardoV94 commented Jun 5, 2021

I can open a PR for the betainc in Aesara. When I opened the PR for the first time nobody mentioned that interest :)

Sorry, I've been too busy to keep up on PRs, but, if you request a review, I'll usually get to it by the weekend.

I didn't mean anyone was at fault, there is no rush on my side. I'll open it there soon. 😅

@ricardoV94
Copy link
Member Author

Closing this one and opening a new one, since many things have changed

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Remove hacks to avoid previous aesara gammainc(c) limitations dist_math.incomplete_beta is very slow
3 participants