-
Notifications
You must be signed in to change notification settings - Fork 226
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
Skew normal distribution PPF incorrect for high skew #1120
Comments
Confirmed with reproducer:
|
@jzmaddock here are the first couple steps. The guess looks pretty good but then it makes a massive first step and attempts to work downward taking 3-4 steps per order of magnitude.
Increasing the max number of steps to 10000 this converges after 710 steps to the correct answer. |
@mborland , @jzmaddock : The following Mathematica code gets the update for the Halley iterate-I wonder if it can be used to stabilize the "wildness" of the Newton iterate: (You can see that the simplification could've been just a bit better there-most of the bells cancel.) So each iteration will take 2 erf calls, one Owen's T call, and an exp.) I confess to quite enjoying the Halley iterate for scalar rootfinding problems. For example, if Φ'(x) = 0 at some point, Newton's method fails, but Halley's method can gracefully degrade to Halley's irrational method. And if the denominator 2Φ'(x)² - Φ(x)Φ''(x) in Halley's method becomes zero, we can gracefully degrade to a Newton step. I also note that we might be able to do a bit better on constraining the domain: math/include/boost/math/distributions/skew_normal.hpp Lines 684 to 685 in 15c40fa
We might be able to use the fact that the mean of the skew normal distribution can be expressed in terms of a computation that requires only an addition and multiplication. That would allow us to write: if (p >= 0.5) {
search_min = μ + ωδsqrt(2/π);
} else {
search_max = μ + ωδsqrt(2/π)
} Maybe not the tightest constraint, but perhaps better than the entire real line. |
Just looking at this now - that looks like a rather expensive way of computing derivatives, but more to the point, I have a hunch that for sufficiently high skewness you will always reach a point where the computation blows up: effectively the CDF becomes something like a square wave with zero derivative(s) either side of a near vertical crossover point. I'm wondering if the TOMS748 algorithm might be a better choice here: it has robust root bracketing (provided you start the right side of zero). It's a little worse than Newton in the smooth cases (typically ~ 12 iterations for double precision) but against that there's no need to compute roots? I'm out today, but I'll try and experiment later... |
Well, the idea is that you have to compute these quantities just to evaluate the CDF anyway, so you might as well use them for the derivatives too. But I think you're probably right: This is a bracketing problem, not a convergence problem. |
TOMS748 gets that particular case in 20 iterations which looks pretty good, but I need to devise some better tests and make sure it doesn't blow up anywhere... |
Rather than Newton iterations. Add test case. Fixes #1120
Hey, sorry I missed out on this conversation. I have some thoughts regarding this. I'm fairly convinced that Newton's method would work great on the logit-CDF. Unfortunately, as far as I can tell, there is no numerically stable implementation of skewnorm CDF in the literature. (For positive skew and mildly-negative x, there is catastrophic cancellation when subtracting the Owen's T, even accounting for the I think I know how to compute it stably, but I'm unfortunately slammed with other work at the moment. |
This showed up in SciPy: scipy/scipy#20124
Minimal Python reproducer:
SciPy recently updated to Boost's develop branch at this commit, which did not solve this issue but only changed the error message to the one above.
Thanks in advance!
The text was updated successfully, but these errors were encountered: