-
Notifications
You must be signed in to change notification settings - Fork 7.2k
More datapoints docs and comments #7830
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
Changes from 3 commits
7db6feb
ca6a467
26a7cc0
fbf098f
f9ac7c0
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -48,26 +48,22 @@ | |
| # Under the hood, they are needed in :mod:`torchvision.transforms.v2` to correctly dispatch to the appropriate function | ||
| # for the input data. | ||
| # | ||
| # :mod:`torchvision.datapoints` supports four types of datapoints: | ||
| # | ||
| # * :class:`~torchvision.datapoints.Image` | ||
| # * :class:`~torchvision.datapoints.Video` | ||
| # * :class:`~torchvision.datapoints.BoundingBoxes` | ||
| # * :class:`~torchvision.datapoints.Mask` | ||
| # | ||
| # What can I do with a datapoint? | ||
| # ------------------------------- | ||
| # | ||
| # Datapoints look and feel just like regular tensors - they **are** tensors. | ||
| # Everything that is supported on a plain :class:`torch.Tensor` like ``.sum()`` or | ||
| # any ``torch.*`` operator will also works on datapoints. See | ||
| # any ``torch.*`` operator will also work on datapoints. See | ||
| # :ref:`datapoint_unwrapping_behaviour` for a few gotchas. | ||
|
|
||
| # %% | ||
| # | ||
| # What datapoints are supported? | ||
| # ------------------------------ | ||
| # | ||
| # So far :mod:`torchvision.datapoints` supports four types of datapoints: | ||
| # | ||
| # * :class:`~torchvision.datapoints.Image` | ||
| # * :class:`~torchvision.datapoints.Video` | ||
| # * :class:`~torchvision.datapoints.BoundingBoxes` | ||
| # * :class:`~torchvision.datapoints.Mask` | ||
| # | ||
| # .. _datapoint_creation: | ||
| # | ||
| # How do I construct a datapoint? | ||
|
|
@@ -209,42 +205,78 @@ def get_transform(train): | |
| # I had a Datapoint but now I have a Tensor. Help! | ||
| # ------------------------------------------------ | ||
| # | ||
| # For a lot of operations involving datapoints, we cannot safely infer whether | ||
| # the result should retain the datapoint type, so we choose to return a plain | ||
| # tensor instead of a datapoint (this might change, see note below): | ||
| # By default, operations on :class:`~torchvision.datapoints.Datapoint` objects | ||
| # will return a pure Tensor: | ||
|
|
||
|
|
||
| assert isinstance(bboxes, datapoints.BoundingBoxes) | ||
|
|
||
| # Shift bboxes by 3 pixels in both H and W | ||
| new_bboxes = bboxes + 3 | ||
|
|
||
| assert isinstance(new_bboxes, torch.Tensor) and not isinstance(new_bboxes, datapoints.BoundingBoxes) | ||
| assert isinstance(new_bboxes, torch.Tensor) | ||
| assert not isinstance(new_bboxes, datapoints.BoundingBoxes) | ||
|
|
||
| # %% | ||
| # .. note:: | ||
| # | ||
| # This behavior only affects native ``torch`` operations. If you are using | ||
| # the builtin ``torchvision`` transforms or functionals, you will always get | ||
| # as output the same type that you passed as input (pure ``Tensor`` or | ||
| # ``Datapoint``). | ||
|
|
||
| # %% | ||
| # If you're writing your own custom transforms or code involving datapoints, you | ||
| # can re-wrap the output into a datapoint by just calling their constructor, or | ||
| # by using the ``.wrap_like()`` class method: | ||
| # But I want a Datapoint back! | ||
| # ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ||
| # | ||
| # You can re-wrap a pure tensor into a datapoint by just calling the datapoint | ||
| # constructor, or by using the ``.wrap_like()`` class method (see more details | ||
| # above in :ref:`datapoint_creation`): | ||
|
|
||
| new_bboxes = bboxes + 3 | ||
| new_bboxes = datapoints.BoundingBoxes.wrap_like(bboxes, new_bboxes) | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. non-blocking thought to reduce the number of chars to type, it could be simple to have
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yeah, I find it a bit long and clunky as well. That would be the best UX but unfortunately we can't do that because We can implement instance methods on BBoxes objects, but I can't think of a good name either right now
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We have #7780 to go from |
||
| assert isinstance(new_bboxes, datapoints.BoundingBoxes) | ||
|
|
||
| # %% | ||
| # See more details above in :ref:`datapoint_creation`. | ||
| # Alternatively, you can use the :func:`~torchvision.datapoints.set_return_type` | ||
| # as a global config setting for the whole program, or as a context manager: | ||
|
|
||
| with datapoints.set_return_type("datapoint"): | ||
| new_bboxes = bboxes + 3 | ||
| assert isinstance(new_bboxes, datapoints.BoundingBoxes) | ||
|
|
||
| # %% | ||
| # Why is this happening? | ||
| # ^^^^^^^^^^^^^^^^^^^^^^ | ||
| # | ||
| # .. note:: | ||
| # **For performance reasons**. :class:`~torchvision.datapoints.Datapoint` | ||
| # classes are Tensor subclasses, so any operation involving a | ||
| # :class:`~torchvision.datapoints.Datapoint` object will go through the | ||
| # `__torch_function__ | ||
| # <https://pytorch.org/docs/stable/notes/extending.html#extending-torch>`_ | ||
| # protocol. This induces a small overhead, which we want to avoid when possible. | ||
| # This doesn't matter for builtin ``torchvision`` transforms because we can | ||
NicolasHug marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| # avoid the overhead there, but it could be a problem in your model's | ||
| # ``forward``. | ||
| # | ||
| # You never need to re-wrap manually if you're using the built-in transforms | ||
| # or their functional equivalents: this is automatically taken care of for | ||
| # you. | ||
| # **The alternative isn't much better anyway.** For every operation where | ||
| # preserving the :class:`~torchvision.datapoints.Datapoint` type makes | ||
| # sense, there are just as many operations where returning a pure Tensor is | ||
| # preferable: is ``img.sum()`` still an :class:`~torchvision.datapoints.Image`? | ||
NicolasHug marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| # If we were to preserve :class:`~torchvision.datapoints.Datapoint` types all | ||
| # the way, even your logits or the output of your loss function would end up | ||
NicolasHug marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| # being of type :class:`~torchvision.datapoints.Image`, and surely that's not | ||
| # desirable. | ||
| # | ||
| # .. note:: | ||
| # | ||
| # This "unwrapping" behaviour is something we're actively seeking feedback on. If you find this surprising or if you | ||
| # This behaviour is something we're actively seeking feedback on. If you find this surprising or if you | ||
| # have any suggestions on how to better support your use-cases, please reach out to us via this issue: | ||
| # https://github.com/pytorch/vision/issues/7319 | ||
| # | ||
| # Exceptions | ||
| # ^^^^^^^^^^ | ||
| # | ||
| # There are a few exceptions to this "unwrapping" rule: | ||
| # | ||
| # 1. Operations like :meth:`~torch.Tensor.clone`, :meth:`~torch.Tensor.to`, | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.