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

[BC-breaking] Introduced InterpolationModes and deprecated arguments: resample and fillcolor #2952

Merged
merged 16 commits into from
Nov 27, 2020

Conversation

vfdev-5
Copy link
Collaborator

@vfdev-5 vfdev-5 commented Nov 3, 2020

Related to #2479

  • Introduced InterpolationModes
  • Deprecated arguments: resample and fillcolor
  • Replaced by interpolation and fill

Context:

  1. fill is mainly used: 4 times in transforms and 3 times in functional vs fillcolor is used 2 times in transforms and functional (RandomAffine and F.affine) => we can decide to replace fillcolor by fill and set a warning about argument deprecation.

  2. interpolation is used 6 times in transforms/functional vs resample is used 4 times in transforms/functional => we can similarly decide to replace resample by interpolation and set a warning about argument deprecation.

Replaced by interpolation and fill
@codecov
Copy link

codecov bot commented Nov 3, 2020

Codecov Report

Merging #2952 (453722c) into master (74de51d) will increase coverage by 1.30%.
The diff coverage is 91.83%.

Impacted file tree graph

@@            Coverage Diff             @@
##           master    #2952      +/-   ##
==========================================
+ Coverage   72.18%   73.49%   +1.30%     
==========================================
  Files          99       99              
  Lines        8806     8832      +26     
  Branches     1383     1397      +14     
==========================================
+ Hits         6357     6491     +134     
+ Misses       2012     1916      -96     
+ Partials      437      425      -12     
Impacted Files Coverage Δ
torchvision/transforms/functional_tensor.py 74.14% <75.00%> (+0.47%) ⬆️
torchvision/transforms/transforms.py 80.83% <91.30%> (-1.75%) ⬇️
torchvision/transforms/functional.py 80.92% <100.00%> (+0.47%) ⬆️
torchvision/transforms/functional_pil.py 68.07% <100.00%> (ø)
torchvision/ops/feature_pyramid_network.py 91.20% <0.00%> (-3.30%) ⬇️
torchvision/models/detection/anchor_utils.py 92.10% <0.00%> (-2.70%) ⬇️
torchvision/ops/deform_conv.py 70.96% <0.00%> (-1.34%) ⬇️
torchvision/models/detection/backbone_utils.py 94.28% <0.00%> (-1.27%) ⬇️
torchvision/models/densenet.py 82.81% <0.00%> (-0.77%) ⬇️
... and 17 more

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 74de51d...ed1b509. Read the comment docs.

Copy link
Contributor

@datumbox datumbox left a comment

Choose a reason for hiding this comment

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

@vfdev-5 Thanks for the PR.

I added one suggestion to improve BC during the deprecation period and marked all the places where this could happen. Nevertheless, if our policy is typically to only throw warnings feel free to ignore.

Also I noticed that in some methods you throw warnings while in others you directly replace the names. I assume that this is because the first are considered public API while the latter not. If that's true, then all good.

torchvision/transforms/functional.py Outdated Show resolved Hide resolved
torchvision/transforms/functional.py Outdated Show resolved Hide resolved
torchvision/transforms/transforms.py Outdated Show resolved Hide resolved
torchvision/transforms/transforms.py Outdated Show resolved Hide resolved
Copy link
Collaborator Author

@vfdev-5 vfdev-5 left a comment

Choose a reason for hiding this comment

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

Thanks for the review @datumbox

I added one suggestion to improve BC during the deprecation period and marked all the places where this could happen. Nevertheless, if our policy is typically to only throw warnings feel free to ignore.

I agree that it is a good practice to provide until when the argument will remain in the API. I'd say by default, it can be 2 future minor releases, until 0.10.0. @fmassa any thoughts?

torchvision/transforms/functional.py Outdated Show resolved Hide resolved
torchvision/transforms/transforms.py Outdated Show resolved Hide resolved
Copy link
Contributor

@datumbox datumbox left a comment

Choose a reason for hiding this comment

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

Thanks for the updates @vfdev-5, your last changes look great.

@fmassa Are you OK to merge?

Copy link
Member

@fmassa fmassa left a comment

Choose a reason for hiding this comment

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

Thanks for the PR @vfdev-5 !

I have one comment regarding the warning message, but it is not blocking for merge.

On a separate note that I would like to discuss here:

When was planning for the Tensor support for transforms, I started to wonder if we should move away from the interpolate=0 enums from PIL (= Image.NEAREST etc), and instead use a more descriptive argument which could work even without the knowledge of PIL.

Two options came to my mind:

  • replace interpolate : int with mode : str as we have in torch.nn.functional.interpolate
  • provide our own Enum for the interpolation mode in torchvision (and hope it works on torchscript)

Thoughts?


Returns:
PIL Image or Tensor: Transformed image.
"""
if resample is not None:
warnings.warn(
"Argument resample is deprecated and will be removed since v0.10.0. Please, use interpolation instead"
Copy link
Member

@fmassa fmassa Nov 5, 2020

Choose a reason for hiding this comment

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

nit: I'm not a native English speaker, but I feel like since might not be the best word here. I would have said instead

Suggested change
"Argument resample is deprecated and will be removed since v0.10.0. Please, use interpolation instead"
"Argument resample is deprecated and will be removed in v0.10.0. Please, use interpolation instead"

This is a minor nit (which applies to the other messages as well), so I'm not considering this as a merge-blocking issue.

@vfdev-5
Copy link
Collaborator Author

vfdev-5 commented Nov 5, 2020

If we would like to use an enum for interpolate, there can be two potential problems with torchscript:

import torch
from enum import Enum

class Modes:
    NEAREST = 0
    BILINEAR = 1

def func(x: torch.Tensor, mode: Modes) -> torch.Tensor:
    if mode == Modes.NEAREST:
        return x + 1
    elif mode == Modes.BILINEAR:
        return x + 2
    else:
        return x

    
y = func(torch.rand(3, 4), Modes.NEAREST)
s_func = torch.jit.script(func)
  1. if this code is launched inside jupyter gives an error:
/opt/conda/lib/python3.7/site-packages/torch/_utils_internal.py in get_source_lines_and_file(obj, error_msg)
     46     filename = None  # in case getsourcefile throws
     47     try:
---> 48         filename = inspect.getsourcefile(obj)
     49         sourcelines, file_lineno = inspect.getsourcelines(obj)
     50     except OSError as e:

/opt/conda/lib/python3.7/inspect.py in getsourcefile(object)
    682     Return None if no way can be identified to get the source.
    683     """
--> 684     filename = getfile(object)
    685     all_bytecode_suffixes = importlib.machinery.DEBUG_BYTECODE_SUFFIXES[:]
    686     all_bytecode_suffixes += importlib.machinery.OPTIMIZED_BYTECODE_SUFFIXES[:]

/opt/conda/lib/python3.7/inspect.py in getfile(object)
    651             if getattr(module, '__file__', None):
    652                 return module.__file__
--> 653         raise TypeError('{!r} is a built-in class'.format(object))
    654     if ismethod(object):
    655         object = object.__func__

TypeError: <class '__main__.Modes'> is a built-in class
  1. if this code is launched as a script with if __name__ == "__main__": close, it gives another error:
Traceback (most recent call last):
  File "torchscript_enum.py", line 22, in <module>
    s_func = torch.jit.script(func)
  File "/opt/conda/lib/python3.7/site-packages/torch/jit/_script.py", line 940, in script
    qualified_name, ast, _rcb, get_default_args(obj)
RuntimeError: 
python value of type 'str' cannot be used as a value. Perhaps it is a closed over global variable? If so, please consider passing it in as an argument or use a local varible instead.:
  File "torchscript_enum.py", line 11
def func(x: torch.Tensor, mode: Modes) -> torch.Tensor:
    if mode == Modes.NEAREST:
               ~~~~~~~~~~~~~ <--- HERE
        return x + 1
    elif mode == Modes.BILINEAR:

@vfdev-5
Copy link
Collaborator Author

vfdev-5 commented Nov 5, 2020

However, the following works inside the script file

import torch
from enum import Enum

class Modes(Enum):
    NEAREST = 0
    BILINEAR = 1


def func(x: torch.Tensor, mode: Modes) -> torch.Tensor:
    if mode == Modes.NEAREST:
        return x + 1
    elif mode == Modes.BILINEAR:
        return x + 2
    else:
        return x

if __name__ == "__main__":
    y = func(torch.rand(3, 4), Modes.NEAREST)
    s_func = torch.jit.script(func)
    y = s_func(torch.rand(3, 4), Modes.NEAREST)

According to pytorch/pytorch#42963

EDIT: removed global Modes

@fmassa
Copy link
Member

fmassa commented Nov 5, 2020

It's great that we can use Enum's with torchscript, but it's weird that we would need to have it set as a global beforehand.
cc @gmagogsfm is this expected?

@vfdev-5
Copy link
Collaborator Author

vfdev-5 commented Nov 5, 2020

Sorry, seems like global keyword can be omitted if used inside a script file.

@vfdev-5 vfdev-5 changed the title Deprecated arguments: resample and fillcolor Introduced InterpolationModes and deprecated arguments: resample and fillcolor Nov 16, 2020
@vfdev-5 vfdev-5 requested review from datumbox and fmassa November 16, 2020 16:25
@vfdev-5 vfdev-5 changed the title Introduced InterpolationModes and deprecated arguments: resample and fillcolor [BC-breaking] Introduced InterpolationModes and deprecated arguments: resample and fillcolor Nov 17, 2020
Copy link
Contributor

@datumbox datumbox left a comment

Choose a reason for hiding this comment

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

The PR looks good. Thanks a lot for the changes, they look great.

I understand that it's a design decision to maintain BC on the high-level transforms.py but not with the lower-level functional implementations, correct? Also, I noticed that on the backend implementations you use raw values for default (ints or strings) instead of their enums. Is this because of a JIT limitation?

@vfdev-5
Copy link
Collaborator Author

vfdev-5 commented Nov 17, 2020

I understand that it's a design decision to maintain BC on the high-level transforms.py but not with the lower-level functional implementations, correct?

BC change is "required" to switch from PIL.Image resampling mode. Almost no change in lower-level functional implementations is a sort of minimal change design.

Also, I noticed that on the backend implementations you use raw values for default (ints or strings) instead of their enums. Is this because of a JIT limitation?

We can certainly find a way to reuse InterpolationModes inside private modules. As I said this is currently blocked by cyclic imports due to where InterpolationModes is defined. Remap from InterpolationModes to PIL modes happens inside F for each method. Remap from InterpolationModes to string values for torch functions is done with InterpolationModes.value attribute.

Copy link
Member

@fmassa fmassa left a comment

Choose a reason for hiding this comment

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

Correct me if I'm wrong, but I think the BC-breaking change that is introduced in here will break all user code that uses the transforms and I if that's the case I'm not sure this is something we can do in torchvision.

if not isinstance(img, torch.Tensor):
return F_pil.resize(img, size=size, interpolation=interpolation)
pil_interpolation = pil_modes_mapping[interpolation]
Copy link
Member

Choose a reason for hiding this comment

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

Interesting that accessing this as a global works with torchscript. I suppose torchscript can compile this branch out and then we don't have an error, but I would expect this to fail if that wasn't the case

torchvision/transforms/functional.py Show resolved Hide resolved
@vfdev-5 vfdev-5 requested a review from fmassa November 20, 2020 14:15
Copy link
Member

@fmassa fmassa left a comment

Choose a reason for hiding this comment

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

Thanks a lot!

I'm merging the PR now to unblock, but I have one last comment that I would like us to check: should it be InterpolationMode or InterpolationModes?

cc @vfdev-5 @datumbox for thoughts


Returns:
PIL Image or Tensor: Rotated image.

.. _filters: https://pillow.readthedocs.io/en/latest/handbook/concepts.html#filters

"""
if resample is not None:
warnings.warn(
"Argument resample is deprecated and will be removed since v0.10.0. Please, use interpolation instead"
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
"Argument resample is deprecated and will be removed since v0.10.0. Please, use interpolation instead"
"Argument resample is deprecated and will be removed in v0.10.0. Please, use interpolation instead"

@fmassa fmassa merged commit 0c44513 into pytorch:master Nov 27, 2020
@datumbox
Copy link
Contributor

@fmassa I think enums are typically singular. Aka Color.Blue not Colors.Blue.

On a similar enum, I used ImageReadMode.

@vfdev-5
Copy link
Collaborator Author

vfdev-5 commented Nov 27, 2020

@fmassa @datumbox thanks for pointing out that. I agree that I can rename InterpolationModes to InterpolationMode.

@vfdev-5 vfdev-5 deleted the vfdev-5/deprecate-resample-fillcolor branch November 27, 2020 16:36
vfdev-5 added a commit to Quansight/vision that referenced this pull request Dec 4, 2020
… resample and fillcolor (pytorch#2952)

* Deprecated arguments: resample and fillcolor
Replaced by interpolation and fill

* Updates according to the review

* Added tests to check warnings and asserted BC

* [WIP] Interpolation modes

* Added InterpolationModes enum

* Added supported for int values for interpolation for BC

* Removed useless test code

* Fix flake8
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.

4 participants