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

simplify model builders #5001

Merged
merged 36 commits into from
Dec 7, 2021
Merged

Conversation

pmeier
Copy link
Collaborator

@pmeier pmeier commented Nov 29, 2021

Addresses #4948.

This PR adds two decorators that help reducing verbose and duplicated code in the prototype model builders:

  1. @handle_legacy_interface This decorator does two things:
    1. Turn positional into keyword arguments and warn that positional is deprecated.
    2. Perform the conversion between pretrained and weights and warn that pretrained is deprecated.
  2. @handle_num_categories_mismatch This decorator will raise an error if num_classes is passed, but doesn't match the number of categories of the pretrained weights.

Examples:

from torchvision.prototype import models

models.alexnet(True, False)
UserWarning: Using 'pretrained', and 'progress' as positional parameter(s) is deprecated. Please use them as keyword parameter(s) instead.
UserWarning: The parameter 'pretrained' is deprecated, please use 'weights' instead.
models.detection.fasterrcnn_resnet50_fpn(True, False, 0, True)
UserWarning: Using 'pretrained', 'progress', 'num_classes', and 'pretrained_backbone' as positional parameter(s) is deprecated. Please use them as keyword parameter(s) instead.
UserWarning: The parameter 'pretrained' is deprecated, please use 'weights' instead.
UserWarning: The parameter 'pretrained_backbone' is deprecated, please use 'weights_backbone' instead.
ValueError: The number of categories of the weights does not match the `num_classes` argument: 91 != 0.

cc @datumbox @bjuncek

@facebook-github-bot
Copy link

facebook-github-bot commented Nov 29, 2021

💊 CI failures summary and remediations

As of commit bc358bc (more details on the Dr. CI page):


  • 1/1 failures introduced in this PR

🕵️ 1 new failure recognized by patterns

The following CI failures do not appear to be due to upstream breakages:

See CircleCI build unittest_linux_cpu_py3.6 (1/1)

Step: "Run tests" (full log | diagnosis details | 🔁 rerun)

/root/project/torchvision/io/video.py:399: Runt...log: [mov,mp4,m4a,3gp,3g2,mj2] moov atom not found

test/test_image.py::test_encode_jpeg[grace_hopper_517x606.jpg]
  /root/project/test/test_image.py:493: UserWarning: The given buffer is not writable, and PyTorch does not support non-writable tensors. This means you can write to the underlying (supposedly non-writable) buffer using the tensor. You may want to copy the buffer to protect its data or make it writable before converting it to a tensor. This type of warning will be suppressed for the rest of this program. (Triggered internally at  /opt/conda/conda-bld/pytorch_1638778025563/work/torch/csrc/utils/tensor_new.cpp:998.)
    encoded_jpeg_pil = torch.frombuffer(buf.getvalue(), dtype=torch.uint8)

test/test_internet.py::TestDatasetUtils::test_download_url_retry_http
  /root/project/env/lib/python3.6/urllib/request.py:522: ResourceWarning: unclosed <ssl.SSLSocket [closed] fd=13, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=6>
    for processor in self.process_request.get(protocol, []):

test/test_io.py::TestVideo::test_read_video_timestamps_corrupted_file
  /root/project/torchvision/io/video.py:399: RuntimeWarning: Failed to open container for /tmp/tmprdj4u5v7.mp4; Caught error: [Errno 1094995529] Invalid data found when processing input: '/tmp/tmprdj4u5v7.mp4'; last error log: [mov,mp4,m4a,3gp,3g2,mj2] moov atom not found
    warnings.warn(msg, RuntimeWarning)

test/test_models.py::test_memory_efficient_densenet[densenet121]
test/test_models.py::test_memory_efficient_densenet[densenet169]
test/test_models.py::test_memory_efficient_densenet[densenet201]
test/test_models.py::test_memory_efficient_densenet[densenet161]
  /root/project/env/lib/python3.6/site-packages/torch/autocast_mode.py:162: UserWarning: User provided device_type of 'cuda', but CUDA is not available. Disabling
    warnings.warn('User provided device_type of \'cuda\', but CUDA is not available. Disabling')

test/test_models.py::test_inception_v3_eval

This comment was automatically generated by Dr. CI (expand for details).

Please report bugs/suggestions to the (internal) Dr. CI Users group.

Click here to manually regenerate this comment.

@NicolasHug
Copy link
Member

Turn positional into keyword arguments and warn that positional is deprecated.

I think this is great and this is something we have discussed with @datumbox already, but I would prefer waiting a bit before doing it here: I'd like this to be a more pervasive change throughout torchvision, not just something specific to the models. Also, I'd like us to have a clearer deprecation policy, i.e. decide when we actually remove stuff. I want to get this done before then next release anyway, likely in January (release is planned for late Feb I think)

Also, this is only tangentially related to this PR, so feel free not to address it here: it'd be great if we could advertise the new API in the deprecation message, and also help users with the transition. So ideally, the message could be something like

The pretrained parameter is deprecated, please use the weights parameter instead. The current behaviour is equivalent to passing weights=ResnetWeights.Blahblah. You can also set weights="default" to get the most up-to-date weights.

@pmeier
Copy link
Collaborator Author

pmeier commented Nov 30, 2021

I'd like this to be a more pervasive change throughout torchvision, not just something specific to the models.

I can turn the positional to keyword only handling into a general decorator if you want. That way we can move forward with the model builders by using said decorator and handle all other cases later by simply using it.

Also, I'd like us to have a clearer deprecation policy, i.e. decide when we actually remove stuff.

In PyTorch core the "regular" policy is to deprecate for one release and unless there is major pushback remove it the next release.

I want to get this done before then next release anyway, likely in January (release is planned for late Feb I think)

Tentative release date is 04.03.2022.

Also, this is only tangentially related to this PR, so feel free not to address it here: it'd be great if we could advertise the new API in the deprecation message, and also help users with the transition. So ideally, the message could be something like

The pretrained parameter is deprecated, please use the weights parameter instead. The current behaviour is equivalent to passing weights=ResnetWeights.Blahblah. You can also set weights="default" to get the most up-to-date weights.

@datumbox What would a good message look like? Please use $FOO or whatever to indicate which parts need to be parametrized.

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.

@pmeier I love the direction of this. I've added a few comments below, please have a look. Note that there is a final refactoring PR that is going to affect you at #5006. Hopefully we will merge it later today and avoid conflicts.

I would prefer waiting a bit before doing it here: I'd like this to be a more pervasive change throughout torchvision, not just something specific to the models.

I agree we should roll this out in the main area in a coordinated manner. Concerning the prototype area, I would be open adopting it early to avoid introducing changes over and over on the API. The Datasets API already uses it, so it makes sense to have it here as well. Thoughts?

I can turn the positional to keyword only handling into a general decorator if you want. That way we can move forward with the model builders by using said decorator and handle all other cases later by simply using it.

Sounds like a good idea. I'll love to see the details.

What would a good message look like?

I think the message provided by @NicolasHug looks great. The words pretrained, weights and ResnetWeights.Blahblah are the parameterized parts, which you already handle.

torchvision/prototype/models/_utils.py Outdated Show resolved Hide resolved
torchvision/prototype/models/alexnet.py Outdated Show resolved Hide resolved
torchvision/prototype/models/detection/faster_rcnn.py Outdated Show resolved Hide resolved
torchvision/prototype/models/detection/faster_rcnn.py Outdated Show resolved Hide resolved
torchvision/prototype/models/detection/faster_rcnn.py Outdated Show resolved Hide resolved
torchvision/prototype/models/quantization/shufflenetv2.py Outdated Show resolved Hide resolved
@NicolasHug
Copy link
Member

NicolasHug commented Nov 30, 2021

I agree we should roll this out in the main area in a coordinated manner. Concerning the prototype area, I would be open adopting it early to avoid introducing changes over and over on the API. The Datasets API already uses it, so it makes sense to have it here as well. Thoughts?

The new datasets make use of the positional argument, which is perfectly fine since they're new classes. But here we're deprecating exising functions and existing usage - I would prefer to do that in a few weeks when we have a good idea of what we want the deprecation process will look like.

@NicolasHug
Copy link
Member

NicolasHug commented Nov 30, 2021

We had a chat with @datumbox .

I'm fine with introducing the keyword-only deprecation here. That means that we need to get to an agreement regarding the keyword deprecations for the rest of the code base before we move the new models from prototypes to main. If we can't reach that point before the next release (unlikely, but possible), we would have to remove the deprecations.

torchvision/prototype/utils/_internal.py Outdated Show resolved Hide resolved
torchvision/prototype/utils/_internal.py Outdated Show resolved Hide resolved
@datumbox
Copy link
Contributor

If we can't reach that point before the next release (unlikely, but possible), we would have to remove the deprecations.

Agreed. I've captured this point step 1 of the release tasks at #4679

@pmeier pmeier marked this pull request as ready for review November 30, 2021 18:44
@pmeier
Copy link
Collaborator Author

pmeier commented Nov 30, 2021

The warnings now look as follows:

  • alexnet(True)
    UserWarning: Using 'weights' as positional parameter(s) is deprecated. Please use keyword parameter(s) instead.
    UserWarning: The current behavior is equivalent to passing `weights=AlexNet_Weights.ImageNet1K_V1`. You can also use `weights='default'` to get the most up-to-date weights.
    
  • alexnet(False)
    UserWarning: Using 'weights' as positional parameter(s) is deprecated. Please use keyword parameter(s) instead.
    UserWarning: The current behavior is equivalent to passing `weights=None`.
    
  • alexnet(pretrained=True)
    UserWarning: The parameter 'pretrained' is deprecated, please use 'weights' instead. The current behavior is equivalent to passing `weights=AlexNet_Weights.ImageNet1K_V1`. You can also use `weights='default'` to get the most up-to-date weights.
    
  • alexnet(pretrained=False)
    UserWarning: The parameter 'pretrained' is deprecated, please use 'weights' instead. The current behavior is equivalent to passing `weights=None`.
    

Happy with them?

@pmeier pmeier requested a review from NicolasHug November 30, 2021 18:46
@datumbox
Copy link
Contributor

datumbox commented Dec 6, 2021

I reviewed the proposed solution and looks great to me. I think we can implement the proposal on all model builders.

@pmeier pmeier requested a review from datumbox December 6, 2021 13:50
weights: Optional[DeepLabV3_ResNet50_Weights] = None,
progress: bool = True,
num_classes: Optional[int] = None,
aux_loss: Optional[bool] = None,
weights_backbone: Optional[ResNet50_Weights] = None,
**kwargs: Any,
Copy link
Contributor

Choose a reason for hiding this comment

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

This changes the signature of the method. Though a corner case, it means that now if someone passed an extra parameter as argument it won't be ignored but instead they will get an exception. Note that kwargs is currently supported by all model builders so I suggest leaving it in place.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Though a corner case, it means that now if someone passed an extra parameter as argument it won't be ignored but instead they will get an exception.

That is kind of the point. The builder silently ignores wrong keyword arguments. Imagine you made a typo

deeplabv3_resnet50(weight=DeepLabV3_ResNet50_Weights.CocoWithVocLabels_V1)

and instead of loading some weights, you get a randomly initialized model instead. I don't think this is expected neither a good thing to have. At the very least, we should emit a warning that there were unused keyword arguments.

Note that kwargs is currently supported by all model builders so I suggest leaving it in place.

There are places where this is useful. For example the **kwargs of VGG variants like

def vgg11(weights: Optional[VGG11_Weights] = None, progress: bool = True, **kwargs: Any) -> VGG:
if type(weights) == bool and weights:
_deprecated_positional(kwargs, "pretrained", "weights", True)
if "pretrained" in kwargs:
weights = _deprecated_param(kwargs, "pretrained", "weights", VGG11_Weights.ImageNet1K_V1)
weights = VGG11_Weights.verify(weights)
return _vgg("A", False, weights, progress, **kwargs)

will ultimately be resolved in

class VGG(nn.Module):
def __init__(
self, features: nn.Module, num_classes: int = 1000, init_weights: bool = True, dropout: float = 0.5
) -> None:

So if there is any unknown keyword argument, the class instantiation would fail.

Copy link
Contributor

Choose a reason for hiding this comment

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

@pmeier I understand and I agree with many points you are raising here. My concern is that this is not the right PR to fix this. Fixing it here only resolves the problem for 2 models, leaving the rest affected. Shall we take this on a separate issue?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Fair enough 👍

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.

@pmeier LGTM, thanks for the major readability improvement. The code looks much much better now.

I've pushed 3 commits, 1 for a missing verify call and 2 for kwargs. If you are OK with it, feel free to merge on green CI. Else revert and let's chat.

@datumbox datumbox linked an issue Dec 6, 2021 that may be closed by this pull request
5 tasks
@datumbox datumbox merged commit 588e9b5 into pytorch:main Dec 7, 2021
@pmeier pmeier deleted the prototype-model-cleanup branch December 7, 2021 13:38
facebook-github-bot pushed a commit that referenced this pull request Dec 9, 2021
Summary:
* simplify model builders

* cleanup

* refactor kwonly to pos or kw handling

* put weight verification back

* revert num categories checks

* fix default weights

* cleanup

* remove manual parameter map

* refactor decorator interface

* address review comments

* cleanup

* refactor callable default

* fix type annotation

* process ungrouped models

* cleanup

* mroe cleanup

* use decorator for detection models

* add decorator for quantization models

* add decorator for segmentation  models

* add decorator for video  models

* remove old helpers

* fix resnet50

* Adding verification back on InceptionV3

* Add kwargs in DeeplabeV3

* Add kwargs on FCN

* Fix typing on Deeplab

* Fix typing on FCN

Reviewed By: NicolasHug

Differential Revision: D32950943

fbshipit-source-id: c2a5c21e48b7e6fffcbba2e1ee7ab9dd7dc4a306

Co-authored-by: Vasilis Vryniotis <[email protected]>
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.

Multi pretrained weights: Cleanups and Refactoring
4 participants