-
-
Notifications
You must be signed in to change notification settings - Fork 5.1k
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
BUG: stable evaluation of expit #3386
Conversation
@@ -73,3 +73,8 @@ def test_float64(self): | |||
0.79139147, 0.9022274, | |||
0.95734875, 0.98201379]) | |||
self.check_expit_out('f8', expected) | |||
|
|||
def test_float64_large(self): | |||
yield assert_allclose, 1.0, expit(710) |
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.
yield
tests don't work in TestCase subclasses (nose weirdness...).
Fixed the yield assertions. I didn't know they weren't allowed in TestCase, and it's disconcerting to me that they were just silent. I've probably committed some code in scipy or elsewhere with tests that are not doing anything... |
Is this the kind of bug that could be backported? |
Yes. However, @rgommers didn't branch 0.14.0 yet. |
I hope this fix is easy to review. Both conditional branches are mathematically the same, but they are numerically stable in different regimes (0<x vs x<0). The expit function is also called the logistic function (which is different from logit). See this blog post explaining how to evaluate it in a numerically stable way, branching according to the sign of x. |
Looks good to me. There should also be tests for other data types, since the same problem occurs (at different thresholds) for float32 and float128:
|
btw numpy and scipy are littered with bugs for float > 64 right? I never use these precisions, and the only time I see them is for reported bugs, so I assume that they are not truly supported beyond numpy.ndarray being able to physically store their representations. |
also my platform doesn't even have |
@WarrenWeckesser added |
BUG: special: fix stable evaluation of expit
Thanks, LGTM |
I'm still surprised that it's evaluated this way. In scikit-learn, we had this implementation (in Cython), until I figured out that reducing expit to tanh was faster and stable enough (up to x=1000, at least): def expit(x):
z = .5 * x
np.tanh(z, z)
z += 1
z *= .5
return z Has this ever been considered for the |
closes #3385