-
-
Notifications
You must be signed in to change notification settings - Fork 5.5k
ENH: special: use boost in nctdtr
#21728
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
ENH: special: use boost in nctdtr
#21728
Conversation
scipy/special/tests/test_cdflib.py
Outdated
|
||
@pytest.mark.parametrize( | ||
"df,nc,x,expected,rtol", | ||
[[3000., 3., 0.1, 0.0018657780826323328, 1e-13], |
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 the test of the parameter range in the linked issue.
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.
Looks good to me! Just some small comments below.
Co-authored-by: Albert Steppi <albert.steppi@gmail.com>
@josef-pkt @bashtage : would migrating In case you have roundtrip tests for |
I switched away from scipy stats distributions for both nct and ncf to use scipy special AFAIR, AFAICS for nct it was only a runtime warning that showed up during rootfinding in sample size computation. (Because I always use older versions of scipy, lagging 1 to 3 years behind, I cannot investigate new problems when they show up.) |
Looking at statsmodels/statsmodels#8624, it would be interesting to know which parameters caused Boost's noncentral t CDF to go wild. |
I have now scipy 0.10
this is just looking at the values in the debugger of reported case in statsmodels issue update
correction: initial warning in statsmodels example is in sf, but that raises the same warning as cdf
|
I don't recall the specifics TBH. It was failing in pre-release testing which led to the previous bug report. |
Both warnings do not appear anymore with a recent scipy version. Maybe you could just suppress it. This PR is ready from my side. |
Thanks, |
@steppi: if you could provide an example of how to use the new rootfinder with boost functions, I could tackle migrating a lot of cdflib functions over to boost over the next months piece by piece. Such PRs are not really popular as they are tedious but they fit my current time budget for individual PRs reasonably well. |
82.35640899964173, 84.45263768373256] | ||
assert_allclose(res, res_exp) | ||
|
||
@pytest.mark.xfail_on_32bit("32bit fails due to algorithm threshold") |
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.
Why are we removing these test cases? Were they failing because the old cdflib reference is inaccurate for some of them? The reference values could be replaced with mpmath
then. This seems like a good opportunity to remove the xfail_on_32bit
and show that they now pass.
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.
Yes, the old reference values were very inaccurate for some cases. Allright, I will integrate them in the new tests against the mpmath reference. I might make a subjective selection though if that's okay with you.
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.
For high noncentrality values of 38 such as in the test originally, the mpmath reference computes CDF values of the order of 1e-310
. There also boost fails to get close or returns nan, so I dropped these for noncentrality of 15 instead.
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.
Cases like this where the reference output is subnormal are why it makes sense to use an atol
in tests. In cases like this, it's fine to return zero and signal underflow through sf_error
. Is Boost returning nan
where the previous method used to return 0? I'd count that as a bug.
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.
Fully agree that the nan
feels like a bug.
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.
@steppi : I do , am just short on time at the moment. Not sure I can make it till the 1.15 release as I am also going on holiday at the end of the month. I want to spend my scipy activities until then mostly on review. If you can/want to take over the last todos here, that would be much appreciated as I think this PR is almost ready to merge.
Edit: I can also file an issue upstream about the nan values but I doubt that they will be fixed in a short time frame.
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.
@steppi : I just had another look at the test cases for nc=38
. Even for small values within the normal floating point range, we get high discrepancies.
For df, nc, t = 0.98, 38, 1.5
the mpmath reference computes 1.546906350750292e-295
but boost results in 2.5919953604832226e-97
. Would you prefer to get the test to pass with something like atol=1e-90
? I would simply ignore these edge cases for now to be honest. In the parameter ranges that matter most we get much better results with boost.
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 looks like you set mp.dps
too low to evaluate the sum. I set mp.dps=500
and got the result 2.591995360483094e-97
from your reference implementation. Much closer to Boost. If you're evaluating a sum with mpmath
, you may need to set dps
pretty high.
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.
Ouch, thanks for spotting this. With mp.dps=500
, the reference calculation did not finish within 10 minutes on my laptop though. It has performance issues at the moment but this is crazy. How long does it take on your machine? Might try out my Mac instead.
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.
With 400 significant digits I also get 2.591995360483094e-97
within 12 minutes of computation time.
Sure, that would be great. I'll do one when I get bandwidth for it, and will ping you on the PR. This would likely be after the xsf migration, which I hope to complete before we branch. |
special.nctdtr
nctdtr
Allright, stars aligned and I had a bit of time yesterday. The There is now one failing parameter combination for 32bit CPUs. Let's skip the test again on 32bit then? @steppi : let me know if you have a strong opinion here about any of the above points, otherwise I will add the test skip. |
@dschmitz89, instead of removing the failing test case, mark it as Syntax is, instead of having a test case
pytest.param(
[0.98, -3.8, 0.15, 0.9999528361700505, 1e-13],
marks=pytest.mark.xfail(reason="Bug in underlying Boost math implementation"),
) for the failing test case on 32bit, your pytest.param(
test_case, # Subsitute in your actual test case
marks=pytest.mark.xfail(condition=sys.maxsize < 2**32, reason="Fails on 32 bit.")
) I don't think it's a good idea to just get rid of failing test cases, or skip the whole test on 32bit because of only one failing case. |
…ns negative value
Interesting that the 32bit job succeeds now. Maybe it had an issue in the way I handled the nan case which is now xfailed. Will push the latest stylistic updates without rerunning CI. |
[skip ci]
The green CI results do not show up here anymore due to my last commit: for the reviewer, they can easily be found here. |
Reference issue
Closes #8344
What does this implement/fix?
Uses boost for
nctdtr
. The PR is modeled after #21505. The trickiest part was the mpmath reference implementation,.Additional information
I did not migrate the noncentral t quantile
nctdtrit
yet as all default tests (no xslow etc.) ran successfully locally and I have to adjust the size of my PRs to the sleeping cycles of my little one, so trying to keep the small.