-
Notifications
You must be signed in to change notification settings - Fork 7.1k
remove private imports from torch.testing #7525
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
base: main
Are you sure you want to change the base?
Conversation
🔗 Helpful Links🧪 See artifacts and rendered test results at hud.pytorch.org/pr/pytorch/vision/7525
Note: Links to docs will display an error until the docs builds have been completed. ❌ 3 FailuresAs of commit f9e77a6: NEW FAILURES - The following jobs have failed:
This comment was automatically generated by Dr. CI and updates every 15 minutes. |
|
||
if error_metas: | ||
raise error_metas[0].to_error(msg) | ||
for actual_item, expected_item in zip(actual_flat, expected_flat): |
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.
The only "regression" compared to the patched assert_close
is that we don't get any information where inside a sample an error happened. Consider the input sample to a detection model, i.e. a two-tuple with an image and a target dictionary. If the comparison of the bounding boxes target fails, assert_close
would include [1]["boxes"]
in the error message, whereas now we will only see the regular message and thus have to figure out ourselves what part of the input caused this.
We can re-implement this behavior if needed, but not sure its worth it. I guesstimate that 99% of our comparisons are single elements and thus no extra traceback is needed.
Apart from this, assert_close_with_image_support
should be a faithful reproduction of the patched assert_close
we had before.
# This is a dirty hack that let's us "hook" into the comparison logic of `torch.testing.assert_close`. It | ||
# will only be triggered in case of failed value comparison. This let's us reuse all of the attribute | ||
# checking that `torch.testing.assert_close` does while giving us the ability to ignore the regular value | ||
# comparison. |
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.
Per comment. Note while this is a hack, it doesn't depend on any non-public functionality or assumptions.
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.
NIT
# This is a dirty hack that let's us "hook" into the comparison logic of `torch.testing.assert_close`. It | |
# will only be triggered in case of failed value comparison. This let's us reuse all of the attribute | |
# checking that `torch.testing.assert_close` does while giving us the ability to ignore the regular value | |
# comparison. | |
# This is a dirty hack that lets us "hook" into the comparison logic of `torch.testing.assert_close`. It | |
# will only be triggered in case of failed value comparison. This lets us reuse all of the attribute | |
# checking that `torch.testing.assert_close` does while giving us the ability to ignore the regular value | |
# comparison. |
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.
Thanks Philip, some quick pass
nonlocal value_comparison_failure | ||
value_comparison_failure = True |
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.
IIUC this is the "hack" part and the rest below is just the same as the implementation for the default msg_callback
?
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. Basically this is our way of detecting that there was value comparison failure since this callback is only called in this specific case.
if not (value_comparison_failure and mae): | ||
raise |
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.
I might be misunderstanding, but why do we even bother try
ing torch.testing.assert_close
when mae
is True?
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.
assert_close
does a lot more checks than just the value comparison. For us the most important ones are shape, dtype, and device checks. If we don't invoke assert_close
, we'll have to do this ourselves or live with the fact that check_dtype=True
is ignored when mae=True
is set.
if actual.dtype is torch.uint8: | ||
actual, expected = actual.to(torch.int), expected.to(torch.int) | ||
mae_value = float(torch.abs(actual - expected).float().mean()) |
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.
(Hopefully correct?) NIT
if actual.dtype is torch.uint8: | |
actual, expected = actual.to(torch.int), expected.to(torch.int) | |
mae_value = float(torch.abs(actual - expected).float().mean()) | |
mae_value = torch.abs(actual.float() - expected.float()).mean() |
# This is a dirty hack that let's us "hook" into the comparison logic of `torch.testing.assert_close`. It | ||
# will only be triggered in case of failed value comparison. This let's us reuse all of the attribute | ||
# checking that `torch.testing.assert_close` does while giving us the ability to ignore the regular value | ||
# comparison. |
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.
NIT
# This is a dirty hack that let's us "hook" into the comparison logic of `torch.testing.assert_close`. It | |
# will only be triggered in case of failed value comparison. This let's us reuse all of the attribute | |
# checking that `torch.testing.assert_close` does while giving us the ability to ignore the regular value | |
# comparison. | |
# This is a dirty hack that lets us "hook" into the comparison logic of `torch.testing.assert_close`. It | |
# will only be triggered in case of failed value comparison. This lets us reuse all of the attribute | |
# checking that `torch.testing.assert_close` does while giving us the ability to ignore the regular value | |
# comparison. |
|
||
self._compare_attributes(actual, expected) | ||
actual, expected = self._equalize_attributes(actual, expected) | ||
enable_mae_comparison = all(isinstance(input, torch.Tensor) for input in [actual, expected]) |
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.
Should this be
enable_mae_comparison = all(isinstance(input, torch.Tensor) for input in [actual, expected]) | |
enable_mae_comparison = all(isinstance(input, torch.Tensor) for input in [actual, expected]) and mae |
? Regardless I don't really understand the reason for enable_mae_comparison
. Why can't we just convert all inputs to tensors and apply mae
comparison iff mae = True
?
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.
I wrote this as a general function that one can use like assert_close
, but with_image_support
. Meaning, you can still do assert_close_with_image_support(None, 5)
and get a proper error message. If we force everything into a tensor, that would not be possible.
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.
But are we ever going to use it when the inputs aren't images (either PIL or Tensors)?
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, we have such usages:
- In the functional v2 tests, we are using
assert_close
(or nowassert_close_with_image_support
) for all kernels and dispatchers and this of course also means bounding boxes, masks and videos. - In the consistency tests for the detection and segmentation tests, we test full samples against each other and thus the inputs are more than just images. This is somewhat also the case in our (fairly limited) transforms tests, but will probably increase there when we ramp them up.
actual, expected = self.actual, self.expected | ||
def assert_close_with_image_support(actual, expected, *, mae=False, atol=None, msg=None, **kwargs): | ||
def compare(actual, expected): | ||
if all(isinstance(input, PIL.Image.Image) for input in [actual, expected]): |
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 not convert all inputs to tensors, regardless of whether they're all PIL Images? Does that mean we can't do assert_close_with_image_support(some_tensor, some_pil_img)
?
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.
See #7525 (comment) for one reason. Plus, we originally had the option to pass in one tensor and one PIL image and let the function handle the conversion to tensor. However, we often saw extra flakiness in the tests just to this conversion and thus we scraped that feature. Since this irregular anyway, the few tests that need this, perform the conversion themselves now. E.g.
vision/test/transforms_v2_kernel_infos.py
Line 117 in 5579995
def pil_reference_wrapper(pil_kernel): |
No description provided.