From 053e7ebd1b50b7a506cfd6e2389043ec05414b1c Mon Sep 17 00:00:00 2001 From: Philip Meier Date: Wed, 16 Mar 2022 10:16:17 +0100 Subject: [PATCH 1/4] port Pad to prototype transforms (#5621) * port Pad to prototype transforms * use literal --- test/test_prototype_transforms.py | 1 + torchvision/prototype/transforms/__init__.py | 1 + torchvision/prototype/transforms/_geometry.py | 91 +++++++++++++------ 3 files changed, 64 insertions(+), 29 deletions(-) diff --git a/test/test_prototype_transforms.py b/test/test_prototype_transforms.py index 5b0693a2e78..b6085bb1c71 100644 --- a/test/test_prototype_transforms.py +++ b/test/test_prototype_transforms.py @@ -71,6 +71,7 @@ class TestSmoke: transforms.CenterCrop([16, 16]), transforms.ConvertImageDtype(), transforms.RandomHorizontalFlip(), + transforms.Pad(5), ) def test_common(self, transform, input): transform(input) diff --git a/torchvision/prototype/transforms/__init__.py b/torchvision/prototype/transforms/__init__.py index 0a3d23db3bd..1cb53f2a885 100644 --- a/torchvision/prototype/transforms/__init__.py +++ b/torchvision/prototype/transforms/__init__.py @@ -15,6 +15,7 @@ TenCrop, BatchMultiCrop, RandomHorizontalFlip, + Pad, RandomZoomOut, ) from ._meta import ConvertBoundingBoxFormat, ConvertImageDtype, ConvertImageColorSpace diff --git a/torchvision/prototype/transforms/_geometry.py b/torchvision/prototype/transforms/_geometry.py index 19e5ced791e..061f12cd446 100644 --- a/torchvision/prototype/transforms/_geometry.py +++ b/torchvision/prototype/transforms/_geometry.py @@ -1,5 +1,6 @@ import collections.abc import math +import numbers import warnings from typing import Any, Dict, List, Union, Sequence, Tuple, cast @@ -9,6 +10,7 @@ from torchvision.prototype.transforms import Transform, InterpolationMode, functional as F from torchvision.transforms.functional import pil_to_tensor from torchvision.transforms.transforms import _setup_size, _interpolation_modes_from_int +from typing_extensions import Literal from ._utils import query_image, get_image_dimensions, has_any, is_simple_tensor @@ -272,42 +274,31 @@ def apply_recursively(obj: Any) -> Any: return apply_recursively(inputs if len(inputs) > 1 else inputs[0]) -class RandomZoomOut(Transform): +class Pad(Transform): def __init__( - self, fill: Union[float, Sequence[float]] = 0.0, side_range: Tuple[float, float] = (1.0, 4.0), p: float = 0.5 + self, + padding: Union[int, Sequence[int]], + fill: Union[float, Sequence[float]] = 0.0, + padding_mode: Literal["constant", "edge", "reflect", "symmetric"] = "constant", ) -> None: super().__init__() + if not isinstance(padding, (numbers.Number, tuple, list)): + raise TypeError("Got inappropriate padding arg") - if fill is None: - fill = 0.0 - self.fill = fill - - self.side_range = side_range - if side_range[0] < 1.0 or side_range[0] > side_range[1]: - raise ValueError(f"Invalid canvas side range provided {side_range}.") - - self.p = p - - def _get_params(self, sample: Any) -> Dict[str, Any]: - image = query_image(sample) - orig_c, orig_h, orig_w = get_image_dimensions(image) - - r = self.side_range[0] + torch.rand(1) * (self.side_range[1] - self.side_range[0]) - canvas_width = int(orig_w * r) - canvas_height = int(orig_h * r) + if not isinstance(fill, (numbers.Number, str, tuple, list)): + raise TypeError("Got inappropriate fill arg") - r = torch.rand(2) - left = int((canvas_width - orig_w) * r[0]) - top = int((canvas_height - orig_h) * r[1]) - right = canvas_width - (left + orig_w) - bottom = canvas_height - (top + orig_h) - padding = [left, top, right, bottom] + if padding_mode not in ["constant", "edge", "reflect", "symmetric"]: + raise ValueError("Padding mode should be either constant, edge, reflect or symmetric") - fill = self.fill - if not isinstance(fill, collections.abc.Sequence): - fill = [fill] * orig_c + if isinstance(padding, Sequence) and len(padding) not in [1, 2, 4]: + raise ValueError( + f"Padding must be an int or a 1, 2, or 4 element tuple, not a {len(padding)} element tuple" + ) - return dict(padding=padding, fill=fill) + self.padding = padding + self.fill = fill + self.padding_mode = padding_mode def _transform(self, input: Any, params: Dict[str, Any]) -> Any: if isinstance(input, features.Image) or is_simple_tensor(input): @@ -349,6 +340,48 @@ def _transform(self, input: Any, params: Dict[str, Any]) -> Any: else: return input + +class RandomZoomOut(Transform): + def __init__( + self, fill: Union[float, Sequence[float]] = 0.0, side_range: Tuple[float, float] = (1.0, 4.0), p: float = 0.5 + ) -> None: + super().__init__() + + if fill is None: + fill = 0.0 + self.fill = fill + + self.side_range = side_range + if side_range[0] < 1.0 or side_range[0] > side_range[1]: + raise ValueError(f"Invalid canvas side range provided {side_range}.") + + self.p = p + + def _get_params(self, sample: Any) -> Dict[str, Any]: + image = query_image(sample) + orig_c, orig_h, orig_w = get_image_dimensions(image) + + r = self.side_range[0] + torch.rand(1) * (self.side_range[1] - self.side_range[0]) + canvas_width = int(orig_w * r) + canvas_height = int(orig_h * r) + + r = torch.rand(2) + left = int((canvas_width - orig_w) * r[0]) + top = int((canvas_height - orig_h) * r[1]) + right = canvas_width - (left + orig_w) + bottom = canvas_height - (top + orig_h) + padding = [left, top, right, bottom] + + fill = self.fill + if not isinstance(fill, collections.abc.Sequence): + fill = [fill] * orig_c + + return dict(padding=padding, fill=fill) + + def _transform(self, input: Any, params: Dict[str, Any]) -> Any: + transform = Pad(**params, padding_mode="constant") + return transform(input) + def forward(self, *inputs: Any) -> Any: sample = inputs if len(inputs) > 1 else inputs[0] if torch.rand(1) >= self.p: From 9edd22c8a07a8c99324a73ec4dd6c553e2c8d410 Mon Sep 17 00:00:00 2001 From: Anton Thomma <11010310+thommaa@users.noreply.github.com> Date: Wed, 16 Mar 2022 23:33:45 +1300 Subject: [PATCH 2/4] Bump up LibTorchvision version number for Podspec to release Cocoapods (#5624) Co-authored-by: Anton Thomma Co-authored-by: Vasilis Vryniotis --- ios/LibTorchvision.podspec | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ios/LibTorchvision.podspec b/ios/LibTorchvision.podspec index 2260bc5fcfc..3e760b77edd 100644 --- a/ios/LibTorchvision.podspec +++ b/ios/LibTorchvision.podspec @@ -1,8 +1,8 @@ -pytorch_version = '1.10.0' +pytorch_version = '1.11.0' Pod::Spec.new do |s| s.name = 'LibTorchvision' - s.version = '0.11.1' + s.version = '0.12.0' s.authors = 'PyTorch Team' s.license = { :type => 'BSD' } s.homepage = 'https://github.com/pytorch/vision' From 600a3f240a742bee3018b8d36e35ff139dd1b779 Mon Sep 17 00:00:00 2001 From: Philip Meier Date: Wed, 16 Mar 2022 12:39:12 +0100 Subject: [PATCH 3/4] pre-download model weights in CI docs build (#5625) * pre-download model weights in CI docs build * move changes into template * change docs image --- .circleci/config.yml | 33 ++++++++++++++++++++++++--------- .circleci/config.yml.in | 33 ++++++++++++++++++++++++--------- scripts/collect_model_urls.py | 18 ++++++++---------- 3 files changed, 56 insertions(+), 28 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 3de0894304b..c68f39642ca 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -174,6 +174,26 @@ commands: - store_test_results: path: test-results + download_model_weights: + parameters: + extract_roots: + type: string + default: "torchvision/models" + background: + type: boolean + default: true + steps: + - apt_install: + args: parallel wget + descr: Install download utilitites + - run: + name: Download model weights + background: << parameters.background >> + command: | + mkdir -p ~/.cache/torch/hub/checkpoints + python scripts/collect_model_urls.py << parameters.extract_roots >> \ + | parallel -j0 'wget --no-verbose -O ~/.cache/torch/hub/checkpoints/`basename {}` {}\?source=ci' + binary_common: &binary_common parameters: # Edit these defaults to do a release @@ -340,14 +360,8 @@ jobs: resource_class: xlarge steps: - checkout - - run: - name: Download model weights - background: true - command: | - sudo apt update -qy && sudo apt install -qy parallel wget - mkdir -p ~/.cache/torch/hub/checkpoints - python scripts/collect_model_urls.py torchvision/prototype/models \ - | parallel -j0 'wget --no-verbose -O ~/.cache/torch/hub/checkpoints/`basename {}` {}\?source=ci' + - download_model_weights: + extract_roots: torchvision/prototype/models - install_torchvision - install_prototype_dependencies - pip_install: @@ -1011,12 +1025,13 @@ jobs: build_docs: <<: *binary_common docker: - - image: "pytorch/manylinux-cuda100" + - image: circleci/python:3.7 resource_class: 2xlarge+ steps: - attach_workspace: at: ~/workspace - checkout + - download_model_weights - run: name: Setup command: .circleci/unittest/linux/scripts/setup_env.sh diff --git a/.circleci/config.yml.in b/.circleci/config.yml.in index e36b368db1c..731d0133528 100644 --- a/.circleci/config.yml.in +++ b/.circleci/config.yml.in @@ -174,6 +174,26 @@ commands: - store_test_results: path: test-results + download_model_weights: + parameters: + extract_roots: + type: string + default: "torchvision/models" + background: + type: boolean + default: true + steps: + - apt_install: + args: parallel wget + descr: Install download utilitites + - run: + name: Download model weights + background: << parameters.background >> + command: | + mkdir -p ~/.cache/torch/hub/checkpoints + python scripts/collect_model_urls.py << parameters.extract_roots >> \ + | parallel -j0 'wget --no-verbose -O ~/.cache/torch/hub/checkpoints/`basename {}` {}\?source=ci' + binary_common: &binary_common parameters: # Edit these defaults to do a release @@ -340,14 +360,8 @@ jobs: resource_class: xlarge steps: - checkout - - run: - name: Download model weights - background: true - command: | - sudo apt update -qy && sudo apt install -qy parallel wget - mkdir -p ~/.cache/torch/hub/checkpoints - python scripts/collect_model_urls.py torchvision/prototype/models \ - | parallel -j0 'wget --no-verbose -O ~/.cache/torch/hub/checkpoints/`basename {}` {}\?source=ci' + - download_model_weights: + extract_roots: torchvision/prototype/models - install_torchvision - install_prototype_dependencies - pip_install: @@ -1011,12 +1025,13 @@ jobs: build_docs: <<: *binary_common docker: - - image: "pytorch/manylinux-cuda100" + - image: circleci/python:3.7 resource_class: 2xlarge+ steps: - attach_workspace: at: ~/workspace - checkout + - download_model_weights - run: name: Setup command: .circleci/unittest/linux/scripts/setup_env.sh diff --git a/scripts/collect_model_urls.py b/scripts/collect_model_urls.py index 3554e80b1ed..2acba6cbbda 100644 --- a/scripts/collect_model_urls.py +++ b/scripts/collect_model_urls.py @@ -2,21 +2,19 @@ import re import sys -MODEL_URL_PATTERN = re.compile(r"https://download[.]pytorch[.]org/models/.*?[.]pth") +MODEL_URL_PATTERN = re.compile(r"https://download[.]pytorch[.]org/models/.+?[.]pth") -def main(root): +def main(*roots): model_urls = set() - for path in pathlib.Path(root).glob("**/*"): - if path.name.startswith("_") or not path.suffix == ".py": - continue - - with open(path, "r") as file: - for line in file: - model_urls.update(MODEL_URL_PATTERN.findall(line)) + for root in roots: + for path in pathlib.Path(root).rglob("*.py"): + with open(path, "r") as file: + for line in file: + model_urls.update(MODEL_URL_PATTERN.findall(line)) print("\n".join(sorted(model_urls))) if __name__ == "__main__": - main(sys.argv[1]) + main(*sys.argv[1:]) From 85c6717272537a838d8dbe046effb3fffe895840 Mon Sep 17 00:00:00 2001 From: Vasilis Vryniotis Date: Wed, 16 Mar 2022 12:43:19 +0000 Subject: [PATCH 4/4] Regenerated config.yml --- .circleci/config.yml | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index c68f39642ca..86aa08d65b6 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -360,19 +360,28 @@ jobs: resource_class: xlarge steps: - checkout - - download_model_weights: - extract_roots: torchvision/prototype/models - install_torchvision - install_prototype_dependencies - pip_install: args: scipy pycocotools h5py descr: Install optional dependencies - - run: - name: Enable prototype tests - command: echo 'export PYTORCH_TEST_WITH_PROTOTYPE=1' >> $BASH_ENV - run_tests_selective: file_or_dir: test/test_prototype_*.py + unittest_extended: + docker: + - image: circleci/python:3.7 + resource_class: xlarge + steps: + - checkout + - download_model_weights + - install_torchvision + - run: + name: Enable extended tests + command: echo 'export PYTORCH_TEST_WITH_EXTENDED=1' >> $BASH_ENV + - run_tests_selective: + file_or_dir: test/test_extended_*.py + binary_linux_wheel: <<: *binary_common docker: @@ -1623,6 +1632,7 @@ workflows: - unittest_torchhub - unittest_onnx - unittest_prototype + - unittest_extended - unittest_linux_cpu: cu_version: cpu name: unittest_linux_cpu_py3.7