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

BUG: Fixed maximum relative error reporting in assert_allclose #13802

Merged
merged 5 commits into from Sep 5, 2019

Conversation

CakeWithSteak
Copy link
Contributor

@CakeWithSteak CakeWithSteak commented Jun 18, 2019

Fixed maximum relative error reporting in assert_allclose.

In cases where the two arrays have zeros at the same positions it will
no longer report nan as the max relative error.

Fixes #13801.

In cases where the two arrays have zeros at the same positions it will
no longer report nan as the max relative error
@seberg seberg self-requested a review July 14, 2019 03:58
@charris charris modified the milestones: 1.16.5 release, 1.17.0 release Jul 15, 2019
@charris
Copy link
Member

charris commented Jul 15, 2019

Note to self: needs backport to 1.16.

@charris charris modified the milestones: 1.17.0 release, 1.17.1 release Jul 22, 2019
@seberg
Copy link
Member

seberg commented Aug 6, 2019

Dang, I just went back to the original issue. The issue is really only for exact zeros? (everything else would not map to NaN. In that case, we could also use nonzero = y != 0 and print (error[nonzero] / abs(y[nonzero])).max(). The function uses advanced indexing anyway already to check the NaN positions.

@CakeWithSteak
Copy link
Contributor Author

Yeah oops, you're right, I thought there would be more possibilities for the result to be nan.
Actually you can get nan one other way, by calling assert_allclose with equal_nan=False on two arrays that have nan at the same positions. In that case the absolute difference is also nan though, so I guess it's not a bug.
Example:

x = np.array([np.nan,1])
y = np.array([np.nan,2])
np.testing.assert_allclose(x,y, equal_nan=False)

Output:

AssertionError: 
Not equal to tolerance rtol=1e-07, atol=0

Mismatch: 100%
Max absolute difference: nan
Max relative difference: nan
 x: array([nan,  1.])
 y: array([nan,  2.])

Should I make a revert commit to revert the previous modifications, then add your changes in a separate one, or should I do it in just one commit?

@seberg
Copy link
Member

seberg commented Aug 6, 2019

don't worry about the history. If you want you can make a local backup branch just in case I guess.

# Filter values where the divisor would be zero
nonzero = y != 0
if all(~nonzero):
max_rel_error = array(inf)
Copy link
Member

Choose a reason for hiding this comment

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

OK, I guess this seems right if y happens to be all zero. I believe the result here should be just inf and not an array with inf inside, max also returns a scalar. (Although this is probably just printed, so it may not even make a difference.

Copy link
Member

Choose a reason for hiding this comment

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

Could you add a test for this branch (assuming it does not exist)?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

max_rel_error is passed to array2string and then printed, that's why I made it an array (although I guess float_(inf) would also work, but it makes no difference)
For the inf branch there is already a test: testing.tests.test_utils.TestAlmostEqual.test_error_message which tests this exact scenario of y being all zeros.
I've also written a test for the original issue TestAssertAllclose.test_report_max_relative_error

@charris
Copy link
Member

charris commented Aug 19, 2019

Close/reopen to rerun tests.

@charris charris closed this Aug 19, 2019
@charris charris reopened this Aug 19, 2019
@charris
Copy link
Member

charris commented Aug 21, 2019

There is a problem with the test.

@charris
Copy link
Member

charris commented Aug 21, 2019

Pushing off to 1.17.2.

@CakeWithSteak
Copy link
Contributor Author

#14203 changed the mismatch message in assert_array_compare, and that broke my test. I'll update it tomorrow when I get home.

@mattip
Copy link
Member

mattip commented Aug 24, 2019

LGTM. @seberg care to re-review?

max_rel_error = (error / abs(y)).max()
# Filter values where the divisor would be zero
nonzero = y != 0
if all(~nonzero):
Copy link
Member

Choose a reason for hiding this comment

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

nonzero is guaranteed to be an array here I think, so it would be better to use nonzero.all() (the other one may be pythons all). Other than that, seems all fine to me.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

nonzero isn't necessarily an array, for example in test TestArrayEqual.test_subclass_that_overrides_eq the not equal operator returns a single bool - calling .all() on it would raise an AttributeError. You're right about all being python's all - I'll import the function from numpy to fix that.

Also, applying operator ~ to a bool wouldn't work as intended, so I think it would be better to use any:

nonzero = y != 0
if not any(nonzero):
	max_rel_error = array(inf)
else:
	max_rel_error = (error[nonzero] / abs(y[nonzero])).max()

That would work even if the not equal operator returns a single bool, but it's kind of hard to read, so we could also invert the if statement.
Thoughts?

Copy link
Member

Choose a reason for hiding this comment

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

A numpy bool woul dbe good enough and considering that indexing works below it should do. But np.all is fine as well.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

So, simply this?

nonzero = bool_(y != 0)
if all(~nonzero):
	max_rel_error = array(inf)
else:
	max_rel_error = (error[nonzero] / abs(y[nonzero])).max()

Copy link
Member

Choose a reason for hiding this comment

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

Just make it np.any and I will be happy (or tell me that it already uses np.any).

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Do you mean np.all here? Yes, all is imported at the top of the function.

…_array_compare, fix behaviour for certain ndarray subclasses.
@charris charris modified the milestones: 1.17.2 release, 1.16.5 release Sep 4, 2019
@charris
Copy link
Member

charris commented Sep 4, 2019

@seberg Look good to you?

@charris charris modified the milestones: 1.16.5 release, 1.16.6 Sep 4, 2019
@seberg
Copy link
Member

seberg commented Sep 5, 2019

Yes, looks good. Thanks @CakeWithSteak.

@seberg seberg merged commit 3dccd84 into numpy:master Sep 5, 2019
charris pushed a commit to charris/numpy that referenced this pull request Sep 5, 2019
…gh-13802)

Fixed maximum relative error reporting in assert_allclose:

In cases where the two arrays have zeros at the same positions it will
no longer report nan as the max relative error
charris pushed a commit to charris/numpy that referenced this pull request Sep 5, 2019
…gh-13802)

Fixed maximum relative error reporting in assert_allclose:

In cases where the two arrays have zeros at the same positions it will
no longer report nan as the max relative error
@charris charris removed the 09 - Backport-Candidate PRs tagged should be backported label Sep 5, 2019
@charris charris removed this from the 1.16.6 milestone Sep 5, 2019
maxwell-aladago pushed a commit to maxwell-aladago/numpy that referenced this pull request Sep 6, 2019
…gh-13802)

Fixed maximum relative error reporting in assert_allclose:

In cases where the two arrays have zeros at the same positions it will
no longer report nan as the max relative error
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

assert_allclose reports NaN as max relative difference if arrays have zeros at the same positions
4 participants