From dfb28628e94f903311f36269ffb7b477e611e952 Mon Sep 17 00:00:00 2001 From: Joao Gomes Date: Thu, 10 Mar 2022 17:24:14 +0000 Subject: [PATCH 01/49] replace most asserts with exceptions --- references/classification/transforms.py | 13 ++++-- references/detection/coco_eval.py | 3 +- references/detection/coco_utils.py | 5 ++- references/optical_flow/transforms.py | 24 ++++++---- references/optical_flow/utils.py | 3 +- references/segmentation/coco_utils.py | 4 +- references/segmentation/utils.py | 3 +- references/similarity/sampler.py | 3 +- references/video_classification/utils.py | 3 +- torchvision/datasets/kinetics.py | 3 +- torchvision/datasets/mnist.py | 21 ++++++--- torchvision/datasets/samplers/clip_sampler.py | 8 +--- torchvision/datasets/sbd.py | 1 - torchvision/datasets/video_utils.py | 3 +- torchvision/io/_video_opt.py | 10 +---- torchvision/models/detection/_utils.py | 12 +++-- torchvision/models/detection/anchor_utils.py | 4 +- torchvision/models/detection/faster_rcnn.py | 9 ++-- torchvision/models/detection/fcos.py | 6 ++- torchvision/models/detection/keypoint_rcnn.py | 3 +- torchvision/models/detection/mask_rcnn.py | 3 +- torchvision/models/detection/retinanet.py | 3 +- torchvision/models/detection/roi_heads.py | 30 ++++++++----- torchvision/models/detection/rpn.py | 3 +- torchvision/models/detection/ssd.py | 6 ++- torchvision/models/detection/ssdlite.py | 7 ++- torchvision/models/feature_extraction.py | 27 +++++------- torchvision/models/googlenet.py | 3 +- torchvision/models/inception.py | 3 +- torchvision/models/mnasnet.py | 18 +++++--- torchvision/models/mobilenetv2.py | 3 +- torchvision/models/optical_flow/raft.py | 44 +++++++++++-------- torchvision/models/vision_transformer.py | 18 +++++--- torchvision/ops/_utils.py | 10 ++--- torchvision/ops/feature_pyramid_network.py | 3 +- torchvision/ops/poolers.py | 14 +++--- torchvision/transforms/_functional_video.py | 21 ++++++--- torchvision/transforms/_transforms_video.py | 3 +- torchvision/utils.py | 11 +++-- 39 files changed, 221 insertions(+), 150 deletions(-) diff --git a/references/classification/transforms.py b/references/classification/transforms.py index e72cd67fbfd..ae01b4ddf18 100644 --- a/references/classification/transforms.py +++ b/references/classification/transforms.py @@ -21,8 +21,11 @@ class RandomMixup(torch.nn.Module): def __init__(self, num_classes: int, p: float = 0.5, alpha: float = 1.0, inplace: bool = False) -> None: super().__init__() - assert num_classes > 0, "Please provide a valid positive value for the num_classes." - assert alpha > 0, "Alpha param can't be zero." + if not num_classes > 0: + raise ValueError("Please provide a valid positive value for the num_classes.") + + if not alpha > 0: + raise ValueError("Alpha param can't be zero.") self.num_classes = num_classes self.p = p @@ -99,8 +102,10 @@ class RandomCutmix(torch.nn.Module): def __init__(self, num_classes: int, p: float = 0.5, alpha: float = 1.0, inplace: bool = False) -> None: super().__init__() - assert num_classes > 0, "Please provide a valid positive value for the num_classes." - assert alpha > 0, "Alpha param can't be zero." + if not num_classes > 0: + raise ValueError("Please provide a valid positive value for the num_classes.") + if not alpha > 0: + raise ValueError("Alpha param can't be zero.") self.num_classes = num_classes self.p = p diff --git a/references/detection/coco_eval.py b/references/detection/coco_eval.py index ec0709c5d91..ba1359f8c65 100644 --- a/references/detection/coco_eval.py +++ b/references/detection/coco_eval.py @@ -12,7 +12,8 @@ class CocoEvaluator: def __init__(self, coco_gt, iou_types): - assert isinstance(iou_types, (list, tuple)) + if not isinstance(iou_types, (list, tuple)): + raise TypeError(f"This constructor expects iou_types of type list or tuple, instead got {type(iou_types)}") coco_gt = copy.deepcopy(coco_gt) self.coco_gt = coco_gt diff --git a/references/detection/coco_utils.py b/references/detection/coco_utils.py index b0f193135ee..39e3affdffa 100644 --- a/references/detection/coco_utils.py +++ b/references/detection/coco_utils.py @@ -100,7 +100,7 @@ def __call__(self, image, target): return image, target -def _coco_remove_images_without_annotations(dataset, cat_list=None): +def _coco_remove_images_without_annotations(dataset: torchvision.datasets.CocoDetection, cat_list: list = None): def _has_only_empty_bbox(anno): return all(any(o <= 1 for o in obj["bbox"][2:]) for obj in anno) @@ -126,7 +126,8 @@ def _has_valid_annotation(anno): return True return False - assert isinstance(dataset, torchvision.datasets.CocoDetection) + if not isinstance(dataset, torchvision.datasets.CocoDetection): + raise TypeError(f"This function expects dataset of type torchvision.datasets.CocoDetection, instead got {type(dataset)}") ids = [] for ds_idx, img_id in enumerate(dataset.ids): ann_ids = dataset.coco.getAnnIds(imgIds=img_id, iscrowd=None) diff --git a/references/optical_flow/transforms.py b/references/optical_flow/transforms.py index b6a42f402e1..3986f021c6b 100644 --- a/references/optical_flow/transforms.py +++ b/references/optical_flow/transforms.py @@ -1,3 +1,4 @@ +from multiprocessing.sharedctypes import Value import torch import torchvision.transforms as T import torchvision.transforms.functional as F @@ -7,16 +8,22 @@ class ValidateModelInput(torch.nn.Module): # Pass-through transform that checks the shape and dtypes to make sure the model gets what it expects def forward(self, img1, img2, flow, valid_flow_mask): - assert all(isinstance(arg, torch.Tensor) for arg in (img1, img2, flow, valid_flow_mask) if arg is not None) - assert all(arg.dtype == torch.float32 for arg in (img1, img2, flow) if arg is not None) + if not all(isinstance(arg, torch.Tensor) for arg in (img1, img2, flow, valid_flow_mask) if arg is not None): + raise TypeError("This method expects all input arguments to be of type torch.Tensor.") + if not all(arg.dtype == torch.float32 for arg in (img1, img2, flow) if arg is not None): + raise TypeError(f"This method expects the tensors img1, img2 and flow of be of dtype torch.float32.") - assert img1.shape == img2.shape + + if not img1.shape == img2.shape: + raise ValueError("img1 and img2 should have the same shape.") h, w = img1.shape[-2:] - if flow is not None: - assert flow.shape == (2, h, w) + if flow is not None and not flow.shape == (2, h, w): + raise ValueError(f"flow.shape should be (2, {h}, {w}) instead of {flow.shape}") if valid_flow_mask is not None: - assert valid_flow_mask.shape == (h, w) - assert valid_flow_mask.dtype == torch.bool + if not valid_flow_mask.shape == (h, w): + raise ValueError(f"valid_flow_mask.shape should be ({h}, {w}) instead of {valid_flow_mask.shape}") + if not valid_flow_mask.dtype == torch.bool: + raise TypeError("valid_flow_mask should be of dtype torch.bool instead of {valid_flow_mask.dtype}") return img1, img2, flow, valid_flow_mask @@ -109,7 +116,8 @@ class RandomErasing(T.RandomErasing): def __init__(self, p=0.5, scale=(0.02, 0.33), ratio=(0.3, 3.3), value=0, inplace=False, max_erase=1): super().__init__(p=p, scale=scale, ratio=ratio, value=value, inplace=inplace) self.max_erase = max_erase - assert self.max_erase > 0 + if not self.max_erase > 0: + raise ValueError("max_raise should be greater than 0") def forward(self, img1, img2, flow, valid_flow_mask): if torch.rand(1) > self.p: diff --git a/references/optical_flow/utils.py b/references/optical_flow/utils.py index acdc49bd1f7..3d04df3cbd5 100644 --- a/references/optical_flow/utils.py +++ b/references/optical_flow/utils.py @@ -71,7 +71,8 @@ def update(self, **kwargs): for k, v in kwargs.items(): if isinstance(v, torch.Tensor): v = v.item() - assert isinstance(v, (float, int)) + if not isinstance(v, (float, int)): + raise TypeError(f"This method expects the value of the input arguments to be of type float or int, instead got {type(v)}") self.meters[k].update(v) def __getattr__(self, attr): diff --git a/references/segmentation/coco_utils.py b/references/segmentation/coco_utils.py index 4d37187f7ec..1f6ea4c024e 100644 --- a/references/segmentation/coco_utils.py +++ b/references/segmentation/coco_utils.py @@ -68,7 +68,9 @@ def _has_valid_annotation(anno): # if more than 1k pixels occupied in the image return sum(obj["area"] for obj in anno) > 1000 - assert isinstance(dataset, torchvision.datasets.CocoDetection) + if not isinstance(dataset, torchvision.datasets.CocoDetection): + raise TypeError(f"This function expects dataset of type torchvision.datasets.CocoDetection, instead got {type(dataset)}") + ids = [] for ds_idx, img_id in enumerate(dataset.ids): ann_ids = dataset.coco.getAnnIds(imgIds=img_id, iscrowd=None) diff --git a/references/segmentation/utils.py b/references/segmentation/utils.py index 22096c9dd2c..bf4131ab19e 100644 --- a/references/segmentation/utils.py +++ b/references/segmentation/utils.py @@ -118,7 +118,8 @@ def update(self, **kwargs): for k, v in kwargs.items(): if isinstance(v, torch.Tensor): v = v.item() - assert isinstance(v, (float, int)) + if not isinstance(v, (float, int)): + raise TypeError(f"This method expects the value of the input arguments to be of type float or int, instead got {type(v)}") self.meters[k].update(v) def __getattr__(self, attr): diff --git a/references/similarity/sampler.py b/references/similarity/sampler.py index 591155fb449..bca29cf43ec 100644 --- a/references/similarity/sampler.py +++ b/references/similarity/sampler.py @@ -47,7 +47,8 @@ def __init__(self, groups, p, k): self.groups = create_groups(groups, self.k) # Ensures there are enough classes to sample from - assert len(self.groups) >= p + if not len(self.groups) >= p: + raise ValueError("There are not enought classes to sample from") def __iter__(self): # Shuffle samples within groups diff --git a/references/video_classification/utils.py b/references/video_classification/utils.py index a68c2386bcf..12fd4f3e388 100644 --- a/references/video_classification/utils.py +++ b/references/video_classification/utils.py @@ -76,7 +76,8 @@ def update(self, **kwargs): for k, v in kwargs.items(): if isinstance(v, torch.Tensor): v = v.item() - assert isinstance(v, (float, int)) + if not isinstance(v, (float, int)): + raise TypeError(f"This method expects the value of the input arguments to be of type float or int, instead got {type(v)}") self.meters[k].update(v) def __getattr__(self, attr): diff --git a/torchvision/datasets/kinetics.py b/torchvision/datasets/kinetics.py index 189142a5e67..6581f80bec5 100644 --- a/torchvision/datasets/kinetics.py +++ b/torchvision/datasets/kinetics.py @@ -118,7 +118,8 @@ def __init__( print("Using legacy structure") self.split_folder = root self.split = "unknown" - assert not download, "Cannot download the videos using legacy_structure." + if download: + raise RuntimeError("Cannot download the videos using legacy_structure.") else: self.split_folder = path.join(root, split) self.split = verify_str_arg(split, arg="split", valid_values=["train", "val"]) diff --git a/torchvision/datasets/mnist.py b/torchvision/datasets/mnist.py index 660de3d420f..c283254ed77 100644 --- a/torchvision/datasets/mnist.py +++ b/torchvision/datasets/mnist.py @@ -442,11 +442,14 @@ def _check_exists(self) -> bool: def _load_data(self): data = read_sn3_pascalvincent_tensor(self.images_file) - assert data.dtype == torch.uint8 - assert data.ndimension() == 3 + if not data.dtype == torch.uint8: + raise TypeError(f"data should be of dtype torch.uint8 instead of {data.dtype}") + if not data.ndimension() == 3: + raise ValueError("data should have 3 dimensions instead of {data.ndimension()}") targets = read_sn3_pascalvincent_tensor(self.labels_file).long() - assert targets.ndimension() == 2 + if not targets.ndimension() == 2: + raise ValueError(f"targets should have 2 dimensions instead of {targets.ndimension()}") if self.what == "test10k": data = data[0:10000, :, :].clone() @@ -530,13 +533,17 @@ def read_sn3_pascalvincent_tensor(path: str, strict: bool = True) -> torch.Tenso def read_label_file(path: str) -> torch.Tensor: x = read_sn3_pascalvincent_tensor(path, strict=False) - assert x.dtype == torch.uint8 - assert x.ndimension() == 1 + if not x.dtype == torch.uint8: + raise TypeError(f"x should be of dtype torch.uint8 instead of {x.dtype}") + if not x.ndimension() == 1: + raise ValueError(f"x should have 1 dimension instead of {x.ndimension()}") return x.long() def read_image_file(path: str) -> torch.Tensor: x = read_sn3_pascalvincent_tensor(path, strict=False) - assert x.dtype == torch.uint8 - assert x.ndimension() == 3 + if not x.dtype == torch.uint8: + raise TypeError(f"x should be of dtype torch.uint8 instead of {x.dtype}") + if not x.ndimension() == 3: + raise ValueError(f"x should have 3 dimension instead of {x.ndimension()}") return x diff --git a/torchvision/datasets/samplers/clip_sampler.py b/torchvision/datasets/samplers/clip_sampler.py index ad7427f1949..0ac491f79e3 100644 --- a/torchvision/datasets/samplers/clip_sampler.py +++ b/torchvision/datasets/samplers/clip_sampler.py @@ -52,12 +52,8 @@ def __init__( if not dist.is_available(): raise RuntimeError("Requires distributed package to be available") rank = dist.get_rank() - assert ( - len(dataset) % group_size == 0 - ), "dataset length must be a multiplier of group size dataset length: %d, group size: %d" % ( - len(dataset), - group_size, - ) + if not len(dataset) % group_size == 0 + raise ValueError(f"dataset length must be a multiplier of group size dataset length: {len(dataset)}, group size: {group_size}") self.dataset = dataset self.group_size = group_size self.num_replicas = num_replicas diff --git a/torchvision/datasets/sbd.py b/torchvision/datasets/sbd.py index ce485680910..030643dc794 100644 --- a/torchvision/datasets/sbd.py +++ b/torchvision/datasets/sbd.py @@ -92,7 +92,6 @@ def __init__( self.images = [os.path.join(image_dir, x + ".jpg") for x in file_names] self.masks = [os.path.join(mask_dir, x + ".mat") for x in file_names] - assert len(self.images) == len(self.masks) self._get_target = self._get_segmentation_target if self.mode == "segmentation" else self._get_boundaries_target diff --git a/torchvision/datasets/video_utils.py b/torchvision/datasets/video_utils.py index efa3836c8d1..826b4e19cf6 100644 --- a/torchvision/datasets/video_utils.py +++ b/torchvision/datasets/video_utils.py @@ -38,7 +38,8 @@ def unfold(tensor: torch.Tensor, size: int, step: int, dilation: int = 1) -> tor `step` between windows. The distance between each element in a window is given by `dilation`. """ - assert tensor.dim() == 1 + if not tensor.dim() == 1: + raise ValueError(f"tensor should have 1 dimension instead of {tensor.dim()}") o_stride = tensor.stride(0) numel = tensor.numel() new_stride = (step * o_stride, dilation * o_stride) diff --git a/torchvision/io/_video_opt.py b/torchvision/io/_video_opt.py index de4b25bb7b5..b5c830cf232 100644 --- a/torchvision/io/_video_opt.py +++ b/torchvision/io/_video_opt.py @@ -67,14 +67,8 @@ def __init__(self) -> None: def _validate_pts(pts_range: Tuple[int, int]) -> None: - if pts_range[1] > 0: - assert ( - pts_range[0] <= pts_range[1] - ), """Start pts should not be smaller than end pts, got - start pts: {:d} and end pts: {:d}""".format( - pts_range[0], - pts_range[1], - ) + if pts_range[1] > 0 and not (pts_range[0] <= pts_range[1]): + raise ValueError(f"Start pts should not be smaller than end pts, got start pts: {pts_range[0]} and end pts: {pts_range[1]}") def _fill_info( diff --git a/torchvision/models/detection/_utils.py b/torchvision/models/detection/_utils.py index 36e99e6506d..bc6912f80b2 100644 --- a/torchvision/models/detection/_utils.py +++ b/torchvision/models/detection/_utils.py @@ -159,8 +159,10 @@ def encode_single(self, reference_boxes: Tensor, proposals: Tensor) -> Tensor: return targets def decode(self, rel_codes: Tensor, boxes: List[Tensor]) -> Tensor: - assert isinstance(boxes, (list, tuple)) - assert isinstance(rel_codes, torch.Tensor) + if not isinstance(boxes, (list, tuple)): + raise TypeError(f"This function expects boxes of type list or tuple, instead got {type(boxes)}") + if not isinstance(rel_codes, torch.Tensor): + raise TypeError(f"This function expects rel_codes of type torch.Tensor, instead got {type(rel_codes)}") boxes_per_image = [b.size(0) for b in boxes] concat_boxes = torch.cat(boxes, dim=0) box_sum = 0 @@ -333,7 +335,8 @@ def __init__(self, high_threshold: float, low_threshold: float, allow_low_qualit """ self.BELOW_LOW_THRESHOLD = -1 self.BETWEEN_THRESHOLDS = -2 - assert low_threshold <= high_threshold + if not low_threshold <= high_threshold: + raise ValueError("low_threshold should be <= high_threshold") self.high_threshold = high_threshold self.low_threshold = low_threshold self.allow_low_quality_matches = allow_low_quality_matches @@ -371,7 +374,8 @@ def __call__(self, match_quality_matrix: Tensor) -> Tensor: matches[between_thresholds] = self.BETWEEN_THRESHOLDS if self.allow_low_quality_matches: - assert all_matches is not None + if all_matches is None: + raise ValueError("all_matches should not be None") self.set_low_quality_matches_(matches, all_matches, match_quality_matrix) return matches diff --git a/torchvision/models/detection/anchor_utils.py b/torchvision/models/detection/anchor_utils.py index 6771dda0ce4..12371f7d7e7 100644 --- a/torchvision/models/detection/anchor_utils.py +++ b/torchvision/models/detection/anchor_utils.py @@ -164,8 +164,8 @@ def __init__( clip: bool = True, ): super().__init__() - if steps is not None: - assert len(aspect_ratios) == len(steps) + if steps is not None and len(aspect_ratios) != len(steps): + raise RuntimeError("aspect_ratios and steps should have the same length") self.aspect_ratios = aspect_ratios self.steps = steps self.clip = clip diff --git a/torchvision/models/detection/faster_rcnn.py b/torchvision/models/detection/faster_rcnn.py index 790740fe9c5..1367cfda7c2 100644 --- a/torchvision/models/detection/faster_rcnn.py +++ b/torchvision/models/detection/faster_rcnn.py @@ -187,8 +187,10 @@ def __init__( "same for all the levels)" ) - assert isinstance(rpn_anchor_generator, (AnchorGenerator, type(None))) - assert isinstance(box_roi_pool, (MultiScaleRoIAlign, type(None))) + if not isinstance(rpn_anchor_generator, (AnchorGenerator, type(None))): + raise TypeError(f"rpn_anchor_generator should be of type AnchorGenerator or None instead of {type(rpn_anchor_generator)}") + if not isinstance(box_roi_pool, (MultiScaleRoIAlign, type(None))): + raise TypeError(f"box_roi_pool should be of type MultiScaleRoIAlign or None instead of {type(box_roi_pool)}") if num_classes is not None: if box_predictor is not None: @@ -299,7 +301,8 @@ def __init__(self, in_channels, num_classes): def forward(self, x): if x.dim() == 4: - assert list(x.shape[2:]) == [1, 1] + if not list(x.shape[2:]) == [1, 1]: + raise ValueError(f"x has the wrong shape, expecting the last two dimensions to be [1,1] instead of {list(x.shape[2:])}") x = x.flatten(start_dim=1) scores = self.cls_score(x) bbox_deltas = self.bbox_pred(x) diff --git a/torchvision/models/detection/fcos.py b/torchvision/models/detection/fcos.py index c4c2e6f5842..19b41c0464f 100644 --- a/torchvision/models/detection/fcos.py +++ b/torchvision/models/detection/fcos.py @@ -378,14 +378,16 @@ def __init__( ) self.backbone = backbone - assert isinstance(anchor_generator, (AnchorGenerator, type(None))) + if not isinstance(anchor_generator, (AnchorGenerator, type(None))): + raise TypeError(f"anchor_generator should be of type AnchorGenerator or None, instead got {type(anchor_generator)}") if anchor_generator is None: anchor_sizes = ((8,), (16,), (32,), (64,), (128,)) # equal to strides of multi-level feature map aspect_ratios = ((1.0,),) * len(anchor_sizes) # set only one anchor anchor_generator = AnchorGenerator(anchor_sizes, aspect_ratios) self.anchor_generator = anchor_generator - assert self.anchor_generator.num_anchors_per_location()[0] == 1 + if not self.anchor_generator.num_anchors_per_location()[0] == 1: + raise ValueError(f"anchor_generator.num_anchors_per_location()[0] should be 1 instead of {anchor_generator.num_anchors_per_location()[0]}") if head is None: head = FCOSHead(backbone.out_channels, anchor_generator.num_anchors_per_location()[0], num_classes) diff --git a/torchvision/models/detection/keypoint_rcnn.py b/torchvision/models/detection/keypoint_rcnn.py index 9f23e66e0c5..f8931be361c 100644 --- a/torchvision/models/detection/keypoint_rcnn.py +++ b/torchvision/models/detection/keypoint_rcnn.py @@ -191,7 +191,8 @@ def __init__( num_keypoints=None, ): - assert isinstance(keypoint_roi_pool, (MultiScaleRoIAlign, type(None))) + if not isinstance(keypoint_roi_pool, (MultiScaleRoIAlign, type(None))): + raise TypeError("keypoint_roi_pool should be of type MultiScaleRoIAlign or None instead of {type(keypoint_roi_pool)}") if min_size is None: min_size = (640, 672, 704, 736, 768, 800) diff --git a/torchvision/models/detection/mask_rcnn.py b/torchvision/models/detection/mask_rcnn.py index 37f88116c5e..7b6ebb8d4cb 100644 --- a/torchvision/models/detection/mask_rcnn.py +++ b/torchvision/models/detection/mask_rcnn.py @@ -191,7 +191,8 @@ def __init__( mask_predictor=None, ): - assert isinstance(mask_roi_pool, (MultiScaleRoIAlign, type(None))) + if not isinstance(mask_roi_pool, (MultiScaleRoIAlign, type(None))): + raise TypeError(f"mask_roi_pool should be of type MultiScaleRoIAlign or None instead of {type(mask_roi_pool)}") if num_classes is not None: if mask_predictor is not None: diff --git a/torchvision/models/detection/retinanet.py b/torchvision/models/detection/retinanet.py index 4f79b5ddbfc..61ded072968 100644 --- a/torchvision/models/detection/retinanet.py +++ b/torchvision/models/detection/retinanet.py @@ -347,7 +347,8 @@ def __init__( ) self.backbone = backbone - assert isinstance(anchor_generator, (AnchorGenerator, type(None))) + if not isinstance(anchor_generator, (AnchorGenerator, type(None))): + raise TypeError(f"anchor_generator should be of type AnchorGenerator or None instead of {type(anchor_generator)}") if anchor_generator is None: anchor_sizes = tuple((x, int(x * 2 ** (1.0 / 3)), int(x * 2 ** (2.0 / 3))) for x in [32, 64, 128, 256, 512]) diff --git a/torchvision/models/detection/roi_heads.py b/torchvision/models/detection/roi_heads.py index b7bbb81111e..b8cf27e8953 100644 --- a/torchvision/models/detection/roi_heads.py +++ b/torchvision/models/detection/roi_heads.py @@ -1,4 +1,5 @@ -from typing import Optional, List, Dict, Tuple +from multiprocessing.sharedctypes import Value +from typing import Optional, List, Dict, Tuple, Type import torch import torch.nn.functional as F @@ -299,7 +300,8 @@ def heatmaps_to_keypoints(maps, rois): def keypointrcnn_loss(keypoint_logits, proposals, gt_keypoints, keypoint_matched_idxs): # type: (Tensor, List[Tensor], List[Tensor], List[Tensor]) -> Tensor N, K, H, W = keypoint_logits.shape - assert H == W + if not H == W: + raise ValueError("keypoint_logits height and width (last two elements of shape) should be equal.") discretization_size = H heatmaps = [] valid = [] @@ -615,11 +617,15 @@ def add_gt_proposals(self, proposals, gt_boxes): def check_targets(self, targets): # type: (Optional[List[Dict[str, Tensor]]]) -> None - assert targets is not None - assert all(["boxes" in t for t in targets]) - assert all(["labels" in t for t in targets]) + if targets is None: + raise ValueError("targets should not be None") + if not all(["boxes" in t for t in targets]): + raise ValueError("Every element of targets should have a boxes key") + if not all(["labels" in t for t in targets]): + raise ValueError("Every element of targets should have a labels key") if self.has_mask(): - assert all(["masks" in t for t in targets]) + if not all(["masks" in t for t in targets]): + raise ValueError("Every element of targets should have a masks key") def select_training_samples( self, @@ -628,7 +634,8 @@ def select_training_samples( ): # type: (...) -> Tuple[List[Tensor], List[Tensor], List[Tensor], List[Tensor]] self.check_targets(targets) - assert targets is not None + if targets is None: + raise ValueError("targets should not be None") dtype = proposals[0].dtype device = proposals[0].device @@ -736,10 +743,13 @@ def forward( for t in targets: # TODO: https://github.com/pytorch/pytorch/issues/26731 floating_point_types = (torch.float, torch.double, torch.half) - assert t["boxes"].dtype in floating_point_types, "target boxes must of float type" - assert t["labels"].dtype == torch.int64, "target labels must of int64 type" + if not t["boxes"].dtype in floating_point_types: + raise TypeError("target boxes must of float type") + if not t["labels"].dtype == torch.int64: + raise TypeError("target labels must of int64 type") if self.has_keypoint(): - assert t["keypoints"].dtype == torch.float32, "target keypoints must of float type" + if not t["keypoints"].dtype == torch.float32: + raise TypeError("target keypoints must of float type") if self.training: proposals, matched_idxs, labels, regression_targets = self.select_training_samples(proposals, targets) diff --git a/torchvision/models/detection/rpn.py b/torchvision/models/detection/rpn.py index 1d63bcc8a54..18379ac25f6 100644 --- a/torchvision/models/detection/rpn.py +++ b/torchvision/models/detection/rpn.py @@ -339,7 +339,8 @@ def forward( losses = {} if self.training: - assert targets is not None + if targets is None: + raise ValueError("targets should not be None") labels, matched_gt_boxes = self.assign_targets_to_anchors(anchors, targets) regression_targets = self.box_coder.encode(matched_gt_boxes, anchors) loss_objectness, loss_rpn_box_reg = self.compute_loss( diff --git a/torchvision/models/detection/ssd.py b/torchvision/models/detection/ssd.py index 08a9ed68e4e..9d2e59641df 100644 --- a/torchvision/models/detection/ssd.py +++ b/torchvision/models/detection/ssd.py @@ -308,7 +308,8 @@ def forward( raise ValueError("In training mode, targets should be passed") if self.training: - assert targets is not None + if targets is None: + raise ValueError("targets should not be None") for target in targets: boxes = target["boxes"] if isinstance(boxes, torch.Tensor): @@ -527,7 +528,8 @@ def _vgg_extractor(backbone: vgg.VGG, highres: bool, trainable_layers: int): num_stages = len(stage_indices) # find the index of the layer from which we wont freeze - assert 0 <= trainable_layers <= num_stages + if 0 <= trainable_layers <= num_stages: + raise ValueError(f"trainable_layers should be in the range [0, {num_stages}].") freeze_before = len(backbone) if trainable_layers == 0 else stage_indices[num_stages - trainable_layers] for b in backbone[:freeze_before]: diff --git a/torchvision/models/detection/ssdlite.py b/torchvision/models/detection/ssdlite.py index 1ee59e069ea..a1cbaeafda9 100644 --- a/torchvision/models/detection/ssdlite.py +++ b/torchvision/models/detection/ssdlite.py @@ -122,7 +122,9 @@ def __init__( super().__init__() _log_api_usage_once(self) - assert not backbone[c4_pos].use_res_connect + if backbone[c4_pos].use_res_connect: + raise ValueError("backbone[c4_pos].use_res_connect should be False") + self.features = nn.Sequential( # As described in section 6.3 of MobileNetV3 paper nn.Sequential(*backbone[:c4_pos], backbone[c4_pos].block[0]), # from start until C4 expansion layer @@ -168,7 +170,8 @@ def _mobilenet_extractor( num_stages = len(stage_indices) # find the index of the layer from which we wont freeze - assert 0 <= trainable_layers <= num_stages + if not 0 <= trainable_layers <= num_stages: + raise ValueError("trainable_layers should be in the range [0, {num_stages}], instead got {trainable_layers}") freeze_before = len(backbone) if trainable_layers == 0 else stage_indices[num_stages - trainable_layers] for b in backbone[:freeze_before]: diff --git a/torchvision/models/feature_extraction.py b/torchvision/models/feature_extraction.py index 0a2b597da23..285f5238e23 100644 --- a/torchvision/models/feature_extraction.py +++ b/torchvision/models/feature_extraction.py @@ -5,7 +5,7 @@ from collections import OrderedDict from copy import deepcopy from itertools import chain -from typing import Dict, Callable, List, Union, Optional, Tuple, Any +from typing import Dict, Callable, List, Type, Union, Optional, Tuple, Any import torch import torchvision @@ -277,7 +277,8 @@ def __init__( # eval graphs) for node in chain(iter(train_graph.nodes), iter(eval_graph.nodes)): if node.op in ["get_attr", "call_module"]: - assert isinstance(node.target, str) + if not isinstance(node.target, str): + raise TypeError(f"node.target should be of type str instead of {type(node.target)}") _copy_attr(root, self, node.target) # train mode by default @@ -290,9 +291,8 @@ def __init__( # Locally defined Tracers are not pickleable. This is needed because torch.package will # serialize a GraphModule without retaining the Graph, and needs to use the correct Tracer # to re-create the Graph during deserialization. - assert ( - self.eval_graph._tracer_cls == self.train_graph._tracer_cls - ), "Train mode and eval mode should use the same tracer class" + if not self.eval_graph._tracer_cls == self.train_graph._tracer_cls: + raise RuntimeError("Train mode and eval mode should use the same tracer class") self._tracer_cls = None if self.graph._tracer_cls and "" not in self.graph._tracer_cls.__qualname__: self._tracer_cls = self.graph._tracer_cls @@ -431,17 +431,14 @@ def create_feature_extractor( } is_training = model.training - assert any( - arg is not None for arg in [return_nodes, train_return_nodes, eval_return_nodes] - ), "Either `return_nodes` or `train_return_nodes` and `eval_return_nodes` together, should be specified" + if not any(arg is not None for arg in [return_nodes, train_return_nodes, eval_return_nodes]): + raise RuntimeError("Either `return_nodes` or `train_return_nodes` and `eval_return_nodes` together, should be specified") - assert not ( - (train_return_nodes is None) ^ (eval_return_nodes is None) - ), "If any of `train_return_nodes` and `eval_return_nodes` are specified, then both should be specified" + if ((train_return_nodes is None) ^ (eval_return_nodes is None)): + raise RuntimeError("If any of `train_return_nodes` and `eval_return_nodes` are specified, then both should be specified") - assert (return_nodes is None) ^ ( - train_return_nodes is None - ), "If `train_return_nodes` and `eval_return_nodes` are specified, then both should be specified" + if not (return_nodes is None) ^ (train_return_nodes is None): + raise RuntimeError("If `train_return_nodes` and `eval_return_nodes` are specified, then both should be specified") # Put *_return_nodes into Dict[str, str] format def to_strdict(n) -> Dict[str, str]: @@ -497,7 +494,7 @@ def to_strdict(n) -> Dict[str, str]: for n in reversed(graph_module.graph.nodes): if n.op == "output": orig_output_nodes.append(n) - assert len(orig_output_nodes) + for n in orig_output_nodes: graph_module.graph.erase_node(n) diff --git a/torchvision/models/googlenet.py b/torchvision/models/googlenet.py index 9e4c3498aab..fc94de07540 100644 --- a/torchvision/models/googlenet.py +++ b/torchvision/models/googlenet.py @@ -50,7 +50,8 @@ def __init__( FutureWarning, ) init_weights = True - assert len(blocks) == 3 + if not len(blocks) == 3: + raise ValueError(f"blocks length should be 3 instead of {len(blocks)}") conv_block = blocks[0] inception_block = blocks[1] inception_aux_block = blocks[2] diff --git a/torchvision/models/inception.py b/torchvision/models/inception.py index c489925cb45..c7adb4384d4 100644 --- a/torchvision/models/inception.py +++ b/torchvision/models/inception.py @@ -48,7 +48,8 @@ def __init__( FutureWarning, ) init_weights = True - assert len(inception_blocks) == 7 + if not len(inception_blocks) == 7: + raise ValueError(f"lenght of inception_blocks should be 7 instead of {len(inception_blocks)}") conv_block = inception_blocks[0] inception_a = inception_blocks[1] inception_b = inception_blocks[2] diff --git a/torchvision/models/mnasnet.py b/torchvision/models/mnasnet.py index c3d4013f30c..e9c7691121e 100644 --- a/torchvision/models/mnasnet.py +++ b/torchvision/models/mnasnet.py @@ -27,8 +27,10 @@ def __init__( self, in_ch: int, out_ch: int, kernel_size: int, stride: int, expansion_factor: int, bn_momentum: float = 0.1 ) -> None: super().__init__() - assert stride in [1, 2] - assert kernel_size in [3, 5] + if not stride in [1, 2]: + raise ValueError(f"stride should be 1 or 2 instead of {stride}") + if not kernel_size in [3, 5]: + raise ValueError(f"kernel_size should be 3 or 5 instead of {kernel_size}") mid_ch = in_ch * expansion_factor self.apply_residual = in_ch == out_ch and stride == 1 self.layers = nn.Sequential( @@ -56,7 +58,8 @@ def _stack( in_ch: int, out_ch: int, kernel_size: int, stride: int, exp_factor: int, repeats: int, bn_momentum: float ) -> nn.Sequential: """Creates a stack of inverted residuals.""" - assert repeats >= 1 + if not repeats >= 1: + raise ValueError("repeats should be >= 1") # First one has no skip, because feature map size changes. first = _InvertedResidual(in_ch, out_ch, kernel_size, stride, exp_factor, bn_momentum=bn_momentum) remaining = [] @@ -69,7 +72,8 @@ def _round_to_multiple_of(val: float, divisor: int, round_up_bias: float = 0.9) """Asymmetric rounding to make `val` divisible by `divisor`. With default bias, will round up, unless the number is no more than 10% greater than the smaller divisible value, i.e. (83, 8) -> 80, but (84, 8) -> 88.""" - assert 0.0 < round_up_bias < 1.0 + if not 0.0 < round_up_bias < 1.0: + raise ValueError(f"round_up_bias should be greater than 0.0 and smaller than 1.0 instead of {round_up_bias}") new_val = max(divisor, int(val + divisor / 2) // divisor * divisor) return new_val if new_val >= round_up_bias * val else new_val + divisor @@ -99,7 +103,8 @@ class MNASNet(torch.nn.Module): def __init__(self, alpha: float, num_classes: int = 1000, dropout: float = 0.2) -> None: super().__init__() _log_api_usage_once(self) - assert alpha > 0.0 + if not alpha > 0.0: + raise ValueError(f"alpha should be greater than 0.0 instead of {alpha}") self.alpha = alpha self.num_classes = num_classes depths = _get_depths(alpha) @@ -158,7 +163,8 @@ def _load_from_state_dict( error_msgs: List[str], ) -> None: version = local_metadata.get("version", None) - assert version in [1, 2] + if not version in [1, 2]: + raise ValueError(f"version shluld be set to 1 or 2 instead of {version}") if version == 1 and not self.alpha == 1.0: # In the initial version of the model (v1), stem was fixed-size. diff --git a/torchvision/models/mobilenetv2.py b/torchvision/models/mobilenetv2.py index 930f68d13e9..78f36546fd6 100644 --- a/torchvision/models/mobilenetv2.py +++ b/torchvision/models/mobilenetv2.py @@ -44,7 +44,8 @@ def __init__( ) -> None: super().__init__() self.stride = stride - assert stride in [1, 2] + if not stride in [1, 2]: + raise ValueError(f"stride should be 1 or 2 insted of {stride}") if norm_layer is None: norm_layer = nn.BatchNorm2d diff --git a/torchvision/models/optical_flow/raft.py b/torchvision/models/optical_flow/raft.py index 4dfd232d499..123833e95c8 100644 --- a/torchvision/models/optical_flow/raft.py +++ b/torchvision/models/optical_flow/raft.py @@ -1,3 +1,4 @@ +from multiprocessing.sharedctypes import Value from typing import List import torch @@ -121,7 +122,8 @@ class FeatureEncoder(nn.Module): def __init__(self, *, block=ResidualBlock, layers=(64, 64, 96, 128, 256), norm_layer=nn.BatchNorm2d): super().__init__() - assert len(layers) == 5 + if not len(layers) == 5: + raise ValueError("The expected number of layers is 5") # See note in ResidualBlock for the reason behind bias=True self.convnormrelu = Conv2dNormActivation( @@ -169,8 +171,10 @@ class MotionEncoder(nn.Module): def __init__(self, *, in_channels_corr, corr_layers=(256, 192), flow_layers=(128, 64), out_channels=128): super().__init__() - assert len(flow_layers) == 2 - assert len(corr_layers) in (1, 2) + if not len(flow_layers) == 2: + raise ValueError("The expected number of flow_layers is 2") + if not len(corr_layers) in (1, 2): + raise ValueError("The number of corr_layers should be 1 or 2") self.convcorr1 = Conv2dNormActivation(in_channels_corr, corr_layers[0], norm_layer=None, kernel_size=1) if len(corr_layers) == 2: @@ -234,8 +238,10 @@ class RecurrentBlock(nn.Module): def __init__(self, *, input_size, hidden_size, kernel_size=((1, 5), (5, 1)), padding=((0, 2), (2, 0))): super().__init__() - assert len(kernel_size) == len(padding) - assert len(kernel_size) in (1, 2) + if not len(kernel_size) == len(padding): + raise ValueError("kernel_size should have the same length as padding") + if not len(kernel_size) in (1, 2): + raise self.convgru1 = ConvGRU( input_size=input_size, hidden_size=hidden_size, kernel_size=kernel_size[0], padding=padding[0] @@ -351,7 +357,8 @@ def build_pyramid(self, fmap1, fmap2): to build the correlation pyramid. """ - torch._assert(fmap1.shape == fmap2.shape, "Input feature maps should have the same shapes") + if not fmap1.shape == fmap2.shape: + raise ValueError("Input feature maps should have the same shape") corr_volume = self._compute_corr_volume(fmap1, fmap2) batch_size, h, w, num_channels, _, _ = corr_volume.shape # _, _ = h, w @@ -384,10 +391,8 @@ def index_pyramid(self, centroids_coords): corr_features = torch.cat(indexed_pyramid, dim=-1).permute(0, 3, 1, 2).contiguous() expected_output_shape = (batch_size, self.out_channels, h, w) - torch._assert( - corr_features.shape == expected_output_shape, - f"Output shape of index pyramid is incorrect. Should be {expected_output_shape}, got {corr_features.shape}", - ) + if not corr_features.shape == expected_output_shape: + raise ValueError(f"Output shape of index pyramid is incorrect. Should be {expected_output_shape}, got {corr_features.shape}") return corr_features @@ -454,28 +459,29 @@ def __init__(self, *, feature_encoder, context_encoder, corr_block, update_block def forward(self, image1, image2, num_flow_updates: int = 12): batch_size, _, h, w = image1.shape - torch._assert((h, w) == image2.shape[-2:], "input images should have the same shape") - torch._assert((h % 8 == 0) and (w % 8 == 0), "input image H and W should be divisible by 8") + if not (h, w) == image2.shape[-2:]: + raise ValueError("input images should have the same shape") + if not (h % 8 == 0) and (w % 8 == 0): + raise ValueError("input image H and W should be divisible by 8") fmaps = self.feature_encoder(torch.cat([image1, image2], dim=0)) fmap1, fmap2 = torch.chunk(fmaps, chunks=2, dim=0) - torch._assert(fmap1.shape[-2:] == (h // 8, w // 8), "The feature encoder should downsample H and W by 8") + if not fmap1.shape[-2:] == (h // 8, w // 8): + raise ValueError("The feature encoder should downsample H and W by 8") self.corr_block.build_pyramid(fmap1, fmap2) context_out = self.context_encoder(image1) - torch._assert(context_out.shape[-2:] == (h // 8, w // 8), "The context encoder should downsample H and W by 8") + if not context_out.shape[-2:] == (h // 8, w // 8): + raise ValueError("The context encoder should downsample H and W by 8") # As in the original paper, the actual output of the context encoder is split in 2 parts: # - one part is used to initialize the hidden state of the recurent units of the update block # - the rest is the "actual" context. hidden_state_size = self.update_block.hidden_state_size out_channels_context = context_out.shape[1] - hidden_state_size - torch._assert( - out_channels_context > 0, - f"The context encoder outputs {context_out.shape[1]} channels, but it should have at strictly more than" - f"hidden_state={hidden_state_size} channels", - ) + if not out_channels_context > 0: + raise ValueError(f"The context encoder outputs {context_out.shape[1]} channels, but it should have at strictly more than hidden_state={hidden_state_size} channels") hidden_state, context = torch.split(context_out, [hidden_state_size, out_channels_context], dim=1) hidden_state = torch.tanh(hidden_state) context = F.relu(context) diff --git a/torchvision/models/vision_transformer.py b/torchvision/models/vision_transformer.py index 29f756ccbe5..9056b2549cf 100644 --- a/torchvision/models/vision_transformer.py +++ b/torchvision/models/vision_transformer.py @@ -76,7 +76,8 @@ def __init__( self.mlp = MLPBlock(hidden_dim, mlp_dim, dropout) def forward(self, input: torch.Tensor): - torch._assert(input.dim() == 3, f"Expected (seq_length, batch_size, hidden_dim) got {input.shape}") + if not input.dim() == 3: + raise ValueError(f"Expected (seq_length, batch_size, hidden_dim) got {input.shape}")) x = self.ln_1(input) x, _ = self.self_attention(query=x, key=x, value=x, need_weights=False) x = self.dropout(x) @@ -120,7 +121,8 @@ def __init__( self.ln = norm_layer(hidden_dim) def forward(self, input: torch.Tensor): - torch._assert(input.dim() == 3, f"Expected (batch_size, seq_length, hidden_dim) got {input.shape}") + if not input.dim() == 3: + raise ValueError(f"Expected (batch_size, seq_length, hidden_dim) got {input.shape}") input = input + self.pos_embedding return self.ln(self.layers(self.dropout(input))) @@ -145,7 +147,8 @@ def __init__( ): super().__init__() _log_api_usage_once(self) - torch._assert(image_size % patch_size == 0, "Input shape indivisible by patch size!") + if not image_size % patch_size == 0: + raise ValueError("Input shape indivisible by patch size!") self.image_size = image_size self.patch_size = patch_size self.hidden_dim = hidden_dim @@ -236,8 +239,10 @@ def __init__( def _process_input(self, x: torch.Tensor) -> torch.Tensor: n, c, h, w = x.shape p = self.patch_size - torch._assert(h == self.image_size, "Wrong image height!") - torch._assert(w == self.image_size, "Wrong image width!") + if not h == self.image_size: + raise ValueError("Wrong image height!") + if not w == self.image_size: + raise ValueError("Wrong image width!") n_h = h // p n_w = w // p @@ -434,7 +439,8 @@ def interpolate_embeddings( # (1, seq_length, hidden_dim) -> (1, hidden_dim, seq_length) pos_embedding_img = pos_embedding_img.permute(0, 2, 1) seq_length_1d = int(math.sqrt(seq_length)) - torch._assert(seq_length_1d * seq_length_1d == seq_length, "seq_length is not a perfect square!") + if not seq_length_1d * seq_length_1d == seq_length: + raise ValueError("seq_length is not a perfect square!") # (1, hidden_dim, seq_length) -> (1, hidden_dim, seq_l_1d, seq_l_1d) pos_embedding_img = pos_embedding_img.reshape(1, hidden_dim, seq_length_1d, seq_length_1d) diff --git a/torchvision/ops/_utils.py b/torchvision/ops/_utils.py index 3a07c747f58..2cc8af2ea43 100644 --- a/torchvision/ops/_utils.py +++ b/torchvision/ops/_utils.py @@ -28,13 +28,13 @@ def convert_boxes_to_roi_format(boxes: List[Tensor]) -> Tensor: def check_roi_boxes_shape(boxes: Union[Tensor, List[Tensor]]): if isinstance(boxes, (list, tuple)): for _tensor in boxes: - assert ( - _tensor.size(1) == 4 - ), "The shape of the tensor in the boxes list is not correct as List[Tensor[L, 4]]" + if not _tensor.size(1) == 4: + raise ValueError("The shape of the tensor in the boxes list is not correct as List[Tensor[L, 4]]") elif isinstance(boxes, torch.Tensor): - assert boxes.size(1) == 5, "The boxes tensor shape is not correct as Tensor[K, 5]" + if not boxes.size(1) == 5: + raise ValueError("The boxes tensor shape is not correct as Tensor[K, 5]") else: - assert False, "boxes is expected to be a Tensor[L, 5] or a List[Tensor[K, 4]]" + raise TypeError("boxes is expected to be a Tensor[L, 5] or a List[Tensor[K, 4]]") return diff --git a/torchvision/ops/feature_pyramid_network.py b/torchvision/ops/feature_pyramid_network.py index 93caa47d04b..2e1ac0cd8cf 100644 --- a/torchvision/ops/feature_pyramid_network.py +++ b/torchvision/ops/feature_pyramid_network.py @@ -95,7 +95,8 @@ def __init__( nn.init.constant_(m.bias, 0) if extra_blocks is not None: - assert isinstance(extra_blocks, ExtraFPNBlock) + if not isinstance(extra_blocks, ExtraFPNBlock): + raise TypeError(f"extra_blocks should be of type ExtraFPNBlock not {type(extra_blocks)}") self.extra_blocks = extra_blocks def get_result_from_inner_blocks(self, x: Tensor, idx: int) -> Tensor: diff --git a/torchvision/ops/poolers.py b/torchvision/ops/poolers.py index ceabb77732b..db9e6faa55f 100644 --- a/torchvision/ops/poolers.py +++ b/torchvision/ops/poolers.py @@ -112,7 +112,8 @@ def _infer_scale(feature: Tensor, original_size: List[int]) -> float: def _setup_scales( features: List[Tensor], image_shapes: List[Tuple[int, int]], canonical_scale: int, canonical_level: int ) -> Tuple[List[float], LevelMapper]: - assert len(image_shapes) != 0 + if len(image_shapes) == 0: + raise ValueError("images list should not be empty") max_x = 0 max_y = 0 for shape in image_shapes: @@ -150,8 +151,8 @@ def _multiscale_roi_align( boxes: List[Tensor], output_size: List[int], sampling_ratio: int, - scales: Optional[List[float]], - mapper: Optional[LevelMapper], + scales: List[float], + mapper: LevelMapper, ) -> Tensor: """ Args: @@ -161,14 +162,11 @@ def _multiscale_roi_align( reference. The coordinate must satisfy ``0 <= x1 < x2`` and ``0 <= y1 < y2``. output_size (Union[List[Tuple[int, int]], List[int]]): size of the output sampling_ratio (int): sampling ratio for ROIAlign - scales (Optional[List[float]]): If None, scales will be automatically infered. Default value is None. - mapper (Optional[LevelMapper]): If none, mapper will be automatically infered. Default value is None. + scales (List[float]): scales list + mapper (LevelMapper): level mapper Returns: result (Tensor) """ - assert scales is not None - assert mapper is not None - num_levels = len(x_filtered) rois = _convert_to_roi_format(boxes) diff --git a/torchvision/transforms/_functional_video.py b/torchvision/transforms/_functional_video.py index 2ab7adb8af9..479e76e634c 100644 --- a/torchvision/transforms/_functional_video.py +++ b/torchvision/transforms/_functional_video.py @@ -24,12 +24,14 @@ def crop(clip, i, j, h, w): Args: clip (torch.tensor): Video clip to be cropped. Size is (C, T, H, W) """ - assert len(clip.size()) == 4, "clip should be a 4D tensor" + if not len(clip.size()) == 4: + raise ValueError("clip should be a 4D tensor") return clip[..., i : i + h, j : j + w] def resize(clip, target_size, interpolation_mode): - assert len(target_size) == 2, "target size should be tuple (height, width)" + if not len(target_size) == 2: + raise ValueError("target size should be tuple (height, width)") return torch.nn.functional.interpolate(clip, size=target_size, mode=interpolation_mode, align_corners=False) @@ -46,17 +48,20 @@ def resized_crop(clip, i, j, h, w, size, interpolation_mode="bilinear"): Returns: clip (torch.tensor): Resized and cropped clip. Size is (C, T, H, W) """ - assert _is_tensor_video_clip(clip), "clip should be a 4D torch.tensor" + if not _is_tensor_video_clip(clip): + raise ValueError("clip should be a 4D torch.tensor") clip = crop(clip, i, j, h, w) clip = resize(clip, size, interpolation_mode) return clip def center_crop(clip, crop_size): - assert _is_tensor_video_clip(clip), "clip should be a 4D torch.tensor" + if not _is_tensor_video_clip(clip): + raise ValueError("clip should be a 4D torch.tensor") h, w = clip.size(-2), clip.size(-1) th, tw = crop_size - assert h >= th and w >= tw, "height and width must be no smaller than crop_size" + if not h >= th and w >= tw: + raise ValueError("height and width must be no smaller than crop_size") i = int(round((h - th) / 2.0)) j = int(round((w - tw) / 2.0)) @@ -87,7 +92,8 @@ def normalize(clip, mean, std, inplace=False): Returns: normalized clip (torch.tensor): Size is (C, T, H, W) """ - assert _is_tensor_video_clip(clip), "clip should be a 4D torch.tensor" + if not _is_tensor_video_clip(clip): + raise ValueError("clip should be a 4D torch.tensor") if not inplace: clip = clip.clone() mean = torch.as_tensor(mean, dtype=clip.dtype, device=clip.device) @@ -103,5 +109,6 @@ def hflip(clip): Returns: flipped clip (torch.tensor): Size is (C, T, H, W) """ - assert _is_tensor_video_clip(clip), "clip should be a 4D torch.tensor" + if not _is_tensor_video_clip(clip): + raise ValueError("clip should be a 4D torch.tensor") return clip.flip(-1) diff --git a/torchvision/transforms/_transforms_video.py b/torchvision/transforms/_transforms_video.py index 4a36c8abbf9..f686dbcbcf1 100644 --- a/torchvision/transforms/_transforms_video.py +++ b/torchvision/transforms/_transforms_video.py @@ -59,7 +59,8 @@ def __init__( interpolation_mode="bilinear", ): if isinstance(size, tuple): - assert len(size) == 2, "size should be tuple (height, width)" + if not len(size) == 2: + raise ValueError("size should be tuple (height, width)") self.size = size else: self.size = (size, size) diff --git a/torchvision/utils.py b/torchvision/utils.py index 6d3293d103d..6f1021e00ce 100644 --- a/torchvision/utils.py +++ b/torchvision/utils.py @@ -2,7 +2,7 @@ import pathlib import warnings from types import FunctionType -from typing import Any, BinaryIO, List, Optional, Tuple, Union +from typing import Any, BinaryIO, List, Optional, Tuple, Type, Union import numpy as np import torch @@ -82,10 +82,8 @@ def make_grid( if normalize is True: tensor = tensor.clone() # avoid modifying tensor in-place - if value_range is not None: - assert isinstance( - value_range, tuple - ), "value_range has to be a tuple (min, max) if specified. min and max are numbers" + if value_range is not None and not isinstance(value_range, tuple): + raise TypeError("value_range has to be a tuple (min, max) if specified. min and max are numbers") def norm_ip(img, low, high): img.clamp_(min=low, max=high) @@ -103,7 +101,8 @@ def norm_range(t, value_range): else: norm_range(tensor, value_range) - assert isinstance(tensor, torch.Tensor) + if not isinstance(tensor, torch.Tensor): + raise ValueError("tensor should be of type torch.Tensor") if tensor.size(0) == 1: return tensor.squeeze(0) From 40d0528a6f70078d6eb142e0a160df8a25a9cec2 Mon Sep 17 00:00:00 2001 From: Joao Gomes Date: Thu, 10 Mar 2022 21:37:29 +0000 Subject: [PATCH 02/49] fix formating issues --- references/detection/coco_utils.py | 6 ++++-- references/optical_flow/transforms.py | 4 ++-- references/optical_flow/utils.py | 4 +++- references/segmentation/coco_utils.py | 4 +++- references/segmentation/utils.py | 4 +++- references/video_classification/utils.py | 4 +++- torchvision/io/_video_opt.py | 4 +++- torchvision/models/detection/faster_rcnn.py | 12 +++++++++--- torchvision/models/detection/fcos.py | 8 ++++++-- torchvision/models/detection/keypoint_rcnn.py | 4 +++- torchvision/models/detection/mask_rcnn.py | 4 +++- torchvision/models/detection/retinanet.py | 4 +++- torchvision/models/feature_extraction.py | 18 ++++++++++++------ torchvision/models/optical_flow/raft.py | 10 +++++++--- torchvision/ops/poolers.py | 2 +- 15 files changed, 65 insertions(+), 27 deletions(-) diff --git a/references/detection/coco_utils.py b/references/detection/coco_utils.py index 39e3affdffa..00ec08cb17f 100644 --- a/references/detection/coco_utils.py +++ b/references/detection/coco_utils.py @@ -100,7 +100,7 @@ def __call__(self, image, target): return image, target -def _coco_remove_images_without_annotations(dataset: torchvision.datasets.CocoDetection, cat_list: list = None): +def _coco_remove_images_without_annotations(dataset: torchvision.datasets.CocoDetection, cat_list: list = None): def _has_only_empty_bbox(anno): return all(any(o <= 1 for o in obj["bbox"][2:]) for obj in anno) @@ -127,7 +127,9 @@ def _has_valid_annotation(anno): return False if not isinstance(dataset, torchvision.datasets.CocoDetection): - raise TypeError(f"This function expects dataset of type torchvision.datasets.CocoDetection, instead got {type(dataset)}") + raise TypeError( + f"This function expects dataset of type torchvision.datasets.CocoDetection, instead got {type(dataset)}" + ) ids = [] for ds_idx, img_id in enumerate(dataset.ids): ann_ids = dataset.coco.getAnnIds(imgIds=img_id, iscrowd=None) diff --git a/references/optical_flow/transforms.py b/references/optical_flow/transforms.py index 3986f021c6b..e40b57a933f 100644 --- a/references/optical_flow/transforms.py +++ b/references/optical_flow/transforms.py @@ -1,4 +1,5 @@ from multiprocessing.sharedctypes import Value + import torch import torchvision.transforms as T import torchvision.transforms.functional as F @@ -9,11 +10,10 @@ class ValidateModelInput(torch.nn.Module): def forward(self, img1, img2, flow, valid_flow_mask): if not all(isinstance(arg, torch.Tensor) for arg in (img1, img2, flow, valid_flow_mask) if arg is not None): - raise TypeError("This method expects all input arguments to be of type torch.Tensor.") + raise TypeError("This method expects all input arguments to be of type torch.Tensor.") if not all(arg.dtype == torch.float32 for arg in (img1, img2, flow) if arg is not None): raise TypeError(f"This method expects the tensors img1, img2 and flow of be of dtype torch.float32.") - if not img1.shape == img2.shape: raise ValueError("img1 and img2 should have the same shape.") h, w = img1.shape[-2:] diff --git a/references/optical_flow/utils.py b/references/optical_flow/utils.py index 3d04df3cbd5..e2b3a583fa9 100644 --- a/references/optical_flow/utils.py +++ b/references/optical_flow/utils.py @@ -72,7 +72,9 @@ def update(self, **kwargs): if isinstance(v, torch.Tensor): v = v.item() if not isinstance(v, (float, int)): - raise TypeError(f"This method expects the value of the input arguments to be of type float or int, instead got {type(v)}") + raise TypeError( + f"This method expects the value of the input arguments to be of type float or int, instead got {type(v)}" + ) self.meters[k].update(v) def __getattr__(self, attr): diff --git a/references/segmentation/coco_utils.py b/references/segmentation/coco_utils.py index 1f6ea4c024e..e02434012f1 100644 --- a/references/segmentation/coco_utils.py +++ b/references/segmentation/coco_utils.py @@ -69,7 +69,9 @@ def _has_valid_annotation(anno): return sum(obj["area"] for obj in anno) > 1000 if not isinstance(dataset, torchvision.datasets.CocoDetection): - raise TypeError(f"This function expects dataset of type torchvision.datasets.CocoDetection, instead got {type(dataset)}") + raise TypeError( + f"This function expects dataset of type torchvision.datasets.CocoDetection, instead got {type(dataset)}" + ) ids = [] for ds_idx, img_id in enumerate(dataset.ids): diff --git a/references/segmentation/utils.py b/references/segmentation/utils.py index bf4131ab19e..27c8f4ce51e 100644 --- a/references/segmentation/utils.py +++ b/references/segmentation/utils.py @@ -119,7 +119,9 @@ def update(self, **kwargs): if isinstance(v, torch.Tensor): v = v.item() if not isinstance(v, (float, int)): - raise TypeError(f"This method expects the value of the input arguments to be of type float or int, instead got {type(v)}") + raise TypeError( + f"This method expects the value of the input arguments to be of type float or int, instead got {type(v)}" + ) self.meters[k].update(v) def __getattr__(self, attr): diff --git a/references/video_classification/utils.py b/references/video_classification/utils.py index 12fd4f3e388..116adf8d72f 100644 --- a/references/video_classification/utils.py +++ b/references/video_classification/utils.py @@ -77,7 +77,9 @@ def update(self, **kwargs): if isinstance(v, torch.Tensor): v = v.item() if not isinstance(v, (float, int)): - raise TypeError(f"This method expects the value of the input arguments to be of type float or int, instead got {type(v)}") + raise TypeError( + f"This method expects the value of the input arguments to be of type float or int, instead got {type(v)}" + ) self.meters[k].update(v) def __getattr__(self, attr): diff --git a/torchvision/io/_video_opt.py b/torchvision/io/_video_opt.py index b5c830cf232..50cf30b3390 100644 --- a/torchvision/io/_video_opt.py +++ b/torchvision/io/_video_opt.py @@ -68,7 +68,9 @@ def __init__(self) -> None: def _validate_pts(pts_range: Tuple[int, int]) -> None: if pts_range[1] > 0 and not (pts_range[0] <= pts_range[1]): - raise ValueError(f"Start pts should not be smaller than end pts, got start pts: {pts_range[0]} and end pts: {pts_range[1]}") + raise ValueError( + f"Start pts should not be smaller than end pts, got start pts: {pts_range[0]} and end pts: {pts_range[1]}" + ) def _fill_info( diff --git a/torchvision/models/detection/faster_rcnn.py b/torchvision/models/detection/faster_rcnn.py index 1367cfda7c2..ce5eb55c7b1 100644 --- a/torchvision/models/detection/faster_rcnn.py +++ b/torchvision/models/detection/faster_rcnn.py @@ -188,9 +188,13 @@ def __init__( ) if not isinstance(rpn_anchor_generator, (AnchorGenerator, type(None))): - raise TypeError(f"rpn_anchor_generator should be of type AnchorGenerator or None instead of {type(rpn_anchor_generator)}") + raise TypeError( + f"rpn_anchor_generator should be of type AnchorGenerator or None instead of {type(rpn_anchor_generator)}" + ) if not isinstance(box_roi_pool, (MultiScaleRoIAlign, type(None))): - raise TypeError(f"box_roi_pool should be of type MultiScaleRoIAlign or None instead of {type(box_roi_pool)}") + raise TypeError( + f"box_roi_pool should be of type MultiScaleRoIAlign or None instead of {type(box_roi_pool)}" + ) if num_classes is not None: if box_predictor is not None: @@ -302,7 +306,9 @@ def __init__(self, in_channels, num_classes): def forward(self, x): if x.dim() == 4: if not list(x.shape[2:]) == [1, 1]: - raise ValueError(f"x has the wrong shape, expecting the last two dimensions to be [1,1] instead of {list(x.shape[2:])}") + raise ValueError( + f"x has the wrong shape, expecting the last two dimensions to be [1,1] instead of {list(x.shape[2:])}" + ) x = x.flatten(start_dim=1) scores = self.cls_score(x) bbox_deltas = self.bbox_pred(x) diff --git a/torchvision/models/detection/fcos.py b/torchvision/models/detection/fcos.py index 19b41c0464f..9a133d78d2e 100644 --- a/torchvision/models/detection/fcos.py +++ b/torchvision/models/detection/fcos.py @@ -379,7 +379,9 @@ def __init__( self.backbone = backbone if not isinstance(anchor_generator, (AnchorGenerator, type(None))): - raise TypeError(f"anchor_generator should be of type AnchorGenerator or None, instead got {type(anchor_generator)}") + raise TypeError( + f"anchor_generator should be of type AnchorGenerator or None, instead got {type(anchor_generator)}" + ) if anchor_generator is None: anchor_sizes = ((8,), (16,), (32,), (64,), (128,)) # equal to strides of multi-level feature map @@ -387,7 +389,9 @@ def __init__( anchor_generator = AnchorGenerator(anchor_sizes, aspect_ratios) self.anchor_generator = anchor_generator if not self.anchor_generator.num_anchors_per_location()[0] == 1: - raise ValueError(f"anchor_generator.num_anchors_per_location()[0] should be 1 instead of {anchor_generator.num_anchors_per_location()[0]}") + raise ValueError( + f"anchor_generator.num_anchors_per_location()[0] should be 1 instead of {anchor_generator.num_anchors_per_location()[0]}" + ) if head is None: head = FCOSHead(backbone.out_channels, anchor_generator.num_anchors_per_location()[0], num_classes) diff --git a/torchvision/models/detection/keypoint_rcnn.py b/torchvision/models/detection/keypoint_rcnn.py index f8931be361c..aadd390afc8 100644 --- a/torchvision/models/detection/keypoint_rcnn.py +++ b/torchvision/models/detection/keypoint_rcnn.py @@ -192,7 +192,9 @@ def __init__( ): if not isinstance(keypoint_roi_pool, (MultiScaleRoIAlign, type(None))): - raise TypeError("keypoint_roi_pool should be of type MultiScaleRoIAlign or None instead of {type(keypoint_roi_pool)}") + raise TypeError( + "keypoint_roi_pool should be of type MultiScaleRoIAlign or None instead of {type(keypoint_roi_pool)}" + ) if min_size is None: min_size = (640, 672, 704, 736, 768, 800) diff --git a/torchvision/models/detection/mask_rcnn.py b/torchvision/models/detection/mask_rcnn.py index 7b6ebb8d4cb..c733613452a 100644 --- a/torchvision/models/detection/mask_rcnn.py +++ b/torchvision/models/detection/mask_rcnn.py @@ -192,7 +192,9 @@ def __init__( ): if not isinstance(mask_roi_pool, (MultiScaleRoIAlign, type(None))): - raise TypeError(f"mask_roi_pool should be of type MultiScaleRoIAlign or None instead of {type(mask_roi_pool)}") + raise TypeError( + f"mask_roi_pool should be of type MultiScaleRoIAlign or None instead of {type(mask_roi_pool)}" + ) if num_classes is not None: if mask_predictor is not None: diff --git a/torchvision/models/detection/retinanet.py b/torchvision/models/detection/retinanet.py index 61ded072968..2c739e8de5e 100644 --- a/torchvision/models/detection/retinanet.py +++ b/torchvision/models/detection/retinanet.py @@ -348,7 +348,9 @@ def __init__( self.backbone = backbone if not isinstance(anchor_generator, (AnchorGenerator, type(None))): - raise TypeError(f"anchor_generator should be of type AnchorGenerator or None instead of {type(anchor_generator)}") + raise TypeError( + f"anchor_generator should be of type AnchorGenerator or None instead of {type(anchor_generator)}" + ) if anchor_generator is None: anchor_sizes = tuple((x, int(x * 2 ** (1.0 / 3)), int(x * 2 ** (2.0 / 3))) for x in [32, 64, 128, 256, 512]) diff --git a/torchvision/models/feature_extraction.py b/torchvision/models/feature_extraction.py index 285f5238e23..7ecd3cf160f 100644 --- a/torchvision/models/feature_extraction.py +++ b/torchvision/models/feature_extraction.py @@ -278,7 +278,7 @@ def __init__( for node in chain(iter(train_graph.nodes), iter(eval_graph.nodes)): if node.op in ["get_attr", "call_module"]: if not isinstance(node.target, str): - raise TypeError(f"node.target should be of type str instead of {type(node.target)}") + raise TypeError(f"node.target should be of type str instead of {type(node.target)}") _copy_attr(root, self, node.target) # train mode by default @@ -432,13 +432,19 @@ def create_feature_extractor( is_training = model.training if not any(arg is not None for arg in [return_nodes, train_return_nodes, eval_return_nodes]): - raise RuntimeError("Either `return_nodes` or `train_return_nodes` and `eval_return_nodes` together, should be specified") + raise RuntimeError( + "Either `return_nodes` or `train_return_nodes` and `eval_return_nodes` together, should be specified" + ) - if ((train_return_nodes is None) ^ (eval_return_nodes is None)): - raise RuntimeError("If any of `train_return_nodes` and `eval_return_nodes` are specified, then both should be specified") + if (train_return_nodes is None) ^ (eval_return_nodes is None): + raise RuntimeError( + "If any of `train_return_nodes` and `eval_return_nodes` are specified, then both should be specified" + ) if not (return_nodes is None) ^ (train_return_nodes is None): - raise RuntimeError("If `train_return_nodes` and `eval_return_nodes` are specified, then both should be specified") + raise RuntimeError( + "If `train_return_nodes` and `eval_return_nodes` are specified, then both should be specified" + ) # Put *_return_nodes into Dict[str, str] format def to_strdict(n) -> Dict[str, str]: @@ -494,7 +500,7 @@ def to_strdict(n) -> Dict[str, str]: for n in reversed(graph_module.graph.nodes): if n.op == "output": orig_output_nodes.append(n) - + for n in orig_output_nodes: graph_module.graph.erase_node(n) diff --git a/torchvision/models/optical_flow/raft.py b/torchvision/models/optical_flow/raft.py index 123833e95c8..15066942563 100644 --- a/torchvision/models/optical_flow/raft.py +++ b/torchvision/models/optical_flow/raft.py @@ -241,7 +241,7 @@ def __init__(self, *, input_size, hidden_size, kernel_size=((1, 5), (5, 1)), pad if not len(kernel_size) == len(padding): raise ValueError("kernel_size should have the same length as padding") if not len(kernel_size) in (1, 2): - raise + raise self.convgru1 = ConvGRU( input_size=input_size, hidden_size=hidden_size, kernel_size=kernel_size[0], padding=padding[0] @@ -392,7 +392,9 @@ def index_pyramid(self, centroids_coords): expected_output_shape = (batch_size, self.out_channels, h, w) if not corr_features.shape == expected_output_shape: - raise ValueError(f"Output shape of index pyramid is incorrect. Should be {expected_output_shape}, got {corr_features.shape}") + raise ValueError( + f"Output shape of index pyramid is incorrect. Should be {expected_output_shape}, got {corr_features.shape}" + ) return corr_features @@ -481,7 +483,9 @@ def forward(self, image1, image2, num_flow_updates: int = 12): hidden_state_size = self.update_block.hidden_state_size out_channels_context = context_out.shape[1] - hidden_state_size if not out_channels_context > 0: - raise ValueError(f"The context encoder outputs {context_out.shape[1]} channels, but it should have at strictly more than hidden_state={hidden_state_size} channels") + raise ValueError( + f"The context encoder outputs {context_out.shape[1]} channels, but it should have at strictly more than hidden_state={hidden_state_size} channels" + ) hidden_state, context = torch.split(context_out, [hidden_state_size, out_channels_context], dim=1) hidden_state = torch.tanh(hidden_state) context = F.relu(context) diff --git a/torchvision/ops/poolers.py b/torchvision/ops/poolers.py index db9e6faa55f..735d2a10de5 100644 --- a/torchvision/ops/poolers.py +++ b/torchvision/ops/poolers.py @@ -162,7 +162,7 @@ def _multiscale_roi_align( reference. The coordinate must satisfy ``0 <= x1 < x2`` and ``0 <= y1 < y2``. output_size (Union[List[Tuple[int, int]], List[int]]): size of the output sampling_ratio (int): sampling ratio for ROIAlign - scales (List[float]): scales list + scales (List[float]): scales list mapper (LevelMapper): level mapper Returns: result (Tensor) From 13bfd805d30e7f2fa06f5acab8cb2a836421d401 Mon Sep 17 00:00:00 2001 From: Joao Gomes Date: Fri, 11 Mar 2022 09:42:46 +0000 Subject: [PATCH 03/49] fix linting and remove more asserts --- references/optical_flow/transforms.py | 4 +--- torchvision/datasets/samplers/clip_sampler.py | 2 +- torchvision/models/detection/anchor_utils.py | 3 --- torchvision/models/detection/fcos.py | 7 ++++--- .../models/detection/generalized_rcnn.py | 6 ++++-- torchvision/models/detection/retinanet.py | 8 ++++---- torchvision/models/detection/roi_heads.py | 20 +++++-------------- torchvision/models/detection/ssd.py | 12 +++++++---- torchvision/models/detection/ssdlite.py | 5 ++++- torchvision/models/detection/transform.py | 5 ++++- torchvision/models/feature_extraction.py | 9 +++++---- torchvision/models/mnasnet.py | 6 +++--- torchvision/models/mobilenetv2.py | 2 +- torchvision/models/optical_flow/raft.py | 1 - torchvision/models/quantization/inception.py | 3 ++- .../models/quantization/mobilenetv2.py | 3 ++- torchvision/models/quantization/resnet.py | 3 ++- .../models/quantization/shufflenetv2.py | 3 ++- torchvision/models/shufflenetv2.py | 1 - torchvision/models/vision_transformer.py | 2 +- torchvision/ops/boxes.py | 6 ++++-- torchvision/ops/poolers.py | 1 - .../prototype/models/detection/ssdlite.py | 5 ++++- torchvision/utils.py | 2 +- 24 files changed, 62 insertions(+), 57 deletions(-) diff --git a/references/optical_flow/transforms.py b/references/optical_flow/transforms.py index e40b57a933f..e21e3005f40 100644 --- a/references/optical_flow/transforms.py +++ b/references/optical_flow/transforms.py @@ -1,5 +1,3 @@ -from multiprocessing.sharedctypes import Value - import torch import torchvision.transforms as T import torchvision.transforms.functional as F @@ -12,7 +10,7 @@ def forward(self, img1, img2, flow, valid_flow_mask): if not all(isinstance(arg, torch.Tensor) for arg in (img1, img2, flow, valid_flow_mask) if arg is not None): raise TypeError("This method expects all input arguments to be of type torch.Tensor.") if not all(arg.dtype == torch.float32 for arg in (img1, img2, flow) if arg is not None): - raise TypeError(f"This method expects the tensors img1, img2 and flow of be of dtype torch.float32.") + raise TypeError("This method expects the tensors img1, img2 and flow of be of dtype torch.float32.") if not img1.shape == img2.shape: raise ValueError("img1 and img2 should have the same shape.") diff --git a/torchvision/datasets/samplers/clip_sampler.py b/torchvision/datasets/samplers/clip_sampler.py index 0ac491f79e3..2c6f3f77c9e 100644 --- a/torchvision/datasets/samplers/clip_sampler.py +++ b/torchvision/datasets/samplers/clip_sampler.py @@ -52,7 +52,7 @@ def __init__( if not dist.is_available(): raise RuntimeError("Requires distributed package to be available") rank = dist.get_rank() - if not len(dataset) % group_size == 0 + if not len(dataset) % group_size == 0: raise ValueError(f"dataset length must be a multiplier of group size dataset length: {len(dataset)}, group size: {group_size}") self.dataset = dataset self.group_size = group_size diff --git a/torchvision/models/detection/anchor_utils.py b/torchvision/models/detection/anchor_utils.py index 12371f7d7e7..c04c557de14 100644 --- a/torchvision/models/detection/anchor_utils.py +++ b/torchvision/models/detection/anchor_utils.py @@ -45,8 +45,6 @@ def __init__( if not isinstance(aspect_ratios[0], (list, tuple)): aspect_ratios = (aspect_ratios,) * len(sizes) - assert len(sizes) == len(aspect_ratios) - self.sizes = sizes self.aspect_ratios = aspect_ratios self.cell_anchors = [ @@ -86,7 +84,6 @@ def num_anchors_per_location(self): def grid_anchors(self, grid_sizes: List[List[int]], strides: List[List[Tensor]]) -> List[Tensor]: anchors = [] cell_anchors = self.cell_anchors - assert cell_anchors is not None if not (len(grid_sizes) == len(strides) == len(cell_anchors)): raise ValueError( diff --git a/torchvision/models/detection/fcos.py b/torchvision/models/detection/fcos.py index 9a133d78d2e..4b13bba3234 100644 --- a/torchvision/models/detection/fcos.py +++ b/torchvision/models/detection/fcos.py @@ -571,7 +571,10 @@ def forward( original_image_sizes: List[Tuple[int, int]] = [] for img in images: val = img.shape[-2:] - assert len(val) == 2 + if not len(val) == 2: + raise ValueError( + f"expecting the last two dimensions of the Tensor to be H and W instead got {img.shape[-2:]}" + ) original_image_sizes.append((val[0], val[1])) # transform the input @@ -609,8 +612,6 @@ def forward( losses = {} detections: List[Dict[str, Tensor]] = [] if self.training: - assert targets is not None - # compute the losses losses = self.compute_loss(targets, head_outputs, anchors, num_anchors_per_level) else: diff --git a/torchvision/models/detection/generalized_rcnn.py b/torchvision/models/detection/generalized_rcnn.py index 37ef1820d71..c6c640cdab1 100644 --- a/torchvision/models/detection/generalized_rcnn.py +++ b/torchvision/models/detection/generalized_rcnn.py @@ -60,7 +60,6 @@ def forward(self, images, targets=None): if self.training and targets is None: raise ValueError("In training mode, targets should be passed") if self.training: - assert targets is not None for target in targets: boxes = target["boxes"] if isinstance(boxes, torch.Tensor): @@ -72,7 +71,10 @@ def forward(self, images, targets=None): original_image_sizes: List[Tuple[int, int]] = [] for img in images: val = img.shape[-2:] - assert len(val) == 2 + if not len(val) == 2: + raise ValueError( + f"Expecting the last two dimensions of the input tensor to be H and W, instead got {img.shape[-2:]}" + ) original_image_sizes.append((val[0], val[1])) images, targets = self.transform(images, targets) diff --git a/torchvision/models/detection/retinanet.py b/torchvision/models/detection/retinanet.py index 2c739e8de5e..dbe54fe6c8a 100644 --- a/torchvision/models/detection/retinanet.py +++ b/torchvision/models/detection/retinanet.py @@ -491,7 +491,6 @@ def forward(self, images, targets=None): raise ValueError("In training mode, targets should be passed") if self.training: - assert targets is not None for target in targets: boxes = target["boxes"] if isinstance(boxes, torch.Tensor): @@ -504,7 +503,10 @@ def forward(self, images, targets=None): original_image_sizes: List[Tuple[int, int]] = [] for img in images: val = img.shape[-2:] - assert len(val) == 2 + if not len(val) == 2: + raise ValueError( + f"Expecting the two last elements of the input tensors to be H and W instead got {img.shape[-2:]}" + ) original_image_sizes.append((val[0], val[1])) # transform the input @@ -542,8 +544,6 @@ def forward(self, images, targets=None): losses = {} detections: List[Dict[str, Tensor]] = [] if self.training: - assert targets is not None - # compute the losses losses = self.compute_loss(targets, head_outputs, anchors) else: diff --git a/torchvision/models/detection/roi_heads.py b/torchvision/models/detection/roi_heads.py index b8cf27e8953..fd482993439 100644 --- a/torchvision/models/detection/roi_heads.py +++ b/torchvision/models/detection/roi_heads.py @@ -1,5 +1,4 @@ -from multiprocessing.sharedctypes import Value -from typing import Optional, List, Dict, Tuple, Type +from typing import Optional, List, Dict, Tuple import torch import torch.nn.functional as F @@ -765,7 +764,10 @@ def forward( result: List[Dict[str, torch.Tensor]] = [] losses = {} if self.training: - assert labels is not None and regression_targets is not None + if labels is None: + raise RuntimeError("labels cannot be None") + if regression_targets is None: + raise RuntimeError("regression_targets cannot be None") loss_classifier, loss_box_reg = fastrcnn_loss(class_logits, box_regression, labels, regression_targets) losses = {"loss_classifier": loss_classifier, "loss_box_reg": loss_box_reg} else: @@ -783,7 +785,6 @@ def forward( if self.has_mask(): mask_proposals = [p["boxes"] for p in result] if self.training: - assert matched_idxs is not None # during training, only focus on positive boxes num_images = len(proposals) mask_proposals = [] @@ -804,10 +805,6 @@ def forward( loss_mask = {} if self.training: - assert targets is not None - assert pos_matched_idxs is not None - assert mask_logits is not None - gt_masks = [t["masks"] for t in targets] gt_labels = [t["labels"] for t in targets] rcnn_loss_mask = maskrcnn_loss(mask_logits, mask_proposals, gt_masks, gt_labels, pos_matched_idxs) @@ -833,7 +830,6 @@ def forward( num_images = len(proposals) keypoint_proposals = [] pos_matched_idxs = [] - assert matched_idxs is not None for img_id in range(num_images): pos = torch.where(labels[img_id] > 0)[0] keypoint_proposals.append(proposals[img_id][pos]) @@ -847,18 +843,12 @@ def forward( loss_keypoint = {} if self.training: - assert targets is not None - assert pos_matched_idxs is not None - gt_keypoints = [t["keypoints"] for t in targets] rcnn_loss_keypoint = keypointrcnn_loss( keypoint_logits, keypoint_proposals, gt_keypoints, pos_matched_idxs ) loss_keypoint = {"loss_keypoint": rcnn_loss_keypoint} else: - assert keypoint_logits is not None - assert keypoint_proposals is not None - keypoints_probs, kp_scores = keypointrcnn_inference(keypoint_logits, keypoint_proposals) for keypoint_prob, kps, r in zip(keypoints_probs, kp_scores, result): r["keypoints"] = keypoint_prob diff --git a/torchvision/models/detection/ssd.py b/torchvision/models/detection/ssd.py index 9d2e59641df..876f41cf399 100644 --- a/torchvision/models/detection/ssd.py +++ b/torchvision/models/detection/ssd.py @@ -196,7 +196,10 @@ def __init__( else: out_channels = det_utils.retrieve_out_channels(backbone, size) - assert len(out_channels) == len(anchor_generator.aspect_ratios) + if not len(out_channels) == len(anchor_generator.aspect_ratios): + raise RuntimeError( + f"The length of the output channels from the backbone {len(out_channels)} do not match the length of the anchor generator aspect ratios {len(anchor_generator.aspect_ratios)}" + ) num_anchors = self.anchor_generator.num_anchors_per_location() head = SSDHead(out_channels, num_anchors, num_classes) @@ -322,7 +325,10 @@ def forward( original_image_sizes: List[Tuple[int, int]] = [] for img in images: val = img.shape[-2:] - assert len(val) == 2 + if not len(val) == 2: + raise ValueError( + f"The last two dimensions of the input tensors should contain H and W, instead got {img.shape[-2:]}" + ) original_image_sizes.append((val[0], val[1])) # transform the input @@ -357,8 +363,6 @@ def forward( losses = {} detections: List[Dict[str, Tensor]] = [] if self.training: - assert targets is not None - matched_idxs = [] for anchors_per_image, targets_per_image in zip(anchors, targets): if targets_per_image["boxes"].numel() == 0: diff --git a/torchvision/models/detection/ssdlite.py b/torchvision/models/detection/ssdlite.py index a1cbaeafda9..4d30fa5ec63 100644 --- a/torchvision/models/detection/ssdlite.py +++ b/torchvision/models/detection/ssdlite.py @@ -247,7 +247,10 @@ def ssdlite320_mobilenet_v3_large( anchor_generator = DefaultBoxGenerator([[2, 3] for _ in range(6)], min_ratio=0.2, max_ratio=0.95) out_channels = det_utils.retrieve_out_channels(backbone, size) num_anchors = anchor_generator.num_anchors_per_location() - assert len(out_channels) == len(anchor_generator.aspect_ratios) + if not len(out_channels) == len(anchor_generator.aspect_ratios): + raise RuntimeError( + f"The length of the output channels from the backbone {len(out_channels)} do not match the length of the anchor generator aspect ratios {len(anchor_generator.aspect_ratios)}" + ) defaults = { "score_thresh": 0.001, diff --git a/torchvision/models/detection/transform.py b/torchvision/models/detection/transform.py index 960e28500a1..f9cd863658c 100644 --- a/torchvision/models/detection/transform.py +++ b/torchvision/models/detection/transform.py @@ -134,7 +134,10 @@ def forward( images = self.batch_images(images, size_divisible=self.size_divisible) image_sizes_list: List[Tuple[int, int]] = [] for image_size in image_sizes: - assert len(image_size) == 2 + if not len(image_size) == 2: + raise ValueError( + f"Input tensors expected to have in the last two elements H and W, instead got {image_size}" + ) image_sizes_list.append((image_size[0], image_size[1])) image_list = ImageList(images, image_sizes_list) diff --git a/torchvision/models/feature_extraction.py b/torchvision/models/feature_extraction.py index 7ecd3cf160f..85fb396274c 100644 --- a/torchvision/models/feature_extraction.py +++ b/torchvision/models/feature_extraction.py @@ -5,7 +5,7 @@ from collections import OrderedDict from copy import deepcopy from itertools import chain -from typing import Dict, Callable, List, Type, Union, Optional, Tuple, Any +from typing import Dict, Callable, List, Union, Optional, Tuple, Any import torch import torchvision @@ -479,9 +479,10 @@ def to_strdict(n) -> Dict[str, str]: available_nodes = list(tracer.node_to_qualname.values()) # FIXME We don't know if we should expect this to happen - assert len(set(available_nodes)) == len( - available_nodes - ), "There are duplicate nodes! Please raise an issue https://github.com/pytorch/vision/issues" + if len(set(available_nodes)) != len(available_nodes): + raise RuntimeError( + "There are duplicate nodes! Please raise an issue https://github.com/pytorch/vision/issues" + ) # Check that all outputs in return_nodes are present in the model for query in mode_return_nodes[mode].keys(): # To check if a query is available we need to check that at least diff --git a/torchvision/models/mnasnet.py b/torchvision/models/mnasnet.py index e9c7691121e..efc3f8af209 100644 --- a/torchvision/models/mnasnet.py +++ b/torchvision/models/mnasnet.py @@ -27,9 +27,9 @@ def __init__( self, in_ch: int, out_ch: int, kernel_size: int, stride: int, expansion_factor: int, bn_momentum: float = 0.1 ) -> None: super().__init__() - if not stride in [1, 2]: + if stride not in [1, 2]: raise ValueError(f"stride should be 1 or 2 instead of {stride}") - if not kernel_size in [3, 5]: + if kernel_size not in [3, 5]: raise ValueError(f"kernel_size should be 3 or 5 instead of {kernel_size}") mid_ch = in_ch * expansion_factor self.apply_residual = in_ch == out_ch and stride == 1 @@ -163,7 +163,7 @@ def _load_from_state_dict( error_msgs: List[str], ) -> None: version = local_metadata.get("version", None) - if not version in [1, 2]: + if version not in [1, 2]: raise ValueError(f"version shluld be set to 1 or 2 instead of {version}") if version == 1 and not self.alpha == 1.0: diff --git a/torchvision/models/mobilenetv2.py b/torchvision/models/mobilenetv2.py index 78f36546fd6..f65993b0a5a 100644 --- a/torchvision/models/mobilenetv2.py +++ b/torchvision/models/mobilenetv2.py @@ -44,7 +44,7 @@ def __init__( ) -> None: super().__init__() self.stride = stride - if not stride in [1, 2]: + if stride not in [1, 2]: raise ValueError(f"stride should be 1 or 2 insted of {stride}") if norm_layer is None: diff --git a/torchvision/models/optical_flow/raft.py b/torchvision/models/optical_flow/raft.py index 15066942563..9d38fa093f5 100644 --- a/torchvision/models/optical_flow/raft.py +++ b/torchvision/models/optical_flow/raft.py @@ -1,4 +1,3 @@ -from multiprocessing.sharedctypes import Value from typing import List import torch diff --git a/torchvision/models/quantization/inception.py b/torchvision/models/quantization/inception.py index 27d021428b9..6a9c56b3b6c 100644 --- a/torchvision/models/quantization/inception.py +++ b/torchvision/models/quantization/inception.py @@ -216,7 +216,8 @@ def inception_v3( backend = "fbgemm" quantize_model(model, backend) else: - assert pretrained in [True, False] + if pretrained not in [True, False]: + raise ValueError(f"For non quantized models, pretrained should be a bollean value instead of {pretrained}") if pretrained: if quantize: diff --git a/torchvision/models/quantization/mobilenetv2.py b/torchvision/models/quantization/mobilenetv2.py index 8cd9f16d13e..14b97c5ea98 100644 --- a/torchvision/models/quantization/mobilenetv2.py +++ b/torchvision/models/quantization/mobilenetv2.py @@ -88,7 +88,8 @@ def mobilenet_v2( backend = "qnnpack" quantize_model(model, backend) else: - assert pretrained in [True, False] + if pretrained not in [True, False]: + raise ValueError(f"For non quantized models, pretrained should be a bollean value instead of {pretrained}") if pretrained: if quantize: diff --git a/torchvision/models/quantization/resnet.py b/torchvision/models/quantization/resnet.py index f55aa0e103c..7102906aed6 100644 --- a/torchvision/models/quantization/resnet.py +++ b/torchvision/models/quantization/resnet.py @@ -125,7 +125,8 @@ def _resnet( backend = "fbgemm" quantize_model(model, backend) else: - assert pretrained in [True, False] + if pretrained not in [True, False]: + raise ValueError(f"For non quantized models, pretrained should be a bollean value instead of {pretrained}") if pretrained: if quantize: diff --git a/torchvision/models/quantization/shufflenetv2.py b/torchvision/models/quantization/shufflenetv2.py index 9d25315ffa0..deb7cb1c41e 100644 --- a/torchvision/models/quantization/shufflenetv2.py +++ b/torchvision/models/quantization/shufflenetv2.py @@ -89,7 +89,8 @@ def _shufflenetv2( backend = "fbgemm" quantize_model(model, backend) else: - assert pretrained in [True, False] + if pretrained not in [True, False]: + raise ValueError(f"For non quantized models, pretrained should be a bollean value instead of {pretrained}") if pretrained: model_url: Optional[str] = None diff --git a/torchvision/models/shufflenetv2.py b/torchvision/models/shufflenetv2.py index f3758c54aaf..5d195286b08 100644 --- a/torchvision/models/shufflenetv2.py +++ b/torchvision/models/shufflenetv2.py @@ -42,7 +42,6 @@ def __init__(self, inp: int, oup: int, stride: int) -> None: self.stride = stride branch_features = oup // 2 - assert (self.stride != 1) or (inp == branch_features << 1) if self.stride > 1: self.branch1 = nn.Sequential( diff --git a/torchvision/models/vision_transformer.py b/torchvision/models/vision_transformer.py index 9056b2549cf..fae07609bf0 100644 --- a/torchvision/models/vision_transformer.py +++ b/torchvision/models/vision_transformer.py @@ -77,7 +77,7 @@ def __init__( def forward(self, input: torch.Tensor): if not input.dim() == 3: - raise ValueError(f"Expected (seq_length, batch_size, hidden_dim) got {input.shape}")) + raise ValueError(f"Expected (seq_length, batch_size, hidden_dim) got {input.shape}") x = self.ln_1(input) x, _ = self.self_attention(query=x, key=x, value=x, need_weights=False) x = self.dropout(x) diff --git a/torchvision/ops/boxes.py b/torchvision/ops/boxes.py index 38cb4c1a836..56c56e88d30 100644 --- a/torchvision/ops/boxes.py +++ b/torchvision/ops/boxes.py @@ -300,8 +300,10 @@ def generalized_box_iou(boxes1: Tensor, boxes2: Tensor) -> Tensor: _log_api_usage_once(generalized_box_iou) # degenerate boxes gives inf / nan results # so do an early check - assert (boxes1[:, 2:] >= boxes1[:, :2]).all() - assert (boxes2[:, 2:] >= boxes2[:, :2]).all() + if not (boxes1[:, 2:] >= boxes1[:, :2]).all(): + raise ValueError("Some of the input boxes1 are invalid.") + if not (boxes2[:, 2:] >= boxes2[:, :2]).all(): + raise ValueError("Some of the input boxes2 are invalid.") inter, union = _box_inter_union(boxes1, boxes2) iou = inter / union diff --git a/torchvision/ops/poolers.py b/torchvision/ops/poolers.py index 735d2a10de5..778116a3c9c 100644 --- a/torchvision/ops/poolers.py +++ b/torchvision/ops/poolers.py @@ -104,7 +104,6 @@ def _infer_scale(feature: Tensor, original_size: List[int]) -> float: approx_scale = float(s1) / float(s2) scale = 2 ** float(torch.tensor(approx_scale).log2().round()) possible_scales.append(scale) - assert possible_scales[0] == possible_scales[1] return possible_scales[0] diff --git a/torchvision/prototype/models/detection/ssdlite.py b/torchvision/prototype/models/detection/ssdlite.py index 6de34acb5ae..db759b3e394 100644 --- a/torchvision/prototype/models/detection/ssdlite.py +++ b/torchvision/prototype/models/detection/ssdlite.py @@ -98,7 +98,10 @@ def ssdlite320_mobilenet_v3_large( anchor_generator = DefaultBoxGenerator([[2, 3] for _ in range(6)], min_ratio=0.2, max_ratio=0.95) out_channels = det_utils.retrieve_out_channels(backbone, size) num_anchors = anchor_generator.num_anchors_per_location() - assert len(out_channels) == len(anchor_generator.aspect_ratios) + if not len(out_channels) == len(anchor_generator.aspect_ratios): + raise RuntimeError( + f"The length of the output channels from the backbone {len(out_channels)} do not match the length of the anchor generator aspect ratios {len(anchor_generator.aspect_ratios)}" + ) defaults = { "score_thresh": 0.001, diff --git a/torchvision/utils.py b/torchvision/utils.py index 6f1021e00ce..73ca8c5ee71 100644 --- a/torchvision/utils.py +++ b/torchvision/utils.py @@ -2,7 +2,7 @@ import pathlib import warnings from types import FunctionType -from typing import Any, BinaryIO, List, Optional, Tuple, Type, Union +from typing import Any, BinaryIO, List, Optional, Tuple, Union import numpy as np import torch From f5223689d803b09fcabe67337d454e9bf4e13a9d Mon Sep 17 00:00:00 2001 From: Joao Gomes Date: Fri, 11 Mar 2022 10:09:52 +0000 Subject: [PATCH 04/49] fix regresion --- torchvision/ops/poolers.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/torchvision/ops/poolers.py b/torchvision/ops/poolers.py index 778116a3c9c..84b3011f7a2 100644 --- a/torchvision/ops/poolers.py +++ b/torchvision/ops/poolers.py @@ -150,8 +150,8 @@ def _multiscale_roi_align( boxes: List[Tensor], output_size: List[int], sampling_ratio: int, - scales: List[float], - mapper: LevelMapper, + scales: Optional[List[float]], + mapper: Optional[LevelMapper], ) -> Tensor: """ Args: @@ -161,8 +161,8 @@ def _multiscale_roi_align( reference. The coordinate must satisfy ``0 <= x1 < x2`` and ``0 <= y1 < y2``. output_size (Union[List[Tuple[int, int]], List[int]]): size of the output sampling_ratio (int): sampling ratio for ROIAlign - scales (List[float]): scales list - mapper (LevelMapper): level mapper + scales (Optional[List[float]]): If None, scales will be automatically infered. Default value is None. + mapper (Optional[LevelMapper]): If none, mapper will be automatically infered. Default value is None. Returns: result (Tensor) """ From 6a87e4dfb4e1bc352bb5bfc84aa1aa65dec06ccf Mon Sep 17 00:00:00 2001 From: Joao Gomes Date: Fri, 11 Mar 2022 10:26:14 +0000 Subject: [PATCH 05/49] fix regresion --- .../models/detection/generalized_rcnn.py | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/torchvision/models/detection/generalized_rcnn.py b/torchvision/models/detection/generalized_rcnn.py index c6c640cdab1..65bf5e6c96d 100644 --- a/torchvision/models/detection/generalized_rcnn.py +++ b/torchvision/models/detection/generalized_rcnn.py @@ -57,16 +57,17 @@ def forward(self, images, targets=None): like `scores`, `labels` and `mask` (for Mask R-CNN models). """ - if self.training and targets is None: - raise ValueError("In training mode, targets should be passed") if self.training: - for target in targets: - boxes = target["boxes"] - if isinstance(boxes, torch.Tensor): - if len(boxes.shape) != 2 or boxes.shape[-1] != 4: - raise ValueError(f"Expected target boxes to be a tensor of shape [N, 4], got {boxes.shape}.") - else: - raise ValueError(f"Expected target boxes to be of type Tensor, got {type(boxes)}.") + if and targets is None: + raise ValueError("In training mode, targets should be passed") + else: + for target in targets: + boxes = target["boxes"] + if isinstance(boxes, torch.Tensor): + if len(boxes.shape) != 2 or boxes.shape[-1] != 4: + raise ValueError(f"Expected target boxes to be a tensor of shape [N, 4], got {boxes.shape}.") + else: + raise ValueError(f"Expected target boxes to be of type Tensor, got {type(boxes)}.") original_image_sizes: List[Tuple[int, int]] = [] for img in images: From e179358c2b10f3a1bebe77131f04d4a46b479529 Mon Sep 17 00:00:00 2001 From: Joao Gomes Date: Fri, 11 Mar 2022 10:26:44 +0000 Subject: [PATCH 06/49] fix bug --- torchvision/models/detection/generalized_rcnn.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/torchvision/models/detection/generalized_rcnn.py b/torchvision/models/detection/generalized_rcnn.py index 65bf5e6c96d..6e1f4e90eaa 100644 --- a/torchvision/models/detection/generalized_rcnn.py +++ b/torchvision/models/detection/generalized_rcnn.py @@ -58,7 +58,7 @@ def forward(self, images, targets=None): """ if self.training: - if and targets is None: + if targets is None: raise ValueError("In training mode, targets should be passed") else: for target in targets: From 30b171436b0f0077cc6a3a9c97832f36a58758b4 Mon Sep 17 00:00:00 2001 From: Joao Gomes Date: Fri, 11 Mar 2022 11:02:14 +0000 Subject: [PATCH 07/49] apply ufmt --- references/detection/coco_utils.py | 2 +- torchvision/models/detection/ssd.py | 4 +- torchvision/models/optical_flow/raft.py | 2 +- torchvision/models/vision_transformer.py | 4 +- torchvision/ops/poolers.py | 103 ++++++++++++----------- 5 files changed, 59 insertions(+), 56 deletions(-) diff --git a/references/detection/coco_utils.py b/references/detection/coco_utils.py index 00ec08cb17f..396de63297b 100644 --- a/references/detection/coco_utils.py +++ b/references/detection/coco_utils.py @@ -100,7 +100,7 @@ def __call__(self, image, target): return image, target -def _coco_remove_images_without_annotations(dataset: torchvision.datasets.CocoDetection, cat_list: list = None): +def _coco_remove_images_without_annotations(dataset, cat_list=None): def _has_only_empty_bbox(anno): return all(any(o <= 1 for o in obj["bbox"][2:]) for obj in anno) diff --git a/torchvision/models/detection/ssd.py b/torchvision/models/detection/ssd.py index 876f41cf399..36c4d235718 100644 --- a/torchvision/models/detection/ssd.py +++ b/torchvision/models/detection/ssd.py @@ -198,7 +198,7 @@ def __init__( if not len(out_channels) == len(anchor_generator.aspect_ratios): raise RuntimeError( - f"The length of the output channels from the backbone {len(out_channels)} do not match the length of the anchor generator aspect ratios {len(anchor_generator.aspect_ratios)}" + f"The length of the output channels from the backbone ({len(out_channels)}) do not match the length of the anchor generator aspect ratios ({len(anchor_generator.aspect_ratios)})" ) num_anchors = self.anchor_generator.num_anchors_per_location() @@ -532,7 +532,7 @@ def _vgg_extractor(backbone: vgg.VGG, highres: bool, trainable_layers: int): num_stages = len(stage_indices) # find the index of the layer from which we wont freeze - if 0 <= trainable_layers <= num_stages: + if not 0 <= trainable_layers <= num_stages: raise ValueError(f"trainable_layers should be in the range [0, {num_stages}].") freeze_before = len(backbone) if trainable_layers == 0 else stage_indices[num_stages - trainable_layers] diff --git a/torchvision/models/optical_flow/raft.py b/torchvision/models/optical_flow/raft.py index 9d38fa093f5..6f8eedf82e6 100644 --- a/torchvision/models/optical_flow/raft.py +++ b/torchvision/models/optical_flow/raft.py @@ -240,7 +240,7 @@ def __init__(self, *, input_size, hidden_size, kernel_size=((1, 5), (5, 1)), pad if not len(kernel_size) == len(padding): raise ValueError("kernel_size should have the same length as padding") if not len(kernel_size) in (1, 2): - raise + raise ValueError("kernel_size should either 1 or 2") self.convgru1 = ConvGRU( input_size=input_size, hidden_size=hidden_size, kernel_size=kernel_size[0], padding=padding[0] diff --git a/torchvision/models/vision_transformer.py b/torchvision/models/vision_transformer.py index fae07609bf0..e357508259d 100644 --- a/torchvision/models/vision_transformer.py +++ b/torchvision/models/vision_transformer.py @@ -239,9 +239,9 @@ def __init__( def _process_input(self, x: torch.Tensor) -> torch.Tensor: n, c, h, w = x.shape p = self.patch_size - if not h == self.image_size: + if h != self.image_size: raise ValueError("Wrong image height!") - if not w == self.image_size: + if w != self.image_size: raise ValueError("Wrong image width!") n_h = h // p n_w = w // p diff --git a/torchvision/ops/poolers.py b/torchvision/ops/poolers.py index 84b3011f7a2..c1b72bc5a7e 100644 --- a/torchvision/ops/poolers.py +++ b/torchvision/ops/poolers.py @@ -166,63 +166,66 @@ def _multiscale_roi_align( Returns: result (Tensor) """ - num_levels = len(x_filtered) - rois = _convert_to_roi_format(boxes) - - if num_levels == 1: - return roi_align( - x_filtered[0], - rois, - output_size=output_size, - spatial_scale=scales[0], - sampling_ratio=sampling_ratio, - ) + if scales is None or mapper is None: + raise ValueError("scales and mapper should not be None") + else: + num_levels = len(x_filtered) + rois = _convert_to_roi_format(boxes) + + if num_levels == 1: + return roi_align( + x_filtered[0], + rois, + output_size=output_size, + spatial_scale=scales[0], + sampling_ratio=sampling_ratio, + ) - levels = mapper(boxes) + levels = mapper(boxes) - num_rois = len(rois) - num_channels = x_filtered[0].shape[1] + num_rois = len(rois) + num_channels = x_filtered[0].shape[1] - dtype, device = x_filtered[0].dtype, x_filtered[0].device - result = torch.zeros( - ( - num_rois, - num_channels, + dtype, device = x_filtered[0].dtype, x_filtered[0].device + result = torch.zeros( + ( + num_rois, + num_channels, + ) + + output_size, + dtype=dtype, + device=device, ) - + output_size, - dtype=dtype, - device=device, - ) - tracing_results = [] - for level, (per_level_feature, scale) in enumerate(zip(x_filtered, scales)): - idx_in_level = torch.where(levels == level)[0] - rois_per_level = rois[idx_in_level] - - result_idx_in_level = roi_align( - per_level_feature, - rois_per_level, - output_size=output_size, - spatial_scale=scale, - sampling_ratio=sampling_ratio, - ) + tracing_results = [] + for level, (per_level_feature, scale) in enumerate(zip(x_filtered, scales)): + idx_in_level = torch.where(levels == level)[0] + rois_per_level = rois[idx_in_level] + + result_idx_in_level = roi_align( + per_level_feature, + rois_per_level, + output_size=output_size, + spatial_scale=scale, + sampling_ratio=sampling_ratio, + ) + + if torchvision._is_tracing(): + tracing_results.append(result_idx_in_level.to(dtype)) + else: + # result and result_idx_in_level's dtypes are based on dtypes of different + # elements in x_filtered. x_filtered contains tensors output by different + # layers. When autocast is active, it may choose different dtypes for + # different layers' outputs. Therefore, we defensively match result's dtype + # before copying elements from result_idx_in_level in the following op. + # We need to cast manually (can't rely on autocast to cast for us) because + # the op acts on result in-place, and autocast only affects out-of-place ops. + result[idx_in_level] = result_idx_in_level.to(result.dtype) if torchvision._is_tracing(): - tracing_results.append(result_idx_in_level.to(dtype)) - else: - # result and result_idx_in_level's dtypes are based on dtypes of different - # elements in x_filtered. x_filtered contains tensors output by different - # layers. When autocast is active, it may choose different dtypes for - # different layers' outputs. Therefore, we defensively match result's dtype - # before copying elements from result_idx_in_level in the following op. - # We need to cast manually (can't rely on autocast to cast for us) because - # the op acts on result in-place, and autocast only affects out-of-place ops. - result[idx_in_level] = result_idx_in_level.to(result.dtype) - - if torchvision._is_tracing(): - result = _onnx_merge_levels(levels, tracing_results) - - return result + result = _onnx_merge_levels(levels, tracing_results) + + return result class MultiScaleRoIAlign(nn.Module): From 488d2afa55f9bc7a31153c70094c796c4e0490d5 Mon Sep 17 00:00:00 2001 From: Joao Gomes Date: Fri, 11 Mar 2022 11:02:34 +0000 Subject: [PATCH 08/49] apply ufmt --- torchvision/datasets/samplers/clip_sampler.py | 4 +++- torchvision/models/detection/generalized_rcnn.py | 4 +++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/torchvision/datasets/samplers/clip_sampler.py b/torchvision/datasets/samplers/clip_sampler.py index 2c6f3f77c9e..df23de1b317 100644 --- a/torchvision/datasets/samplers/clip_sampler.py +++ b/torchvision/datasets/samplers/clip_sampler.py @@ -53,7 +53,9 @@ def __init__( raise RuntimeError("Requires distributed package to be available") rank = dist.get_rank() if not len(dataset) % group_size == 0: - raise ValueError(f"dataset length must be a multiplier of group size dataset length: {len(dataset)}, group size: {group_size}") + raise ValueError( + f"dataset length must be a multiplier of group size dataset length: {len(dataset)}, group size: {group_size}" + ) self.dataset = dataset self.group_size = group_size self.num_replicas = num_replicas diff --git a/torchvision/models/detection/generalized_rcnn.py b/torchvision/models/detection/generalized_rcnn.py index 6e1f4e90eaa..0e996654b54 100644 --- a/torchvision/models/detection/generalized_rcnn.py +++ b/torchvision/models/detection/generalized_rcnn.py @@ -65,7 +65,9 @@ def forward(self, images, targets=None): boxes = target["boxes"] if isinstance(boxes, torch.Tensor): if len(boxes.shape) != 2 or boxes.shape[-1] != 4: - raise ValueError(f"Expected target boxes to be a tensor of shape [N, 4], got {boxes.shape}.") + raise ValueError( + f"Expected target boxes to be a tensor of shape [N, 4], got {boxes.shape}." + ) else: raise ValueError(f"Expected target boxes to be of type Tensor, got {type(boxes)}.") From 38d2d01b3b306d84500841d9d586e391d5c1e6a9 Mon Sep 17 00:00:00 2001 From: Joao Gomes Date: Fri, 11 Mar 2022 14:30:11 +0000 Subject: [PATCH 09/49] fix tests --- test/test_backbone_utils.py | 6 +++--- test/test_ops.py | 4 ++-- torchvision/models/detection/roi_heads.py | 19 +++++++++++-------- torchvision/models/feature_extraction.py | 6 ++++-- torchvision/models/vision_transformer.py | 15 +++++---------- 5 files changed, 25 insertions(+), 25 deletions(-) diff --git a/test/test_backbone_utils.py b/test/test_backbone_utils.py index ed9b52d0499..45183cda089 100644 --- a/test/test_backbone_utils.py +++ b/test/test_backbone_utils.py @@ -144,16 +144,16 @@ def test_build_fx_feature_extractor(self, model_name): model, train_return_nodes=train_return_nodes, eval_return_nodes=eval_return_nodes ) # Check must specify return nodes - with pytest.raises(AssertionError): + with pytest.raises(RuntimeError): self._create_feature_extractor(model) # Check return_nodes and train_return_nodes / eval_return nodes # mutual exclusivity - with pytest.raises(AssertionError): + with pytest.raises(RuntimeError): self._create_feature_extractor( model, return_nodes=train_return_nodes, train_return_nodes=train_return_nodes ) # Check train_return_nodes / eval_return nodes must both be specified - with pytest.raises(AssertionError): + with pytest.raises(RuntimeError): self._create_feature_extractor(model, train_return_nodes=train_return_nodes) # Check invalid node name raises ValueError with pytest.raises(ValueError): diff --git a/test/test_ops.py b/test/test_ops.py index ad9aaefee52..d1562b00a42 100644 --- a/test/test_ops.py +++ b/test/test_ops.py @@ -138,13 +138,13 @@ def test_autocast(self, x_dtype, rois_dtype): def _helper_boxes_shape(self, func): # test boxes as Tensor[N, 5] - with pytest.raises(AssertionError): + with pytest.raises(ValueError): a = torch.linspace(1, 8 * 8, 8 * 8).reshape(1, 1, 8, 8) boxes = torch.tensor([[0, 0, 3, 3]], dtype=a.dtype) func(a, boxes, output_size=(2, 2)) # test boxes as List[Tensor[N, 4]] - with pytest.raises(AssertionError): + with pytest.raises(ValueError): a = torch.linspace(1, 8 * 8, 8 * 8).reshape(1, 1, 8, 8) boxes = torch.tensor([[0, 0, 3]], dtype=a.dtype) ops.roi_pool(a, [boxes], output_size=(2, 2)) diff --git a/torchvision/models/detection/roi_heads.py b/torchvision/models/detection/roi_heads.py index fd482993439..12703e0a399 100644 --- a/torchvision/models/detection/roi_heads.py +++ b/torchvision/models/detection/roi_heads.py @@ -785,14 +785,17 @@ def forward( if self.has_mask(): mask_proposals = [p["boxes"] for p in result] if self.training: - # during training, only focus on positive boxes - num_images = len(proposals) - mask_proposals = [] - pos_matched_idxs = [] - for img_id in range(num_images): - pos = torch.where(labels[img_id] > 0)[0] - mask_proposals.append(proposals[img_id][pos]) - pos_matched_idxs.append(matched_idxs[img_id][pos]) + if not matched_idxs: + raise ValueError("if in trainning, matched_idxs should not be None") + else: + # during training, only focus on positive boxes + num_images = len(proposals) + mask_proposals = [] + pos_matched_idxs = [] + for img_id in range(num_images): + pos = torch.where(labels[img_id] > 0)[0] + mask_proposals.append(proposals[img_id][pos]) + pos_matched_idxs.append(matched_idxs[img_id][pos]) else: pos_matched_idxs = None diff --git a/torchvision/models/feature_extraction.py b/torchvision/models/feature_extraction.py index 85fb396274c..8d55c9ca8fd 100644 --- a/torchvision/models/feature_extraction.py +++ b/torchvision/models/feature_extraction.py @@ -432,16 +432,18 @@ def create_feature_extractor( is_training = model.training if not any(arg is not None for arg in [return_nodes, train_return_nodes, eval_return_nodes]): + raise RuntimeError( "Either `return_nodes` or `train_return_nodes` and `eval_return_nodes` together, should be specified" ) - if (train_return_nodes is None) ^ (eval_return_nodes is None): + + if ((train_return_nodes is None) ^ (eval_return_nodes is None)): raise RuntimeError( "If any of `train_return_nodes` and `eval_return_nodes` are specified, then both should be specified" ) - if not (return_nodes is None) ^ (train_return_nodes is None): + if not ((return_nodes is None) ^ (train_return_nodes is None)): raise RuntimeError( "If `train_return_nodes` and `eval_return_nodes` are specified, then both should be specified" ) diff --git a/torchvision/models/vision_transformer.py b/torchvision/models/vision_transformer.py index e357508259d..6528a0d8054 100644 --- a/torchvision/models/vision_transformer.py +++ b/torchvision/models/vision_transformer.py @@ -76,8 +76,7 @@ def __init__( self.mlp = MLPBlock(hidden_dim, mlp_dim, dropout) def forward(self, input: torch.Tensor): - if not input.dim() == 3: - raise ValueError(f"Expected (seq_length, batch_size, hidden_dim) got {input.shape}") + torch._assert(input.dim() == 3, f"Expected (seq_length, batch_size, hidden_dim) got {input.shape}") x = self.ln_1(input) x, _ = self.self_attention(query=x, key=x, value=x, need_weights=False) x = self.dropout(x) @@ -121,8 +120,7 @@ def __init__( self.ln = norm_layer(hidden_dim) def forward(self, input: torch.Tensor): - if not input.dim() == 3: - raise ValueError(f"Expected (batch_size, seq_length, hidden_dim) got {input.shape}") + torch._assert(input.dim() == 3, f"Expected (batch_size, seq_length, hidden_dim) got {input.shape}") input = input + self.pos_embedding return self.ln(self.layers(self.dropout(input))) @@ -147,8 +145,7 @@ def __init__( ): super().__init__() _log_api_usage_once(self) - if not image_size % patch_size == 0: - raise ValueError("Input shape indivisible by patch size!") + torch._assert(image_size % patch_size == 0, "Input shape indivisible by patch size!") self.image_size = image_size self.patch_size = patch_size self.hidden_dim = hidden_dim @@ -239,10 +236,8 @@ def __init__( def _process_input(self, x: torch.Tensor) -> torch.Tensor: n, c, h, w = x.shape p = self.patch_size - if h != self.image_size: - raise ValueError("Wrong image height!") - if w != self.image_size: - raise ValueError("Wrong image width!") + torch._assert(h == self.image_size, "Wrong image height!") + torch._assert(w == self.image_size, "Wrong image width!") n_h = h // p n_w = w // p From 7d425740204238a90623d784de65011b0067272f Mon Sep 17 00:00:00 2001 From: Joao Gomes Date: Fri, 11 Mar 2022 14:33:16 +0000 Subject: [PATCH 10/49] fix format --- torchvision/models/feature_extraction.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/torchvision/models/feature_extraction.py b/torchvision/models/feature_extraction.py index 8d55c9ca8fd..3609b5f7005 100644 --- a/torchvision/models/feature_extraction.py +++ b/torchvision/models/feature_extraction.py @@ -437,8 +437,7 @@ def create_feature_extractor( "Either `return_nodes` or `train_return_nodes` and `eval_return_nodes` together, should be specified" ) - - if ((train_return_nodes is None) ^ (eval_return_nodes is None)): + if (train_return_nodes is None) ^ (eval_return_nodes is None): raise RuntimeError( "If any of `train_return_nodes` and `eval_return_nodes` are specified, then both should be specified" ) From dc6856bddfa15281e703ece22bd5cc8e1f3854e3 Mon Sep 17 00:00:00 2001 From: Joao Gomes Date: Fri, 11 Mar 2022 14:47:29 +0000 Subject: [PATCH 11/49] fix None check --- torchvision/models/detection/roi_heads.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/torchvision/models/detection/roi_heads.py b/torchvision/models/detection/roi_heads.py index 12703e0a399..ff580187897 100644 --- a/torchvision/models/detection/roi_heads.py +++ b/torchvision/models/detection/roi_heads.py @@ -785,7 +785,7 @@ def forward( if self.has_mask(): mask_proposals = [p["boxes"] for p in result] if self.training: - if not matched_idxs: + if matched_idxs is None: raise ValueError("if in trainning, matched_idxs should not be None") else: # during training, only focus on positive boxes From 2c56adc07b1e70f3ae648e509ae7c834a913f015 Mon Sep 17 00:00:00 2001 From: Joao Gomes Date: Fri, 11 Mar 2022 15:20:29 +0000 Subject: [PATCH 12/49] fix detection models tests --- torchvision/models/detection/roi_heads.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/torchvision/models/detection/roi_heads.py b/torchvision/models/detection/roi_heads.py index ff580187897..5574f2943c1 100644 --- a/torchvision/models/detection/roi_heads.py +++ b/torchvision/models/detection/roi_heads.py @@ -808,6 +808,9 @@ def forward( loss_mask = {} if self.training: + if any(var is None for var in [targets, pos_matched_idxs, mask_logits]): + raise ValueError("targets, pos_matched_idxs, mask_logits cannot be None when training") + gt_masks = [t["masks"] for t in targets] gt_labels = [t["labels"] for t in targets] rcnn_loss_mask = maskrcnn_loss(mask_logits, mask_proposals, gt_masks, gt_labels, pos_matched_idxs) From aebca6d2ccd1b05a548e1fa6d1aee865be95b5c0 Mon Sep 17 00:00:00 2001 From: Joao Gomes Date: Fri, 11 Mar 2022 15:35:27 +0000 Subject: [PATCH 13/49] non scriptable any --- torchvision/models/detection/roi_heads.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/torchvision/models/detection/roi_heads.py b/torchvision/models/detection/roi_heads.py index 5574f2943c1..4043d59c842 100644 --- a/torchvision/models/detection/roi_heads.py +++ b/torchvision/models/detection/roi_heads.py @@ -808,7 +808,7 @@ def forward( loss_mask = {} if self.training: - if any(var is None for var in [targets, pos_matched_idxs, mask_logits]): + if targets is None or pos_matched_idxs is None or mask_logits is None: raise ValueError("targets, pos_matched_idxs, mask_logits cannot be None when training") gt_masks = [t["masks"] for t in targets] From d54b582a9a7380bf82caca3fbb87bac54770457a Mon Sep 17 00:00:00 2001 From: Joao Gomes Date: Sun, 13 Mar 2022 21:41:45 +0000 Subject: [PATCH 14/49] add more checks for None values --- torchvision/models/detection/anchor_utils.py | 51 +++++++++++--------- torchvision/models/detection/fcos.py | 5 +- torchvision/models/detection/roi_heads.py | 38 +++++++++------ torchvision/models/detection/ssd.py | 29 ++++++----- 4 files changed, 72 insertions(+), 51 deletions(-) diff --git a/torchvision/models/detection/anchor_utils.py b/torchvision/models/detection/anchor_utils.py index c04c557de14..9ef7c80bbb0 100644 --- a/torchvision/models/detection/anchor_utils.py +++ b/torchvision/models/detection/anchor_utils.py @@ -85,30 +85,33 @@ def grid_anchors(self, grid_sizes: List[List[int]], strides: List[List[Tensor]]) anchors = [] cell_anchors = self.cell_anchors - if not (len(grid_sizes) == len(strides) == len(cell_anchors)): - raise ValueError( - "Anchors should be Tuple[Tuple[int]] because each feature " - "map could potentially have different sizes and aspect ratios. " - "There needs to be a match between the number of " - "feature maps passed and the number of sizes / aspect ratios specified." - ) - - for size, stride, base_anchors in zip(grid_sizes, strides, cell_anchors): - grid_height, grid_width = size - stride_height, stride_width = stride - device = base_anchors.device - - # For output anchor, compute [x_center, y_center, x_center, y_center] - shifts_x = torch.arange(0, grid_width, dtype=torch.int32, device=device) * stride_width - shifts_y = torch.arange(0, grid_height, dtype=torch.int32, device=device) * stride_height - shift_y, shift_x = torch.meshgrid(shifts_y, shifts_x, indexing="ij") - shift_x = shift_x.reshape(-1) - shift_y = shift_y.reshape(-1) - shifts = torch.stack((shift_x, shift_y, shift_x, shift_y), dim=1) - - # For every (base anchor, output anchor) pair, - # offset each zero-centered base anchor by the center of the output anchor. - anchors.append((shifts.view(-1, 1, 4) + base_anchors.view(1, -1, 4)).reshape(-1, 4)) + if cell_anchors is None: + raise RuntimeError("cell_anchors should not be None") + else: + if not (len(grid_sizes) == len(strides) == len(cell_anchors)): + raise ValueError( + "Anchors should be Tuple[Tuple[int]] because each feature " + "map could potentially have different sizes and aspect ratios. " + "There needs to be a match between the number of " + "feature maps passed and the number of sizes / aspect ratios specified." + ) + + for size, stride, base_anchors in zip(grid_sizes, strides, cell_anchors): + grid_height, grid_width = size + stride_height, stride_width = stride + device = base_anchors.device + + # For output anchor, compute [x_center, y_center, x_center, y_center] + shifts_x = torch.arange(0, grid_width, dtype=torch.int32, device=device) * stride_width + shifts_y = torch.arange(0, grid_height, dtype=torch.int32, device=device) * stride_height + shift_y, shift_x = torch.meshgrid(shifts_y, shifts_x, indexing="ij") + shift_x = shift_x.reshape(-1) + shift_y = shift_y.reshape(-1) + shifts = torch.stack((shift_x, shift_y, shift_x, shift_y), dim=1) + + # For every (base anchor, output anchor) pair, + # offset each zero-centered base anchor by the center of the output anchor. + anchors.append((shifts.view(-1, 1, 4) + base_anchors.view(1, -1, 4)).reshape(-1, 4)) return anchors diff --git a/torchvision/models/detection/fcos.py b/torchvision/models/detection/fcos.py index 4b13bba3234..01ea7357268 100644 --- a/torchvision/models/detection/fcos.py +++ b/torchvision/models/detection/fcos.py @@ -613,7 +613,10 @@ def forward( detections: List[Dict[str, Tensor]] = [] if self.training: # compute the losses - losses = self.compute_loss(targets, head_outputs, anchors, num_anchors_per_level) + if targets is None: + raise ValueError("targets should not be none when in training mode") + else: + losses = self.compute_loss(targets, head_outputs, anchors, num_anchors_per_level) else: # split outputs per level split_head_outputs: Dict[str, List[Tensor]] = {} diff --git a/torchvision/models/detection/roi_heads.py b/torchvision/models/detection/roi_heads.py index 4043d59c842..552d2fc39e5 100644 --- a/torchvision/models/detection/roi_heads.py +++ b/torchvision/models/detection/roi_heads.py @@ -836,10 +836,13 @@ def forward( num_images = len(proposals) keypoint_proposals = [] pos_matched_idxs = [] - for img_id in range(num_images): - pos = torch.where(labels[img_id] > 0)[0] - keypoint_proposals.append(proposals[img_id][pos]) - pos_matched_idxs.append(matched_idxs[img_id][pos]) + if matched_idxs is None: + raise ValueError("if in trainning, matched_idxs should not be None") + else: + for img_id in range(num_images): + pos = torch.where(labels[img_id] > 0)[0] + keypoint_proposals.append(proposals[img_id][pos]) + pos_matched_idxs.append(matched_idxs[img_id][pos]) else: pos_matched_idxs = None @@ -849,17 +852,24 @@ def forward( loss_keypoint = {} if self.training: - gt_keypoints = [t["keypoints"] for t in targets] - rcnn_loss_keypoint = keypointrcnn_loss( - keypoint_logits, keypoint_proposals, gt_keypoints, pos_matched_idxs - ) - loss_keypoint = {"loss_keypoint": rcnn_loss_keypoint} + if targets is None or pos_matched_idxs is None: + raise ValueError("both targets and pos_matched_idxs should not be None when in training mode") + else: + gt_keypoints = [t["keypoints"] for t in targets] + rcnn_loss_keypoint = keypointrcnn_loss( + keypoint_logits, keypoint_proposals, gt_keypoints, pos_matched_idxs + ) + loss_keypoint = {"loss_keypoint": rcnn_loss_keypoint} else: - keypoints_probs, kp_scores = keypointrcnn_inference(keypoint_logits, keypoint_proposals) - for keypoint_prob, kps, r in zip(keypoints_probs, kp_scores, result): - r["keypoints"] = keypoint_prob - r["keypoints_scores"] = kps - + if keypoint_logits is None or keypoint_proposals is None: + raise ValueError( + "both keypoint_logits and keypoint_proposals should not be None when not in training mode" + ) + else: + keypoints_probs, kp_scores = keypointrcnn_inference(keypoint_logits, keypoint_proposals) + for keypoint_prob, kps, r in zip(keypoints_probs, kp_scores, result): + r["keypoints"] = keypoint_prob + r["keypoints_scores"] = kps losses.update(loss_keypoint) return result, losses diff --git a/torchvision/models/detection/ssd.py b/torchvision/models/detection/ssd.py index 36c4d235718..fe1c732ab3b 100644 --- a/torchvision/models/detection/ssd.py +++ b/torchvision/models/detection/ssd.py @@ -363,18 +363,23 @@ def forward( losses = {} detections: List[Dict[str, Tensor]] = [] if self.training: - matched_idxs = [] - for anchors_per_image, targets_per_image in zip(anchors, targets): - if targets_per_image["boxes"].numel() == 0: - matched_idxs.append( - torch.full((anchors_per_image.size(0),), -1, dtype=torch.int64, device=anchors_per_image.device) - ) - continue - - match_quality_matrix = box_ops.box_iou(targets_per_image["boxes"], anchors_per_image) - matched_idxs.append(self.proposal_matcher(match_quality_matrix)) - - losses = self.compute_loss(targets, head_outputs, anchors, matched_idxs) + if targets is None: + raise ValueError("targets should not be None when in training mode") + else: + matched_idxs = [] + for anchors_per_image, targets_per_image in zip(anchors, targets): + if targets_per_image["boxes"].numel() == 0: + matched_idxs.append( + torch.full( + (anchors_per_image.size(0),), -1, dtype=torch.int64, device=anchors_per_image.device + ) + ) + continue + + match_quality_matrix = box_ops.box_iou(targets_per_image["boxes"], anchors_per_image) + matched_idxs.append(self.proposal_matcher(match_quality_matrix)) + + losses = self.compute_loss(targets, head_outputs, anchors, matched_idxs) else: detections = self.postprocess_detections(head_outputs, anchors, images.image_sizes) detections = self.transform.postprocess(detections, images.image_sizes, original_image_sizes) From 98c27023ec9cbe1a20a737f490e7077fe907e7b7 Mon Sep 17 00:00:00 2001 From: Joao Gomes Date: Sun, 13 Mar 2022 22:27:23 +0000 Subject: [PATCH 15/49] fix retinanet test --- torchvision/models/detection/retinanet.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/torchvision/models/detection/retinanet.py b/torchvision/models/detection/retinanet.py index dbe54fe6c8a..1e9f9f57d0f 100644 --- a/torchvision/models/detection/retinanet.py +++ b/torchvision/models/detection/retinanet.py @@ -491,6 +491,8 @@ def forward(self, images, targets=None): raise ValueError("In training mode, targets should be passed") if self.training: + if targets is None: + raise ValueError("In training mode, targets should be passed") for target in targets: boxes = target["boxes"] if isinstance(boxes, torch.Tensor): From 4900653708464790e117b63d79a1bf54ec6afa13 Mon Sep 17 00:00:00 2001 From: Joao Gomes Date: Sun, 13 Mar 2022 22:48:53 +0000 Subject: [PATCH 16/49] fix retinanet test --- torchvision/models/detection/retinanet.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/torchvision/models/detection/retinanet.py b/torchvision/models/detection/retinanet.py index 1e9f9f57d0f..5903171eb2a 100644 --- a/torchvision/models/detection/retinanet.py +++ b/torchvision/models/detection/retinanet.py @@ -546,6 +546,8 @@ def forward(self, images, targets=None): losses = {} detections: List[Dict[str, Tensor]] = [] if self.training: + if targets is None: + raise ValueError("In training mode, targets should be passed") # compute the losses losses = self.compute_loss(targets, head_outputs, anchors) else: From d5ccbf16843cd9fdc447d1fdc887182f3fbc908b Mon Sep 17 00:00:00 2001 From: Joao Gomes Date: Mon, 14 Mar 2022 11:31:39 +0000 Subject: [PATCH 17/49] Update references/classification/transforms.py Co-authored-by: Nicolas Hug --- references/classification/transforms.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/references/classification/transforms.py b/references/classification/transforms.py index ae01b4ddf18..2338d2eed30 100644 --- a/references/classification/transforms.py +++ b/references/classification/transforms.py @@ -25,7 +25,7 @@ def __init__(self, num_classes: int, p: float = 0.5, alpha: float = 1.0, inplace raise ValueError("Please provide a valid positive value for the num_classes.") if not alpha > 0: - raise ValueError("Alpha param can't be zero.") + raise ValueError("alpha param can't be zero.") self.num_classes = num_classes self.p = p From de2f4b71c6856a8c5a81598f37525410e0581f74 Mon Sep 17 00:00:00 2001 From: Joao Gomes Date: Mon, 14 Mar 2022 11:32:13 +0000 Subject: [PATCH 18/49] Update references/classification/transforms.py Co-authored-by: Nicolas Hug --- references/classification/transforms.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/references/classification/transforms.py b/references/classification/transforms.py index 2338d2eed30..ef99808c11a 100644 --- a/references/classification/transforms.py +++ b/references/classification/transforms.py @@ -22,7 +22,7 @@ class RandomMixup(torch.nn.Module): def __init__(self, num_classes: int, p: float = 0.5, alpha: float = 1.0, inplace: bool = False) -> None: super().__init__() if not num_classes > 0: - raise ValueError("Please provide a valid positive value for the num_classes.") + raise ValueError(f"Please provide a valid positive value for the num_classes. Got num_classes={num_classes}") if not alpha > 0: raise ValueError("alpha param can't be zero.") From 275012a9d36a6d4aee0062cd188498143e6a34df Mon Sep 17 00:00:00 2001 From: Joao Gomes Date: Mon, 14 Mar 2022 11:32:23 +0000 Subject: [PATCH 19/49] Update references/optical_flow/transforms.py Co-authored-by: Nicolas Hug --- references/optical_flow/transforms.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/references/optical_flow/transforms.py b/references/optical_flow/transforms.py index e21e3005f40..4b01dba319d 100644 --- a/references/optical_flow/transforms.py +++ b/references/optical_flow/transforms.py @@ -15,7 +15,7 @@ def forward(self, img1, img2, flow, valid_flow_mask): if not img1.shape == img2.shape: raise ValueError("img1 and img2 should have the same shape.") h, w = img1.shape[-2:] - if flow is not None and not flow.shape == (2, h, w): + if flow is not None and flow.shape != (2, h, w): raise ValueError(f"flow.shape should be (2, {h}, {w}) instead of {flow.shape}") if valid_flow_mask is not None: if not valid_flow_mask.shape == (h, w): From fddd2ac6ae023b7d5a32d198b9fdfda4b67f62c0 Mon Sep 17 00:00:00 2001 From: Joao Gomes Date: Mon, 14 Mar 2022 11:32:29 +0000 Subject: [PATCH 20/49] Update references/optical_flow/transforms.py Co-authored-by: Nicolas Hug --- references/optical_flow/transforms.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/references/optical_flow/transforms.py b/references/optical_flow/transforms.py index 4b01dba319d..39e1c15d0e7 100644 --- a/references/optical_flow/transforms.py +++ b/references/optical_flow/transforms.py @@ -20,7 +20,7 @@ def forward(self, img1, img2, flow, valid_flow_mask): if valid_flow_mask is not None: if not valid_flow_mask.shape == (h, w): raise ValueError(f"valid_flow_mask.shape should be ({h}, {w}) instead of {valid_flow_mask.shape}") - if not valid_flow_mask.dtype == torch.bool: + if valid_flow_mask.dtype != torch.bool: raise TypeError("valid_flow_mask should be of dtype torch.bool instead of {valid_flow_mask.dtype}") return img1, img2, flow, valid_flow_mask From 7e60b461d6ed87e8d7ed96eea24a7a401d4346ee Mon Sep 17 00:00:00 2001 From: Joao Gomes Date: Mon, 14 Mar 2022 11:32:36 +0000 Subject: [PATCH 21/49] Update references/optical_flow/transforms.py Co-authored-by: Nicolas Hug --- references/optical_flow/transforms.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/references/optical_flow/transforms.py b/references/optical_flow/transforms.py index 39e1c15d0e7..717b5adcad5 100644 --- a/references/optical_flow/transforms.py +++ b/references/optical_flow/transforms.py @@ -114,7 +114,7 @@ class RandomErasing(T.RandomErasing): def __init__(self, p=0.5, scale=(0.02, 0.33), ratio=(0.3, 3.3), value=0, inplace=False, max_erase=1): super().__init__(p=p, scale=scale, ratio=ratio, value=value, inplace=inplace) self.max_erase = max_erase - if not self.max_erase > 0: + if self.max_erase <= 0: raise ValueError("max_raise should be greater than 0") def forward(self, img1, img2, flow, valid_flow_mask): From 6c2e94ffab512338e4fdf8b72312bf5d3c509764 Mon Sep 17 00:00:00 2001 From: Joao Gomes Date: Mon, 14 Mar 2022 11:39:28 +0000 Subject: [PATCH 22/49] make value checks more pythonic: --- references/classification/transforms.py | 8 ++++---- torchvision/models/mnasnet.py | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/references/classification/transforms.py b/references/classification/transforms.py index ae01b4ddf18..6f9ba00744b 100644 --- a/references/classification/transforms.py +++ b/references/classification/transforms.py @@ -21,10 +21,10 @@ class RandomMixup(torch.nn.Module): def __init__(self, num_classes: int, p: float = 0.5, alpha: float = 1.0, inplace: bool = False) -> None: super().__init__() - if not num_classes > 0: + if num_classes <= 1: raise ValueError("Please provide a valid positive value for the num_classes.") - if not alpha > 0: + if alpha <= 0: raise ValueError("Alpha param can't be zero.") self.num_classes = num_classes @@ -102,9 +102,9 @@ class RandomCutmix(torch.nn.Module): def __init__(self, num_classes: int, p: float = 0.5, alpha: float = 1.0, inplace: bool = False) -> None: super().__init__() - if not num_classes > 0: + if num_classes <= 1: raise ValueError("Please provide a valid positive value for the num_classes.") - if not alpha > 0: + if alpha <= 0: raise ValueError("Alpha param can't be zero.") self.num_classes = num_classes diff --git a/torchvision/models/mnasnet.py b/torchvision/models/mnasnet.py index efc3f8af209..0b58e81f9e5 100644 --- a/torchvision/models/mnasnet.py +++ b/torchvision/models/mnasnet.py @@ -103,7 +103,7 @@ class MNASNet(torch.nn.Module): def __init__(self, alpha: float, num_classes: int = 1000, dropout: float = 0.2) -> None: super().__init__() _log_api_usage_once(self) - if not alpha > 0.0: + if alpha <= 0.0: raise ValueError(f"alpha should be greater than 0.0 instead of {alpha}") self.alpha = alpha self.num_classes = num_classes From cb95c97e02da50867ad6270e7f24676c64ef697b Mon Sep 17 00:00:00 2001 From: Joao Gomes Date: Mon, 14 Mar 2022 11:43:03 +0000 Subject: [PATCH 23/49] Update references/optical_flow/transforms.py Co-authored-by: Nicolas Hug --- references/optical_flow/transforms.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/references/optical_flow/transforms.py b/references/optical_flow/transforms.py index 717b5adcad5..357abeb0b38 100644 --- a/references/optical_flow/transforms.py +++ b/references/optical_flow/transforms.py @@ -18,7 +18,7 @@ def forward(self, img1, img2, flow, valid_flow_mask): if flow is not None and flow.shape != (2, h, w): raise ValueError(f"flow.shape should be (2, {h}, {w}) instead of {flow.shape}") if valid_flow_mask is not None: - if not valid_flow_mask.shape == (h, w): + if valid_flow_mask.shape != (h, w): raise ValueError(f"valid_flow_mask.shape should be ({h}, {w}) instead of {valid_flow_mask.shape}") if valid_flow_mask.dtype != torch.bool: raise TypeError("valid_flow_mask should be of dtype torch.bool instead of {valid_flow_mask.dtype}") From ff8f557acfbc9d3a5ab75d4aecd16c2ca3611b25 Mon Sep 17 00:00:00 2001 From: Joao Gomes Date: Mon, 14 Mar 2022 11:43:45 +0000 Subject: [PATCH 24/49] make value checks more pythonic --- references/optical_flow/transforms.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/references/optical_flow/transforms.py b/references/optical_flow/transforms.py index 717b5adcad5..0b1c2186596 100644 --- a/references/optical_flow/transforms.py +++ b/references/optical_flow/transforms.py @@ -12,7 +12,7 @@ def forward(self, img1, img2, flow, valid_flow_mask): if not all(arg.dtype == torch.float32 for arg in (img1, img2, flow) if arg is not None): raise TypeError("This method expects the tensors img1, img2 and flow of be of dtype torch.float32.") - if not img1.shape == img2.shape: + if img1.shape != img2.shape: raise ValueError("img1 and img2 should have the same shape.") h, w = img1.shape[-2:] if flow is not None and flow.shape != (2, h, w): From abafdb2775d99c6f4699abaa851042ce647238cf Mon Sep 17 00:00:00 2001 From: Joao Gomes Date: Mon, 14 Mar 2022 13:33:15 +0000 Subject: [PATCH 25/49] make more checks pythonic --- references/classification/transforms.py | 4 ++- references/similarity/sampler.py | 2 +- torchvision/datasets/mnist.py | 10 +++--- torchvision/datasets/samplers/clip_sampler.py | 2 +- torchvision/datasets/video_utils.py | 2 +- torchvision/io/_video_opt.py | 2 +- torchvision/models/detection/_utils.py | 2 +- torchvision/models/detection/faster_rcnn.py | 2 +- torchvision/models/detection/fcos.py | 4 +-- .../models/detection/generalized_rcnn.py | 2 +- torchvision/models/detection/retinanet.py | 2 +- torchvision/models/detection/roi_heads.py | 12 ++++--- torchvision/models/detection/ssd.py | 6 ++-- torchvision/models/detection/ssdlite.py | 2 +- torchvision/models/detection/transform.py | 2 +- torchvision/models/feature_extraction.py | 6 ++-- torchvision/models/googlenet.py | 2 +- torchvision/models/inception.py | 2 +- torchvision/models/mnasnet.py | 4 +-- torchvision/models/optical_flow/raft.py | 36 +++++++++---------- torchvision/models/vision_transformer.py | 6 ++-- torchvision/ops/_utils.py | 12 ++++--- .../prototype/models/detection/ssdlite.py | 2 +- torchvision/transforms/_functional_video.py | 8 ++--- torchvision/transforms/_transforms_video.py | 4 +-- 25 files changed, 74 insertions(+), 64 deletions(-) diff --git a/references/classification/transforms.py b/references/classification/transforms.py index d9118b88040..78c286579f9 100644 --- a/references/classification/transforms.py +++ b/references/classification/transforms.py @@ -23,7 +23,9 @@ def __init__(self, num_classes: int, p: float = 0.5, alpha: float = 1.0, inplace super().__init__() if num_classes <= 1: - raise ValueError(f"Please provide a valid positive value for the num_classes. Got num_classes={num_classes}") + raise ValueError( + f"Please provide a valid positive value for the num_classes. Got num_classes={num_classes}" + ) if alpha <= 0: raise ValueError("Alpha param can't be zero.") diff --git a/references/similarity/sampler.py b/references/similarity/sampler.py index bca29cf43ec..f4564eca33e 100644 --- a/references/similarity/sampler.py +++ b/references/similarity/sampler.py @@ -47,7 +47,7 @@ def __init__(self, groups, p, k): self.groups = create_groups(groups, self.k) # Ensures there are enough classes to sample from - if not len(self.groups) >= p: + if len(self.groups) < p: raise ValueError("There are not enought classes to sample from") def __iter__(self): diff --git a/torchvision/datasets/mnist.py b/torchvision/datasets/mnist.py index c283254ed77..98fa86b8dd2 100644 --- a/torchvision/datasets/mnist.py +++ b/torchvision/datasets/mnist.py @@ -442,13 +442,13 @@ def _check_exists(self) -> bool: def _load_data(self): data = read_sn3_pascalvincent_tensor(self.images_file) - if not data.dtype == torch.uint8: + if data.dtype != torch.uint8: raise TypeError(f"data should be of dtype torch.uint8 instead of {data.dtype}") - if not data.ndimension() == 3: + if data.ndimension() != 3: raise ValueError("data should have 3 dimensions instead of {data.ndimension()}") targets = read_sn3_pascalvincent_tensor(self.labels_file).long() - if not targets.ndimension() == 2: + if targets.ndimension() != 2: raise ValueError(f"targets should have 2 dimensions instead of {targets.ndimension()}") if self.what == "test10k": @@ -533,7 +533,7 @@ def read_sn3_pascalvincent_tensor(path: str, strict: bool = True) -> torch.Tenso def read_label_file(path: str) -> torch.Tensor: x = read_sn3_pascalvincent_tensor(path, strict=False) - if not x.dtype == torch.uint8: + if x.dtype != torch.uint8: raise TypeError(f"x should be of dtype torch.uint8 instead of {x.dtype}") if not x.ndimension() == 1: raise ValueError(f"x should have 1 dimension instead of {x.ndimension()}") @@ -542,7 +542,7 @@ def read_label_file(path: str) -> torch.Tensor: def read_image_file(path: str) -> torch.Tensor: x = read_sn3_pascalvincent_tensor(path, strict=False) - if not x.dtype == torch.uint8: + if x.dtype != torch.uint8: raise TypeError(f"x should be of dtype torch.uint8 instead of {x.dtype}") if not x.ndimension() == 3: raise ValueError(f"x should have 3 dimension instead of {x.ndimension()}") diff --git a/torchvision/datasets/samplers/clip_sampler.py b/torchvision/datasets/samplers/clip_sampler.py index df23de1b317..f4975f8c021 100644 --- a/torchvision/datasets/samplers/clip_sampler.py +++ b/torchvision/datasets/samplers/clip_sampler.py @@ -52,7 +52,7 @@ def __init__( if not dist.is_available(): raise RuntimeError("Requires distributed package to be available") rank = dist.get_rank() - if not len(dataset) % group_size == 0: + if len(dataset) % group_size != 0: raise ValueError( f"dataset length must be a multiplier of group size dataset length: {len(dataset)}, group size: {group_size}" ) diff --git a/torchvision/datasets/video_utils.py b/torchvision/datasets/video_utils.py index 826b4e19cf6..d444496ffe7 100644 --- a/torchvision/datasets/video_utils.py +++ b/torchvision/datasets/video_utils.py @@ -38,7 +38,7 @@ def unfold(tensor: torch.Tensor, size: int, step: int, dilation: int = 1) -> tor `step` between windows. The distance between each element in a window is given by `dilation`. """ - if not tensor.dim() == 1: + if tensor.dim() != 1: raise ValueError(f"tensor should have 1 dimension instead of {tensor.dim()}") o_stride = tensor.stride(0) numel = tensor.numel() diff --git a/torchvision/io/_video_opt.py b/torchvision/io/_video_opt.py index 50cf30b3390..48b9a2fb34a 100644 --- a/torchvision/io/_video_opt.py +++ b/torchvision/io/_video_opt.py @@ -67,7 +67,7 @@ def __init__(self) -> None: def _validate_pts(pts_range: Tuple[int, int]) -> None: - if pts_range[1] > 0 and not (pts_range[0] <= pts_range[1]): + if pts_range[1] > 0 and pts_range[0] > pts_range[1]: raise ValueError( f"Start pts should not be smaller than end pts, got start pts: {pts_range[0]} and end pts: {pts_range[1]}" ) diff --git a/torchvision/models/detection/_utils.py b/torchvision/models/detection/_utils.py index bc6912f80b2..d7126ef681b 100644 --- a/torchvision/models/detection/_utils.py +++ b/torchvision/models/detection/_utils.py @@ -335,7 +335,7 @@ def __init__(self, high_threshold: float, low_threshold: float, allow_low_qualit """ self.BELOW_LOW_THRESHOLD = -1 self.BETWEEN_THRESHOLDS = -2 - if not low_threshold <= high_threshold: + if low_threshold > high_threshold: raise ValueError("low_threshold should be <= high_threshold") self.high_threshold = high_threshold self.low_threshold = low_threshold diff --git a/torchvision/models/detection/faster_rcnn.py b/torchvision/models/detection/faster_rcnn.py index ce5eb55c7b1..35cb968d711 100644 --- a/torchvision/models/detection/faster_rcnn.py +++ b/torchvision/models/detection/faster_rcnn.py @@ -305,7 +305,7 @@ def __init__(self, in_channels, num_classes): def forward(self, x): if x.dim() == 4: - if not list(x.shape[2:]) == [1, 1]: + if list(x.shape[2:]) != [1, 1]: raise ValueError( f"x has the wrong shape, expecting the last two dimensions to be [1,1] instead of {list(x.shape[2:])}" ) diff --git a/torchvision/models/detection/fcos.py b/torchvision/models/detection/fcos.py index 01ea7357268..24db93ffc51 100644 --- a/torchvision/models/detection/fcos.py +++ b/torchvision/models/detection/fcos.py @@ -388,7 +388,7 @@ def __init__( aspect_ratios = ((1.0,),) * len(anchor_sizes) # set only one anchor anchor_generator = AnchorGenerator(anchor_sizes, aspect_ratios) self.anchor_generator = anchor_generator - if not self.anchor_generator.num_anchors_per_location()[0] == 1: + if self.anchor_generator.num_anchors_per_location()[0] != 1: raise ValueError( f"anchor_generator.num_anchors_per_location()[0] should be 1 instead of {anchor_generator.num_anchors_per_location()[0]}" ) @@ -571,7 +571,7 @@ def forward( original_image_sizes: List[Tuple[int, int]] = [] for img in images: val = img.shape[-2:] - if not len(val) == 2: + if not len(val) != 2: raise ValueError( f"expecting the last two dimensions of the Tensor to be H and W instead got {img.shape[-2:]}" ) diff --git a/torchvision/models/detection/generalized_rcnn.py b/torchvision/models/detection/generalized_rcnn.py index 0e996654b54..09b33fe6973 100644 --- a/torchvision/models/detection/generalized_rcnn.py +++ b/torchvision/models/detection/generalized_rcnn.py @@ -74,7 +74,7 @@ def forward(self, images, targets=None): original_image_sizes: List[Tuple[int, int]] = [] for img in images: val = img.shape[-2:] - if not len(val) == 2: + if not len(val) != 2: raise ValueError( f"Expecting the last two dimensions of the input tensor to be H and W, instead got {img.shape[-2:]}" ) diff --git a/torchvision/models/detection/retinanet.py b/torchvision/models/detection/retinanet.py index 5903171eb2a..bb295169a12 100644 --- a/torchvision/models/detection/retinanet.py +++ b/torchvision/models/detection/retinanet.py @@ -505,7 +505,7 @@ def forward(self, images, targets=None): original_image_sizes: List[Tuple[int, int]] = [] for img in images: val = img.shape[-2:] - if not len(val) == 2: + if not len(val) != 2: raise ValueError( f"Expecting the two last elements of the input tensors to be H and W instead got {img.shape[-2:]}" ) diff --git a/torchvision/models/detection/roi_heads.py b/torchvision/models/detection/roi_heads.py index 552d2fc39e5..949ff1e750f 100644 --- a/torchvision/models/detection/roi_heads.py +++ b/torchvision/models/detection/roi_heads.py @@ -299,8 +299,10 @@ def heatmaps_to_keypoints(maps, rois): def keypointrcnn_loss(keypoint_logits, proposals, gt_keypoints, keypoint_matched_idxs): # type: (Tensor, List[Tensor], List[Tensor], List[Tensor]) -> Tensor N, K, H, W = keypoint_logits.shape - if not H == W: - raise ValueError("keypoint_logits height and width (last two elements of shape) should be equal.") + if H != W: + raise ValueError( + f"keypoint_logits height and width (last two elements of shape) should be equal. Instead got H = {H} and W = {W}" + ) discretization_size = H heatmaps = [] valid = [] @@ -743,12 +745,12 @@ def forward( # TODO: https://github.com/pytorch/pytorch/issues/26731 floating_point_types = (torch.float, torch.double, torch.half) if not t["boxes"].dtype in floating_point_types: - raise TypeError("target boxes must of float type") + raise TypeError(f"target boxes must of float type, instead got {t['boxes'].dtype}") if not t["labels"].dtype == torch.int64: - raise TypeError("target labels must of int64 type") + raise TypeError("target labels must of int64 type, instead got {t['labels'].dtype}") if self.has_keypoint(): if not t["keypoints"].dtype == torch.float32: - raise TypeError("target keypoints must of float type") + raise TypeError(f"target keypoints must of float type, instead got {t['keypoints'].dtype}") if self.training: proposals, matched_idxs, labels, regression_targets = self.select_training_samples(proposals, targets) diff --git a/torchvision/models/detection/ssd.py b/torchvision/models/detection/ssd.py index fe1c732ab3b..7ec8c9cc3b1 100644 --- a/torchvision/models/detection/ssd.py +++ b/torchvision/models/detection/ssd.py @@ -196,7 +196,7 @@ def __init__( else: out_channels = det_utils.retrieve_out_channels(backbone, size) - if not len(out_channels) == len(anchor_generator.aspect_ratios): + if len(out_channels) != len(anchor_generator.aspect_ratios): raise RuntimeError( f"The length of the output channels from the backbone ({len(out_channels)}) do not match the length of the anchor generator aspect ratios ({len(anchor_generator.aspect_ratios)})" ) @@ -325,7 +325,7 @@ def forward( original_image_sizes: List[Tuple[int, int]] = [] for img in images: val = img.shape[-2:] - if not len(val) == 2: + if not len(val) != 2: raise ValueError( f"The last two dimensions of the input tensors should contain H and W, instead got {img.shape[-2:]}" ) @@ -538,7 +538,7 @@ def _vgg_extractor(backbone: vgg.VGG, highres: bool, trainable_layers: int): # find the index of the layer from which we wont freeze if not 0 <= trainable_layers <= num_stages: - raise ValueError(f"trainable_layers should be in the range [0, {num_stages}].") + raise ValueError(f"trainable_layers should be in the range [0, {num_stages}]. Instead got {trainable_layers}") freeze_before = len(backbone) if trainable_layers == 0 else stage_indices[num_stages - trainable_layers] for b in backbone[:freeze_before]: diff --git a/torchvision/models/detection/ssdlite.py b/torchvision/models/detection/ssdlite.py index 4d30fa5ec63..10cd0c1cb8a 100644 --- a/torchvision/models/detection/ssdlite.py +++ b/torchvision/models/detection/ssdlite.py @@ -247,7 +247,7 @@ def ssdlite320_mobilenet_v3_large( anchor_generator = DefaultBoxGenerator([[2, 3] for _ in range(6)], min_ratio=0.2, max_ratio=0.95) out_channels = det_utils.retrieve_out_channels(backbone, size) num_anchors = anchor_generator.num_anchors_per_location() - if not len(out_channels) == len(anchor_generator.aspect_ratios): + if len(out_channels) != len(anchor_generator.aspect_ratios): raise RuntimeError( f"The length of the output channels from the backbone {len(out_channels)} do not match the length of the anchor generator aspect ratios {len(anchor_generator.aspect_ratios)}" ) diff --git a/torchvision/models/detection/transform.py b/torchvision/models/detection/transform.py index f9cd863658c..58b38baee04 100644 --- a/torchvision/models/detection/transform.py +++ b/torchvision/models/detection/transform.py @@ -134,7 +134,7 @@ def forward( images = self.batch_images(images, size_divisible=self.size_divisible) image_sizes_list: List[Tuple[int, int]] = [] for image_size in image_sizes: - if not len(image_size) == 2: + if len(image_size) != 2: raise ValueError( f"Input tensors expected to have in the last two elements H and W, instead got {image_size}" ) diff --git a/torchvision/models/feature_extraction.py b/torchvision/models/feature_extraction.py index 3609b5f7005..6e580813bb4 100644 --- a/torchvision/models/feature_extraction.py +++ b/torchvision/models/feature_extraction.py @@ -291,8 +291,10 @@ def __init__( # Locally defined Tracers are not pickleable. This is needed because torch.package will # serialize a GraphModule without retaining the Graph, and needs to use the correct Tracer # to re-create the Graph during deserialization. - if not self.eval_graph._tracer_cls == self.train_graph._tracer_cls: - raise RuntimeError("Train mode and eval mode should use the same tracer class") + if self.eval_graph._tracer_cls != self.train_graph._tracer_cls: + raise RuntimeError( + f"Train mode and eval mode should use the same tracer class. Instead got {self.eval_graph._tracer_cls} for eval vs {self.train_graph._tracer_cls} for train" + ) self._tracer_cls = None if self.graph._tracer_cls and "" not in self.graph._tracer_cls.__qualname__: self._tracer_cls = self.graph._tracer_cls diff --git a/torchvision/models/googlenet.py b/torchvision/models/googlenet.py index fc94de07540..f3487b44c09 100644 --- a/torchvision/models/googlenet.py +++ b/torchvision/models/googlenet.py @@ -50,7 +50,7 @@ def __init__( FutureWarning, ) init_weights = True - if not len(blocks) == 3: + if len(blocks) != 3: raise ValueError(f"blocks length should be 3 instead of {len(blocks)}") conv_block = blocks[0] inception_block = blocks[1] diff --git a/torchvision/models/inception.py b/torchvision/models/inception.py index c7adb4384d4..0fe6400a681 100644 --- a/torchvision/models/inception.py +++ b/torchvision/models/inception.py @@ -48,7 +48,7 @@ def __init__( FutureWarning, ) init_weights = True - if not len(inception_blocks) == 7: + if len(inception_blocks) != 7: raise ValueError(f"lenght of inception_blocks should be 7 instead of {len(inception_blocks)}") conv_block = inception_blocks[0] inception_a = inception_blocks[1] diff --git a/torchvision/models/mnasnet.py b/torchvision/models/mnasnet.py index 0b58e81f9e5..9608c555a88 100644 --- a/torchvision/models/mnasnet.py +++ b/torchvision/models/mnasnet.py @@ -58,8 +58,8 @@ def _stack( in_ch: int, out_ch: int, kernel_size: int, stride: int, exp_factor: int, repeats: int, bn_momentum: float ) -> nn.Sequential: """Creates a stack of inverted residuals.""" - if not repeats >= 1: - raise ValueError("repeats should be >= 1") + if repeats < 1: + raise ValueError(f"repeats should be >= 1, instead got {repeats}") # First one has no skip, because feature map size changes. first = _InvertedResidual(in_ch, out_ch, kernel_size, stride, exp_factor, bn_momentum=bn_momentum) remaining = [] diff --git a/torchvision/models/optical_flow/raft.py b/torchvision/models/optical_flow/raft.py index 6f8eedf82e6..f0605d8f056 100644 --- a/torchvision/models/optical_flow/raft.py +++ b/torchvision/models/optical_flow/raft.py @@ -121,8 +121,8 @@ class FeatureEncoder(nn.Module): def __init__(self, *, block=ResidualBlock, layers=(64, 64, 96, 128, 256), norm_layer=nn.BatchNorm2d): super().__init__() - if not len(layers) == 5: - raise ValueError("The expected number of layers is 5") + if len(layers) != 5: + raise ValueError(f"The expected number of layers is 5, instead got {len(layers)}") # See note in ResidualBlock for the reason behind bias=True self.convnormrelu = Conv2dNormActivation( @@ -170,10 +170,10 @@ class MotionEncoder(nn.Module): def __init__(self, *, in_channels_corr, corr_layers=(256, 192), flow_layers=(128, 64), out_channels=128): super().__init__() - if not len(flow_layers) == 2: - raise ValueError("The expected number of flow_layers is 2") + if len(flow_layers) != 2: + raise ValueError(f"The expected number of flow_layers is 2, instead got {len(flow_layers)}") if not len(corr_layers) in (1, 2): - raise ValueError("The number of corr_layers should be 1 or 2") + raise ValueError(f"The number of corr_layers should be 1 or 2, instead got {len(corr_layers)}") self.convcorr1 = Conv2dNormActivation(in_channels_corr, corr_layers[0], norm_layer=None, kernel_size=1) if len(corr_layers) == 2: @@ -237,10 +237,10 @@ class RecurrentBlock(nn.Module): def __init__(self, *, input_size, hidden_size, kernel_size=((1, 5), (5, 1)), padding=((0, 2), (2, 0))): super().__init__() - if not len(kernel_size) == len(padding): - raise ValueError("kernel_size should have the same length as padding") - if not len(kernel_size) in (1, 2): - raise ValueError("kernel_size should either 1 or 2") + if len(kernel_size) != len(padding): + raise ValueError(f"kernel_size should have the same length as padding, instead got len(kernel_size) = {len(kernel_size)} and len(padding) = {len(padding)}") + if len(kernel_size) not in (1, 2): + raise ValueError(f"kernel_size should either 1 or 2, instead got {len(kernel_size)}") self.convgru1 = ConvGRU( input_size=input_size, hidden_size=hidden_size, kernel_size=kernel_size[0], padding=padding[0] @@ -356,8 +356,8 @@ def build_pyramid(self, fmap1, fmap2): to build the correlation pyramid. """ - if not fmap1.shape == fmap2.shape: - raise ValueError("Input feature maps should have the same shape") + if fmap1.shape != fmap2.shape: + raise ValueError(f"Input feature maps should have the same shape, instead got {fmap1.shape} (fmap1.shape) != {fmap2.shape} (fmap2.shape)") corr_volume = self._compute_corr_volume(fmap1, fmap2) batch_size, h, w, num_channels, _, _ = corr_volume.shape # _, _ = h, w @@ -390,7 +390,7 @@ def index_pyramid(self, centroids_coords): corr_features = torch.cat(indexed_pyramid, dim=-1).permute(0, 3, 1, 2).contiguous() expected_output_shape = (batch_size, self.out_channels, h, w) - if not corr_features.shape == expected_output_shape: + if corr_features.shape != expected_output_shape: raise ValueError( f"Output shape of index pyramid is incorrect. Should be {expected_output_shape}, got {corr_features.shape}" ) @@ -460,20 +460,20 @@ def __init__(self, *, feature_encoder, context_encoder, corr_block, update_block def forward(self, image1, image2, num_flow_updates: int = 12): batch_size, _, h, w = image1.shape - if not (h, w) == image2.shape[-2:]: - raise ValueError("input images should have the same shape") + if (h, w) != image2.shape[-2:]: + raise ValueError(f"input images should have the same shape, instead got {} != {image2.shape[-2:]}") if not (h % 8 == 0) and (w % 8 == 0): - raise ValueError("input image H and W should be divisible by 8") + raise ValueError(f"input image H and W should be divisible by 8, insted got {h} (h) and {w} (w)") fmaps = self.feature_encoder(torch.cat([image1, image2], dim=0)) fmap1, fmap2 = torch.chunk(fmaps, chunks=2, dim=0) - if not fmap1.shape[-2:] == (h // 8, w // 8): + if fmap1.shape[-2:] != (h // 8, w // 8): raise ValueError("The feature encoder should downsample H and W by 8") self.corr_block.build_pyramid(fmap1, fmap2) context_out = self.context_encoder(image1) - if not context_out.shape[-2:] == (h // 8, w // 8): + if context_out.shape[-2:] != (h // 8, w // 8): raise ValueError("The context encoder should downsample H and W by 8") # As in the original paper, the actual output of the context encoder is split in 2 parts: @@ -481,7 +481,7 @@ def forward(self, image1, image2, num_flow_updates: int = 12): # - the rest is the "actual" context. hidden_state_size = self.update_block.hidden_state_size out_channels_context = context_out.shape[1] - hidden_state_size - if not out_channels_context > 0: + if out_channels_context <= 0: raise ValueError( f"The context encoder outputs {context_out.shape[1]} channels, but it should have at strictly more than hidden_state={hidden_state_size} channels" ) diff --git a/torchvision/models/vision_transformer.py b/torchvision/models/vision_transformer.py index 6528a0d8054..43e4d315cec 100644 --- a/torchvision/models/vision_transformer.py +++ b/torchvision/models/vision_transformer.py @@ -434,8 +434,10 @@ def interpolate_embeddings( # (1, seq_length, hidden_dim) -> (1, hidden_dim, seq_length) pos_embedding_img = pos_embedding_img.permute(0, 2, 1) seq_length_1d = int(math.sqrt(seq_length)) - if not seq_length_1d * seq_length_1d == seq_length: - raise ValueError("seq_length is not a perfect square!") + if seq_length_1d * seq_length_1d != seq_length: + raise ValueError( + f"seq_length is not a perfect square! Instead got seq_length_1d * seq_length_1d = {seq_length_1d * seq_length_1d } and seq_length = {seq_length}" + ) # (1, hidden_dim, seq_length) -> (1, hidden_dim, seq_l_1d, seq_l_1d) pos_embedding_img = pos_embedding_img.reshape(1, hidden_dim, seq_length_1d, seq_length_1d) diff --git a/torchvision/ops/_utils.py b/torchvision/ops/_utils.py index 2cc8af2ea43..6964cfaae78 100644 --- a/torchvision/ops/_utils.py +++ b/torchvision/ops/_utils.py @@ -28,13 +28,15 @@ def convert_boxes_to_roi_format(boxes: List[Tensor]) -> Tensor: def check_roi_boxes_shape(boxes: Union[Tensor, List[Tensor]]): if isinstance(boxes, (list, tuple)): for _tensor in boxes: - if not _tensor.size(1) == 4: - raise ValueError("The shape of the tensor in the boxes list is not correct as List[Tensor[L, 4]]") + if _tensor.size(1) != 4: + raise ValueError( + f"The shape of the tensor in the boxes list is not correct as List[Tensor[L, 4]], instead got {_tensor.size}" + ) elif isinstance(boxes, torch.Tensor): - if not boxes.size(1) == 5: - raise ValueError("The boxes tensor shape is not correct as Tensor[K, 5]") + if boxes.size(1) != 5: + raise ValueError(f"The boxes tensor shape is not correct as Tensor[K, 5], instead got {boxes.size}") else: - raise TypeError("boxes is expected to be a Tensor[L, 5] or a List[Tensor[K, 4]]") + raise TypeError(f"boxes is expected to be a Tensor[L, 5] or a List[Tensor[K, 4]], instead got {type(boxes)}") return diff --git a/torchvision/prototype/models/detection/ssdlite.py b/torchvision/prototype/models/detection/ssdlite.py index db759b3e394..45fe078568b 100644 --- a/torchvision/prototype/models/detection/ssdlite.py +++ b/torchvision/prototype/models/detection/ssdlite.py @@ -98,7 +98,7 @@ def ssdlite320_mobilenet_v3_large( anchor_generator = DefaultBoxGenerator([[2, 3] for _ in range(6)], min_ratio=0.2, max_ratio=0.95) out_channels = det_utils.retrieve_out_channels(backbone, size) num_anchors = anchor_generator.num_anchors_per_location() - if not len(out_channels) == len(anchor_generator.aspect_ratios): + if len(out_channels) != len(anchor_generator.aspect_ratios): raise RuntimeError( f"The length of the output channels from the backbone {len(out_channels)} do not match the length of the anchor generator aspect ratios {len(anchor_generator.aspect_ratios)}" ) diff --git a/torchvision/transforms/_functional_video.py b/torchvision/transforms/_functional_video.py index 479e76e634c..f969a2542d0 100644 --- a/torchvision/transforms/_functional_video.py +++ b/torchvision/transforms/_functional_video.py @@ -24,14 +24,14 @@ def crop(clip, i, j, h, w): Args: clip (torch.tensor): Video clip to be cropped. Size is (C, T, H, W) """ - if not len(clip.size()) == 4: + if len(clip.size()) != 4: raise ValueError("clip should be a 4D tensor") return clip[..., i : i + h, j : j + w] def resize(clip, target_size, interpolation_mode): - if not len(target_size) == 2: - raise ValueError("target size should be tuple (height, width)") + if len(target_size) != 2: + raise ValueError(f"target size should be tuple (height, width), instead got {target_size}") return torch.nn.functional.interpolate(clip, size=target_size, mode=interpolation_mode, align_corners=False) @@ -60,7 +60,7 @@ def center_crop(clip, crop_size): raise ValueError("clip should be a 4D torch.tensor") h, w = clip.size(-2), clip.size(-1) th, tw = crop_size - if not h >= th and w >= tw: + if h < th or w < tw: raise ValueError("height and width must be no smaller than crop_size") i = int(round((h - th) / 2.0)) diff --git a/torchvision/transforms/_transforms_video.py b/torchvision/transforms/_transforms_video.py index f686dbcbcf1..69512af6eb1 100644 --- a/torchvision/transforms/_transforms_video.py +++ b/torchvision/transforms/_transforms_video.py @@ -59,8 +59,8 @@ def __init__( interpolation_mode="bilinear", ): if isinstance(size, tuple): - if not len(size) == 2: - raise ValueError("size should be tuple (height, width)") + if len(size) != 2: + raise ValueError(f"size should be tuple (height, width), instead got {size}") self.size = size else: self.size = (size, size) From 5b30ce3e284352f008d3baea58f1ad9eea03a280 Mon Sep 17 00:00:00 2001 From: Joao Gomes Date: Mon, 14 Mar 2022 13:37:09 +0000 Subject: [PATCH 26/49] fix bug --- torchvision/models/optical_flow/raft.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/torchvision/models/optical_flow/raft.py b/torchvision/models/optical_flow/raft.py index f0605d8f056..b1d38052f96 100644 --- a/torchvision/models/optical_flow/raft.py +++ b/torchvision/models/optical_flow/raft.py @@ -461,7 +461,7 @@ def forward(self, image1, image2, num_flow_updates: int = 12): batch_size, _, h, w = image1.shape if (h, w) != image2.shape[-2:]: - raise ValueError(f"input images should have the same shape, instead got {} != {image2.shape[-2:]}") + raise ValueError(f"input images should have the same shape, instead got ({h}, {w}) != {image2.shape[-2:]}") if not (h % 8 == 0) and (w % 8 == 0): raise ValueError(f"input image H and W should be divisible by 8, insted got {h} (h) and {w} (w)") From ade33648ba55da8d40ffa9584add500a6a7472af Mon Sep 17 00:00:00 2001 From: Joao Gomes Date: Mon, 14 Mar 2022 13:44:54 +0000 Subject: [PATCH 27/49] appy ufmt --- torchvision/models/optical_flow/raft.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/torchvision/models/optical_flow/raft.py b/torchvision/models/optical_flow/raft.py index b1d38052f96..5a7e1e1a39b 100644 --- a/torchvision/models/optical_flow/raft.py +++ b/torchvision/models/optical_flow/raft.py @@ -238,7 +238,9 @@ def __init__(self, *, input_size, hidden_size, kernel_size=((1, 5), (5, 1)), pad super().__init__() if len(kernel_size) != len(padding): - raise ValueError(f"kernel_size should have the same length as padding, instead got len(kernel_size) = {len(kernel_size)} and len(padding) = {len(padding)}") + raise ValueError( + f"kernel_size should have the same length as padding, instead got len(kernel_size) = {len(kernel_size)} and len(padding) = {len(padding)}" + ) if len(kernel_size) not in (1, 2): raise ValueError(f"kernel_size should either 1 or 2, instead got {len(kernel_size)}") @@ -357,7 +359,9 @@ def build_pyramid(self, fmap1, fmap2): """ if fmap1.shape != fmap2.shape: - raise ValueError(f"Input feature maps should have the same shape, instead got {fmap1.shape} (fmap1.shape) != {fmap2.shape} (fmap2.shape)") + raise ValueError( + f"Input feature maps should have the same shape, instead got {fmap1.shape} (fmap1.shape) != {fmap2.shape} (fmap2.shape)" + ) corr_volume = self._compute_corr_volume(fmap1, fmap2) batch_size, h, w, num_channels, _, _ = corr_volume.shape # _, _ = h, w From 2f4ecc14319267033f0b94ff942bea63ab215742 Mon Sep 17 00:00:00 2001 From: Joao Gomes Date: Mon, 14 Mar 2022 13:48:08 +0000 Subject: [PATCH 28/49] fix tracing issues --- torchvision/ops/_utils.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/torchvision/ops/_utils.py b/torchvision/ops/_utils.py index 6964cfaae78..b38d61860b8 100644 --- a/torchvision/ops/_utils.py +++ b/torchvision/ops/_utils.py @@ -30,11 +30,11 @@ def check_roi_boxes_shape(boxes: Union[Tensor, List[Tensor]]): for _tensor in boxes: if _tensor.size(1) != 4: raise ValueError( - f"The shape of the tensor in the boxes list is not correct as List[Tensor[L, 4]], instead got {_tensor.size}" + f"The shape of the tensor in the boxes list is not correct as List[Tensor[L, 4]]." ) elif isinstance(boxes, torch.Tensor): if boxes.size(1) != 5: - raise ValueError(f"The boxes tensor shape is not correct as Tensor[K, 5], instead got {boxes.size}") + raise ValueError(f"The boxes tensor shape is not correct as Tensor[K, 5]/") else: raise TypeError(f"boxes is expected to be a Tensor[L, 5] or a List[Tensor[K, 4]], instead got {type(boxes)}") return From 981617bc9eea99b8206b883ea2920dbcdda20b53 Mon Sep 17 00:00:00 2001 From: Joao Gomes Date: Mon, 14 Mar 2022 14:59:01 +0000 Subject: [PATCH 29/49] fib typos --- torchvision/models/detection/generalized_rcnn.py | 2 +- torchvision/models/detection/retinanet.py | 2 +- torchvision/models/detection/ssd.py | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/torchvision/models/detection/generalized_rcnn.py b/torchvision/models/detection/generalized_rcnn.py index 09b33fe6973..bc53d35109c 100644 --- a/torchvision/models/detection/generalized_rcnn.py +++ b/torchvision/models/detection/generalized_rcnn.py @@ -74,7 +74,7 @@ def forward(self, images, targets=None): original_image_sizes: List[Tuple[int, int]] = [] for img in images: val = img.shape[-2:] - if not len(val) != 2: + if len(val) != 2: raise ValueError( f"Expecting the last two dimensions of the input tensor to be H and W, instead got {img.shape[-2:]}" ) diff --git a/torchvision/models/detection/retinanet.py b/torchvision/models/detection/retinanet.py index bb295169a12..764e2566a6c 100644 --- a/torchvision/models/detection/retinanet.py +++ b/torchvision/models/detection/retinanet.py @@ -505,7 +505,7 @@ def forward(self, images, targets=None): original_image_sizes: List[Tuple[int, int]] = [] for img in images: val = img.shape[-2:] - if not len(val) != 2: + if len(val) != 2: raise ValueError( f"Expecting the two last elements of the input tensors to be H and W instead got {img.shape[-2:]}" ) diff --git a/torchvision/models/detection/ssd.py b/torchvision/models/detection/ssd.py index 7ec8c9cc3b1..eb9fc6f1fb8 100644 --- a/torchvision/models/detection/ssd.py +++ b/torchvision/models/detection/ssd.py @@ -325,7 +325,7 @@ def forward( original_image_sizes: List[Tuple[int, int]] = [] for img in images: val = img.shape[-2:] - if not len(val) != 2: + if len(val) != 2: raise ValueError( f"The last two dimensions of the input tensors should contain H and W, instead got {img.shape[-2:]}" ) From fec7d4bd8aabe815aa9cb5195394b4af56099b64 Mon Sep 17 00:00:00 2001 From: Joao Gomes Date: Mon, 14 Mar 2022 15:03:09 +0000 Subject: [PATCH 30/49] fix lint --- torchvision/ops/_utils.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/torchvision/ops/_utils.py b/torchvision/ops/_utils.py index b38d61860b8..123d0b256c9 100644 --- a/torchvision/ops/_utils.py +++ b/torchvision/ops/_utils.py @@ -29,9 +29,7 @@ def check_roi_boxes_shape(boxes: Union[Tensor, List[Tensor]]): if isinstance(boxes, (list, tuple)): for _tensor in boxes: if _tensor.size(1) != 4: - raise ValueError( - f"The shape of the tensor in the boxes list is not correct as List[Tensor[L, 4]]." - ) + raise ValueError(f"The shape of the tensor in the boxes list is not correct as List[Tensor[L, 4]].") elif isinstance(boxes, torch.Tensor): if boxes.size(1) != 5: raise ValueError(f"The boxes tensor shape is not correct as Tensor[K, 5]/") From ca59cd77a3a7d275910ccf8ac10dc5ac12627647 Mon Sep 17 00:00:00 2001 From: Joao Gomes Date: Mon, 14 Mar 2022 15:08:42 +0000 Subject: [PATCH 31/49] remove unecessary f-strings --- torchvision/ops/_utils.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/torchvision/ops/_utils.py b/torchvision/ops/_utils.py index 123d0b256c9..30f28e51c4c 100644 --- a/torchvision/ops/_utils.py +++ b/torchvision/ops/_utils.py @@ -29,10 +29,10 @@ def check_roi_boxes_shape(boxes: Union[Tensor, List[Tensor]]): if isinstance(boxes, (list, tuple)): for _tensor in boxes: if _tensor.size(1) != 4: - raise ValueError(f"The shape of the tensor in the boxes list is not correct as List[Tensor[L, 4]].") + raise ValueError("The shape of the tensor in the boxes list is not correct as List[Tensor[L, 4]].") elif isinstance(boxes, torch.Tensor): if boxes.size(1) != 5: - raise ValueError(f"The boxes tensor shape is not correct as Tensor[K, 5]/") + raise ValueError("The boxes tensor shape is not correct as Tensor[K, 5]/") else: raise TypeError(f"boxes is expected to be a Tensor[L, 5] or a List[Tensor[K, 4]], instead got {type(boxes)}") return From 81ac57ccb9e22b7b8f8cc35e50e7e02b497db4a7 Mon Sep 17 00:00:00 2001 From: Joao Gomes Date: Mon, 14 Mar 2022 15:51:04 +0000 Subject: [PATCH 32/49] fix bug --- torchvision/models/detection/fcos.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/torchvision/models/detection/fcos.py b/torchvision/models/detection/fcos.py index 24db93ffc51..b99f7f8a545 100644 --- a/torchvision/models/detection/fcos.py +++ b/torchvision/models/detection/fcos.py @@ -571,7 +571,7 @@ def forward( original_image_sizes: List[Tuple[int, int]] = [] for img in images: val = img.shape[-2:] - if not len(val) != 2: + if len(val) != 2: raise ValueError( f"expecting the last two dimensions of the Tensor to be H and W instead got {img.shape[-2:]}" ) From e68c1be9c1d752359a57a96bc686ecdf0d0295c6 Mon Sep 17 00:00:00 2001 From: Joao Gomes Date: Tue, 15 Mar 2022 10:47:18 +0000 Subject: [PATCH 33/49] Update torchvision/datasets/mnist.py Co-authored-by: Nicolas Hug --- torchvision/datasets/mnist.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/torchvision/datasets/mnist.py b/torchvision/datasets/mnist.py index 98fa86b8dd2..4a812027a12 100644 --- a/torchvision/datasets/mnist.py +++ b/torchvision/datasets/mnist.py @@ -535,7 +535,7 @@ def read_label_file(path: str) -> torch.Tensor: x = read_sn3_pascalvincent_tensor(path, strict=False) if x.dtype != torch.uint8: raise TypeError(f"x should be of dtype torch.uint8 instead of {x.dtype}") - if not x.ndimension() == 1: + if x.ndimension() != 1: raise ValueError(f"x should have 1 dimension instead of {x.ndimension()}") return x.long() From d92a0f91deec5ebc31bb4d2898aa1c582514b577 Mon Sep 17 00:00:00 2001 From: Joao Gomes Date: Tue, 15 Mar 2022 10:47:26 +0000 Subject: [PATCH 34/49] Update torchvision/datasets/mnist.py Co-authored-by: Nicolas Hug --- torchvision/datasets/mnist.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/torchvision/datasets/mnist.py b/torchvision/datasets/mnist.py index 4a812027a12..9f9ec457499 100644 --- a/torchvision/datasets/mnist.py +++ b/torchvision/datasets/mnist.py @@ -544,6 +544,6 @@ def read_image_file(path: str) -> torch.Tensor: x = read_sn3_pascalvincent_tensor(path, strict=False) if x.dtype != torch.uint8: raise TypeError(f"x should be of dtype torch.uint8 instead of {x.dtype}") - if not x.ndimension() == 3: + if x.ndimension() != 3: raise ValueError(f"x should have 3 dimension instead of {x.ndimension()}") return x From 4a30fc977b0dfd8998d5c9d59e1036032ac36c74 Mon Sep 17 00:00:00 2001 From: Joao Gomes Date: Tue, 15 Mar 2022 11:45:13 +0000 Subject: [PATCH 35/49] Update torchvision/ops/boxes.py Co-authored-by: Nicolas Hug --- torchvision/ops/boxes.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/torchvision/ops/boxes.py b/torchvision/ops/boxes.py index 56c56e88d30..2f1f984ca25 100644 --- a/torchvision/ops/boxes.py +++ b/torchvision/ops/boxes.py @@ -300,7 +300,7 @@ def generalized_box_iou(boxes1: Tensor, boxes2: Tensor) -> Tensor: _log_api_usage_once(generalized_box_iou) # degenerate boxes gives inf / nan results # so do an early check - if not (boxes1[:, 2:] >= boxes1[:, :2]).all(): + if (boxes1[:, 2:] < boxes1[:, :2]).any(): raise ValueError("Some of the input boxes1 are invalid.") if not (boxes2[:, 2:] >= boxes2[:, :2]).all(): raise ValueError("Some of the input boxes2 are invalid.") From e4f214de9ff130b63311178604fb571ff6164588 Mon Sep 17 00:00:00 2001 From: Joao Gomes Date: Tue, 15 Mar 2022 11:45:42 +0000 Subject: [PATCH 36/49] Update torchvision/ops/poolers.py Co-authored-by: Nicolas Hug --- torchvision/ops/poolers.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/torchvision/ops/poolers.py b/torchvision/ops/poolers.py index c1b72bc5a7e..332da0023d2 100644 --- a/torchvision/ops/poolers.py +++ b/torchvision/ops/poolers.py @@ -111,7 +111,7 @@ def _infer_scale(feature: Tensor, original_size: List[int]) -> float: def _setup_scales( features: List[Tensor], image_shapes: List[Tuple[int, int]], canonical_scale: int, canonical_level: int ) -> Tuple[List[float], LevelMapper]: - if len(image_shapes) == 0: + if not image_shapes: raise ValueError("images list should not be empty") max_x = 0 max_y = 0 From 9e9ca6d429961b3a18ffcc7e35007c4756112eee Mon Sep 17 00:00:00 2001 From: Joao Gomes Date: Tue, 15 Mar 2022 11:45:59 +0000 Subject: [PATCH 37/49] Update torchvision/utils.py Co-authored-by: Nicolas Hug --- torchvision/utils.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/torchvision/utils.py b/torchvision/utils.py index 73ca8c5ee71..4737a047327 100644 --- a/torchvision/utils.py +++ b/torchvision/utils.py @@ -102,7 +102,7 @@ def norm_range(t, value_range): norm_range(tensor, value_range) if not isinstance(tensor, torch.Tensor): - raise ValueError("tensor should be of type torch.Tensor") + raise TypeError("tensor should be of type torch.Tensor") if tensor.size(0) == 1: return tensor.squeeze(0) From b234e0804e8befcd9fbc46feecd5f22fa2a070f3 Mon Sep 17 00:00:00 2001 From: Joao Gomes Date: Tue, 15 Mar 2022 11:56:53 +0000 Subject: [PATCH 38/49] address PR comments --- references/classification/transforms.py | 2 +- test/test_backbone_utils.py | 6 +++--- torchvision/datasets/kinetics.py | 2 +- torchvision/models/feature_extraction.py | 8 +++----- torchvision/models/shufflenetv2.py | 4 ++++ 5 files changed, 12 insertions(+), 10 deletions(-) diff --git a/references/classification/transforms.py b/references/classification/transforms.py index 78c286579f9..ba3e35d87ac 100644 --- a/references/classification/transforms.py +++ b/references/classification/transforms.py @@ -105,7 +105,7 @@ class RandomCutmix(torch.nn.Module): def __init__(self, num_classes: int, p: float = 0.5, alpha: float = 1.0, inplace: bool = False) -> None: super().__init__() - if num_classes <= 1: + if num_classes < 1: raise ValueError("Please provide a valid positive value for the num_classes.") if alpha <= 0: raise ValueError("Alpha param can't be zero.") diff --git a/test/test_backbone_utils.py b/test/test_backbone_utils.py index 45183cda089..a3ba427f1de 100644 --- a/test/test_backbone_utils.py +++ b/test/test_backbone_utils.py @@ -144,16 +144,16 @@ def test_build_fx_feature_extractor(self, model_name): model, train_return_nodes=train_return_nodes, eval_return_nodes=eval_return_nodes ) # Check must specify return nodes - with pytest.raises(RuntimeError): + with pytest.raises(ValueError): self._create_feature_extractor(model) # Check return_nodes and train_return_nodes / eval_return nodes # mutual exclusivity - with pytest.raises(RuntimeError): + with pytest.raises(ValueError): self._create_feature_extractor( model, return_nodes=train_return_nodes, train_return_nodes=train_return_nodes ) # Check train_return_nodes / eval_return nodes must both be specified - with pytest.raises(RuntimeError): + with pytest.raises(ValueError): self._create_feature_extractor(model, train_return_nodes=train_return_nodes) # Check invalid node name raises ValueError with pytest.raises(ValueError): diff --git a/torchvision/datasets/kinetics.py b/torchvision/datasets/kinetics.py index 6581f80bec5..e1ac4ac500c 100644 --- a/torchvision/datasets/kinetics.py +++ b/torchvision/datasets/kinetics.py @@ -119,7 +119,7 @@ def __init__( self.split_folder = root self.split = "unknown" if download: - raise RuntimeError("Cannot download the videos using legacy_structure.") + raise ValueError("Cannot download the videos using legacy_structure.") else: self.split_folder = path.join(root, split) self.split = verify_str_arg(split, arg="split", valid_values=["train", "val"]) diff --git a/torchvision/models/feature_extraction.py b/torchvision/models/feature_extraction.py index 6e580813bb4..f75ac356ddd 100644 --- a/torchvision/models/feature_extraction.py +++ b/torchvision/models/feature_extraction.py @@ -435,19 +435,17 @@ def create_feature_extractor( if not any(arg is not None for arg in [return_nodes, train_return_nodes, eval_return_nodes]): - raise RuntimeError( + raise ValueError( "Either `return_nodes` or `train_return_nodes` and `eval_return_nodes` together, should be specified" ) if (train_return_nodes is None) ^ (eval_return_nodes is None): - raise RuntimeError( + raise ValueError( "If any of `train_return_nodes` and `eval_return_nodes` are specified, then both should be specified" ) if not ((return_nodes is None) ^ (train_return_nodes is None)): - raise RuntimeError( - "If `train_return_nodes` and `eval_return_nodes` are specified, then both should be specified" - ) + raise ValueError("If `train_return_nodes` and `eval_return_nodes` are specified, then both should be specified") # Put *_return_nodes into Dict[str, str] format def to_strdict(n) -> Dict[str, str]: diff --git a/torchvision/models/shufflenetv2.py b/torchvision/models/shufflenetv2.py index 5d195286b08..9a893ba1510 100644 --- a/torchvision/models/shufflenetv2.py +++ b/torchvision/models/shufflenetv2.py @@ -42,6 +42,10 @@ def __init__(self, inp: int, oup: int, stride: int) -> None: self.stride = stride branch_features = oup // 2 + if (self.stride == 1) and (inp != branch_features << 1): + raise ValueError( + f"Invalid combination of stride {stride}, inp {inp} and oup {oup} values. If stride == 1 then inp should be equal to oup // 2 << 1." + ) if self.stride > 1: self.branch1 = nn.Sequential( From 1a45e1e99f5331cf505ebc4d611a5e62245557db Mon Sep 17 00:00:00 2001 From: Joao Gomes Date: Tue, 15 Mar 2022 12:06:50 +0000 Subject: [PATCH 39/49] Update torchvision/io/_video_opt.py Co-authored-by: Nicolas Hug --- torchvision/io/_video_opt.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/torchvision/io/_video_opt.py b/torchvision/io/_video_opt.py index 48b9a2fb34a..5357d25ea62 100644 --- a/torchvision/io/_video_opt.py +++ b/torchvision/io/_video_opt.py @@ -67,7 +67,7 @@ def __init__(self) -> None: def _validate_pts(pts_range: Tuple[int, int]) -> None: - if pts_range[1] > 0 and pts_range[0] > pts_range[1]: + if pts_range[0] > pts_range[1] > 0: raise ValueError( f"Start pts should not be smaller than end pts, got start pts: {pts_range[0]} and end pts: {pts_range[1]}" ) From 8437088eb91fe870d9de7d7c0e1da96e47d56a7c Mon Sep 17 00:00:00 2001 From: Joao Gomes Date: Tue, 15 Mar 2022 12:07:55 +0000 Subject: [PATCH 40/49] Update torchvision/models/detection/generalized_rcnn.py Co-authored-by: Nicolas Hug --- torchvision/models/detection/generalized_rcnn.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/torchvision/models/detection/generalized_rcnn.py b/torchvision/models/detection/generalized_rcnn.py index bc53d35109c..8ff31823f30 100644 --- a/torchvision/models/detection/generalized_rcnn.py +++ b/torchvision/models/detection/generalized_rcnn.py @@ -69,7 +69,7 @@ def forward(self, images, targets=None): f"Expected target boxes to be a tensor of shape [N, 4], got {boxes.shape}." ) else: - raise ValueError(f"Expected target boxes to be of type Tensor, got {type(boxes)}.") + raise TypeError(f"Expected target boxes to be of type Tensor, got {type(boxes)}.") original_image_sizes: List[Tuple[int, int]] = [] for img in images: From cff417aca7a660967f645735b66c67710c3dd1d6 Mon Sep 17 00:00:00 2001 From: Joao Gomes Date: Tue, 15 Mar 2022 12:10:36 +0000 Subject: [PATCH 41/49] Update torchvision/models/feature_extraction.py Co-authored-by: Nicolas Hug --- torchvision/models/feature_extraction.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/torchvision/models/feature_extraction.py b/torchvision/models/feature_extraction.py index f75ac356ddd..5fb3318bf20 100644 --- a/torchvision/models/feature_extraction.py +++ b/torchvision/models/feature_extraction.py @@ -433,7 +433,7 @@ def create_feature_extractor( } is_training = model.training - if not any(arg is not None for arg in [return_nodes, train_return_nodes, eval_return_nodes]): + if all(arg is None for arg in [return_nodes, train_return_nodes, eval_return_nodes]): raise ValueError( "Either `return_nodes` or `train_return_nodes` and `eval_return_nodes` together, should be specified" From 1d9e3d38bb9b73199aa23b4a6851580b37825f87 Mon Sep 17 00:00:00 2001 From: Joao Gomes Date: Tue, 15 Mar 2022 12:21:38 +0000 Subject: [PATCH 42/49] Update torchvision/models/optical_flow/raft.py Co-authored-by: Nicolas Hug --- torchvision/models/optical_flow/raft.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/torchvision/models/optical_flow/raft.py b/torchvision/models/optical_flow/raft.py index 5a7e1e1a39b..00200529f66 100644 --- a/torchvision/models/optical_flow/raft.py +++ b/torchvision/models/optical_flow/raft.py @@ -172,7 +172,7 @@ def __init__(self, *, in_channels_corr, corr_layers=(256, 192), flow_layers=(128 if len(flow_layers) != 2: raise ValueError(f"The expected number of flow_layers is 2, instead got {len(flow_layers)}") - if not len(corr_layers) in (1, 2): + if len(corr_layers) not in (1, 2): raise ValueError(f"The number of corr_layers should be 1 or 2, instead got {len(corr_layers)}") self.convcorr1 = Conv2dNormActivation(in_channels_corr, corr_layers[0], norm_layer=None, kernel_size=1) From ce06c29190a9e11e04fa91c3a6a004c44c525215 Mon Sep 17 00:00:00 2001 From: Joao Gomes Date: Tue, 15 Mar 2022 12:23:29 +0000 Subject: [PATCH 43/49] address PR comments --- torchvision/ops/poolers.py | 102 ++++++++++++++++++------------------- 1 file changed, 51 insertions(+), 51 deletions(-) diff --git a/torchvision/ops/poolers.py b/torchvision/ops/poolers.py index 332da0023d2..f881201a2d2 100644 --- a/torchvision/ops/poolers.py +++ b/torchvision/ops/poolers.py @@ -168,64 +168,64 @@ def _multiscale_roi_align( """ if scales is None or mapper is None: raise ValueError("scales and mapper should not be None") - else: - num_levels = len(x_filtered) - rois = _convert_to_roi_format(boxes) - - if num_levels == 1: - return roi_align( - x_filtered[0], - rois, - output_size=output_size, - spatial_scale=scales[0], - sampling_ratio=sampling_ratio, - ) - - levels = mapper(boxes) - num_rois = len(rois) - num_channels = x_filtered[0].shape[1] + num_levels = len(x_filtered) + rois = _convert_to_roi_format(boxes) - dtype, device = x_filtered[0].dtype, x_filtered[0].device - result = torch.zeros( - ( - num_rois, - num_channels, - ) - + output_size, - dtype=dtype, - device=device, + if num_levels == 1: + return roi_align( + x_filtered[0], + rois, + output_size=output_size, + spatial_scale=scales[0], + sampling_ratio=sampling_ratio, ) - tracing_results = [] - for level, (per_level_feature, scale) in enumerate(zip(x_filtered, scales)): - idx_in_level = torch.where(levels == level)[0] - rois_per_level = rois[idx_in_level] - - result_idx_in_level = roi_align( - per_level_feature, - rois_per_level, - output_size=output_size, - spatial_scale=scale, - sampling_ratio=sampling_ratio, - ) + levels = mapper(boxes) - if torchvision._is_tracing(): - tracing_results.append(result_idx_in_level.to(dtype)) - else: - # result and result_idx_in_level's dtypes are based on dtypes of different - # elements in x_filtered. x_filtered contains tensors output by different - # layers. When autocast is active, it may choose different dtypes for - # different layers' outputs. Therefore, we defensively match result's dtype - # before copying elements from result_idx_in_level in the following op. - # We need to cast manually (can't rely on autocast to cast for us) because - # the op acts on result in-place, and autocast only affects out-of-place ops. - result[idx_in_level] = result_idx_in_level.to(result.dtype) + num_rois = len(rois) + num_channels = x_filtered[0].shape[1] - if torchvision._is_tracing(): - result = _onnx_merge_levels(levels, tracing_results) + dtype, device = x_filtered[0].dtype, x_filtered[0].device + result = torch.zeros( + ( + num_rois, + num_channels, + ) + + output_size, + dtype=dtype, + device=device, + ) - return result + tracing_results = [] + for level, (per_level_feature, scale) in enumerate(zip(x_filtered, scales)): + idx_in_level = torch.where(levels == level)[0] + rois_per_level = rois[idx_in_level] + + result_idx_in_level = roi_align( + per_level_feature, + rois_per_level, + output_size=output_size, + spatial_scale=scale, + sampling_ratio=sampling_ratio, + ) + + if torchvision._is_tracing(): + tracing_results.append(result_idx_in_level.to(dtype)) + else: + # result and result_idx_in_level's dtypes are based on dtypes of different + # elements in x_filtered. x_filtered contains tensors output by different + # layers. When autocast is active, it may choose different dtypes for + # different layers' outputs. Therefore, we defensively match result's dtype + # before copying elements from result_idx_in_level in the following op. + # We need to cast manually (can't rely on autocast to cast for us) because + # the op acts on result in-place, and autocast only affects out-of-place ops. + result[idx_in_level] = result_idx_in_level.to(result.dtype) + + if torchvision._is_tracing(): + result = _onnx_merge_levels(levels, tracing_results) + + return result class MultiScaleRoIAlign(nn.Module): From 2b1870f1c36e3ec4418df027fb21e5401a75983a Mon Sep 17 00:00:00 2001 From: Joao Gomes Date: Tue, 15 Mar 2022 13:27:50 +0000 Subject: [PATCH 44/49] addressing further pr comments --- test/test_models.py | 2 +- torchvision/models/detection/fcos.py | 2 +- torchvision/models/detection/retinanet.py | 2 +- torchvision/models/detection/ssd.py | 2 +- torchvision/models/quantization/inception.py | 3 +-- torchvision/models/quantization/mobilenetv2.py | 3 +-- torchvision/models/quantization/resnet.py | 3 +-- torchvision/models/quantization/shufflenetv2.py | 3 +-- 8 files changed, 8 insertions(+), 12 deletions(-) diff --git a/test/test_models.py b/test/test_models.py index af433049a94..fb024c8da3f 100644 --- a/test/test_models.py +++ b/test/test_models.py @@ -767,7 +767,7 @@ def test_detection_model_validation(model_fn): # validate type targets = [{"boxes": 0.0}] - with pytest.raises(ValueError): + with pytest.raises(TypeError): model(x, targets=targets) # validate boxes shape diff --git a/torchvision/models/detection/fcos.py b/torchvision/models/detection/fcos.py index b99f7f8a545..ba51e819f0a 100644 --- a/torchvision/models/detection/fcos.py +++ b/torchvision/models/detection/fcos.py @@ -566,7 +566,7 @@ def forward( if len(boxes.shape) != 2 or boxes.shape[-1] != 4: raise ValueError(f"Expected target boxes to be a tensor of shape [N, 4], got {boxes.shape}.") else: - raise ValueError(f"Expected target boxes to be of type Tensor, got {type(boxes)}.") + raise TypeError(f"Expected target boxes to be of type Tensor, got {type(boxes)}.") original_image_sizes: List[Tuple[int, int]] = [] for img in images: diff --git a/torchvision/models/detection/retinanet.py b/torchvision/models/detection/retinanet.py index 764e2566a6c..6d6463d6894 100644 --- a/torchvision/models/detection/retinanet.py +++ b/torchvision/models/detection/retinanet.py @@ -499,7 +499,7 @@ def forward(self, images, targets=None): if len(boxes.shape) != 2 or boxes.shape[-1] != 4: raise ValueError(f"Expected target boxes to be a tensor of shape [N, 4], got {boxes.shape}.") else: - raise ValueError(f"Expected target boxes to be of type Tensor, got {type(boxes)}.") + raise TypeError(f"Expected target boxes to be of type Tensor, got {type(boxes)}.") # get the original image sizes original_image_sizes: List[Tuple[int, int]] = [] diff --git a/torchvision/models/detection/ssd.py b/torchvision/models/detection/ssd.py index eb9fc6f1fb8..2e51fcfb547 100644 --- a/torchvision/models/detection/ssd.py +++ b/torchvision/models/detection/ssd.py @@ -319,7 +319,7 @@ def forward( if len(boxes.shape) != 2 or boxes.shape[-1] != 4: raise ValueError(f"Expected target boxes to be a tensor of shape [N, 4], got {boxes.shape}.") else: - raise ValueError(f"Expected target boxes to be of type Tensor, got {type(boxes)}.") + raise TypeError(f"Expected target boxes to be of type Tensor, got {type(boxes)}.") # get the original image sizes original_image_sizes: List[Tuple[int, int]] = [] diff --git a/torchvision/models/quantization/inception.py b/torchvision/models/quantization/inception.py index 6a9c56b3b6c..27d021428b9 100644 --- a/torchvision/models/quantization/inception.py +++ b/torchvision/models/quantization/inception.py @@ -216,8 +216,7 @@ def inception_v3( backend = "fbgemm" quantize_model(model, backend) else: - if pretrained not in [True, False]: - raise ValueError(f"For non quantized models, pretrained should be a bollean value instead of {pretrained}") + assert pretrained in [True, False] if pretrained: if quantize: diff --git a/torchvision/models/quantization/mobilenetv2.py b/torchvision/models/quantization/mobilenetv2.py index 14b97c5ea98..8cd9f16d13e 100644 --- a/torchvision/models/quantization/mobilenetv2.py +++ b/torchvision/models/quantization/mobilenetv2.py @@ -88,8 +88,7 @@ def mobilenet_v2( backend = "qnnpack" quantize_model(model, backend) else: - if pretrained not in [True, False]: - raise ValueError(f"For non quantized models, pretrained should be a bollean value instead of {pretrained}") + assert pretrained in [True, False] if pretrained: if quantize: diff --git a/torchvision/models/quantization/resnet.py b/torchvision/models/quantization/resnet.py index 7102906aed6..f55aa0e103c 100644 --- a/torchvision/models/quantization/resnet.py +++ b/torchvision/models/quantization/resnet.py @@ -125,8 +125,7 @@ def _resnet( backend = "fbgemm" quantize_model(model, backend) else: - if pretrained not in [True, False]: - raise ValueError(f"For non quantized models, pretrained should be a bollean value instead of {pretrained}") + assert pretrained in [True, False] if pretrained: if quantize: diff --git a/torchvision/models/quantization/shufflenetv2.py b/torchvision/models/quantization/shufflenetv2.py index deb7cb1c41e..9d25315ffa0 100644 --- a/torchvision/models/quantization/shufflenetv2.py +++ b/torchvision/models/quantization/shufflenetv2.py @@ -89,8 +89,7 @@ def _shufflenetv2( backend = "fbgemm" quantize_model(model, backend) else: - if pretrained not in [True, False]: - raise ValueError(f"For non quantized models, pretrained should be a bollean value instead of {pretrained}") + assert pretrained in [True, False] if pretrained: model_url: Optional[str] = None From 851adb266b463c90cb19d84e37efb62aaed6289c Mon Sep 17 00:00:00 2001 From: Joao Gomes Date: Tue, 15 Mar 2022 13:38:48 +0000 Subject: [PATCH 45/49] fix bug --- references/classification/transforms.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/references/classification/transforms.py b/references/classification/transforms.py index ba3e35d87ac..9a8ef7877d6 100644 --- a/references/classification/transforms.py +++ b/references/classification/transforms.py @@ -22,7 +22,7 @@ class RandomMixup(torch.nn.Module): def __init__(self, num_classes: int, p: float = 0.5, alpha: float = 1.0, inplace: bool = False) -> None: super().__init__() - if num_classes <= 1: + if num_classes < 1: raise ValueError( f"Please provide a valid positive value for the num_classes. Got num_classes={num_classes}" ) From a915f1f4d0daf09afca508a563eefc488f627993 Mon Sep 17 00:00:00 2001 From: Joao Gomes Date: Tue, 15 Mar 2022 13:48:48 +0000 Subject: [PATCH 46/49] remove unecessary else --- torchvision/models/detection/anchor_utils.py | 50 +++++++++---------- torchvision/models/detection/fcos.py | 4 +- .../models/detection/generalized_rcnn.py | 20 ++++---- torchvision/models/detection/roi_heads.py | 50 +++++++++---------- torchvision/models/detection/ssd.py | 24 ++++----- 5 files changed, 74 insertions(+), 74 deletions(-) diff --git a/torchvision/models/detection/anchor_utils.py b/torchvision/models/detection/anchor_utils.py index 9ef7c80bbb0..9b956ca7d76 100644 --- a/torchvision/models/detection/anchor_utils.py +++ b/torchvision/models/detection/anchor_utils.py @@ -87,31 +87,31 @@ def grid_anchors(self, grid_sizes: List[List[int]], strides: List[List[Tensor]]) if cell_anchors is None: raise RuntimeError("cell_anchors should not be None") - else: - if not (len(grid_sizes) == len(strides) == len(cell_anchors)): - raise ValueError( - "Anchors should be Tuple[Tuple[int]] because each feature " - "map could potentially have different sizes and aspect ratios. " - "There needs to be a match between the number of " - "feature maps passed and the number of sizes / aspect ratios specified." - ) - - for size, stride, base_anchors in zip(grid_sizes, strides, cell_anchors): - grid_height, grid_width = size - stride_height, stride_width = stride - device = base_anchors.device - - # For output anchor, compute [x_center, y_center, x_center, y_center] - shifts_x = torch.arange(0, grid_width, dtype=torch.int32, device=device) * stride_width - shifts_y = torch.arange(0, grid_height, dtype=torch.int32, device=device) * stride_height - shift_y, shift_x = torch.meshgrid(shifts_y, shifts_x, indexing="ij") - shift_x = shift_x.reshape(-1) - shift_y = shift_y.reshape(-1) - shifts = torch.stack((shift_x, shift_y, shift_x, shift_y), dim=1) - - # For every (base anchor, output anchor) pair, - # offset each zero-centered base anchor by the center of the output anchor. - anchors.append((shifts.view(-1, 1, 4) + base_anchors.view(1, -1, 4)).reshape(-1, 4)) + + if not (len(grid_sizes) == len(strides) == len(cell_anchors)): + raise ValueError( + "Anchors should be Tuple[Tuple[int]] because each feature " + "map could potentially have different sizes and aspect ratios. " + "There needs to be a match between the number of " + "feature maps passed and the number of sizes / aspect ratios specified." + ) + + for size, stride, base_anchors in zip(grid_sizes, strides, cell_anchors): + grid_height, grid_width = size + stride_height, stride_width = stride + device = base_anchors.device + + # For output anchor, compute [x_center, y_center, x_center, y_center] + shifts_x = torch.arange(0, grid_width, dtype=torch.int32, device=device) * stride_width + shifts_y = torch.arange(0, grid_height, dtype=torch.int32, device=device) * stride_height + shift_y, shift_x = torch.meshgrid(shifts_y, shifts_x, indexing="ij") + shift_x = shift_x.reshape(-1) + shift_y = shift_y.reshape(-1) + shifts = torch.stack((shift_x, shift_y, shift_x, shift_y), dim=1) + + # For every (base anchor, output anchor) pair, + # offset each zero-centered base anchor by the center of the output anchor. + anchors.append((shifts.view(-1, 1, 4) + base_anchors.view(1, -1, 4)).reshape(-1, 4)) return anchors diff --git a/torchvision/models/detection/fcos.py b/torchvision/models/detection/fcos.py index ba51e819f0a..c15702f5e18 100644 --- a/torchvision/models/detection/fcos.py +++ b/torchvision/models/detection/fcos.py @@ -615,8 +615,8 @@ def forward( # compute the losses if targets is None: raise ValueError("targets should not be none when in training mode") - else: - losses = self.compute_loss(targets, head_outputs, anchors, num_anchors_per_level) + + losses = self.compute_loss(targets, head_outputs, anchors, num_anchors_per_level) else: # split outputs per level split_head_outputs: Dict[str, List[Tensor]] = {} diff --git a/torchvision/models/detection/generalized_rcnn.py b/torchvision/models/detection/generalized_rcnn.py index 8ff31823f30..02719d66041 100644 --- a/torchvision/models/detection/generalized_rcnn.py +++ b/torchvision/models/detection/generalized_rcnn.py @@ -60,16 +60,16 @@ def forward(self, images, targets=None): if self.training: if targets is None: raise ValueError("In training mode, targets should be passed") - else: - for target in targets: - boxes = target["boxes"] - if isinstance(boxes, torch.Tensor): - if len(boxes.shape) != 2 or boxes.shape[-1] != 4: - raise ValueError( - f"Expected target boxes to be a tensor of shape [N, 4], got {boxes.shape}." - ) - else: - raise TypeError(f"Expected target boxes to be of type Tensor, got {type(boxes)}.") + + for target in targets: + boxes = target["boxes"] + if isinstance(boxes, torch.Tensor): + if len(boxes.shape) != 2 or boxes.shape[-1] != 4: + raise ValueError( + f"Expected target boxes to be a tensor of shape [N, 4], got {boxes.shape}." + ) + else: + raise TypeError(f"Expected target boxes to be of type Tensor, got {type(boxes)}.") original_image_sizes: List[Tuple[int, int]] = [] for img in images: diff --git a/torchvision/models/detection/roi_heads.py b/torchvision/models/detection/roi_heads.py index 949ff1e750f..74c6a694223 100644 --- a/torchvision/models/detection/roi_heads.py +++ b/torchvision/models/detection/roi_heads.py @@ -789,15 +789,15 @@ def forward( if self.training: if matched_idxs is None: raise ValueError("if in trainning, matched_idxs should not be None") - else: - # during training, only focus on positive boxes - num_images = len(proposals) - mask_proposals = [] - pos_matched_idxs = [] - for img_id in range(num_images): - pos = torch.where(labels[img_id] > 0)[0] - mask_proposals.append(proposals[img_id][pos]) - pos_matched_idxs.append(matched_idxs[img_id][pos]) + + # during training, only focus on positive boxes + num_images = len(proposals) + mask_proposals = [] + pos_matched_idxs = [] + for img_id in range(num_images): + pos = torch.where(labels[img_id] > 0)[0] + mask_proposals.append(proposals[img_id][pos]) + pos_matched_idxs.append(matched_idxs[img_id][pos]) else: pos_matched_idxs = None @@ -840,11 +840,11 @@ def forward( pos_matched_idxs = [] if matched_idxs is None: raise ValueError("if in trainning, matched_idxs should not be None") - else: - for img_id in range(num_images): - pos = torch.where(labels[img_id] > 0)[0] - keypoint_proposals.append(proposals[img_id][pos]) - pos_matched_idxs.append(matched_idxs[img_id][pos]) + + for img_id in range(num_images): + pos = torch.where(labels[img_id] > 0)[0] + keypoint_proposals.append(proposals[img_id][pos]) + pos_matched_idxs.append(matched_idxs[img_id][pos]) else: pos_matched_idxs = None @@ -856,22 +856,22 @@ def forward( if self.training: if targets is None or pos_matched_idxs is None: raise ValueError("both targets and pos_matched_idxs should not be None when in training mode") - else: - gt_keypoints = [t["keypoints"] for t in targets] - rcnn_loss_keypoint = keypointrcnn_loss( - keypoint_logits, keypoint_proposals, gt_keypoints, pos_matched_idxs - ) - loss_keypoint = {"loss_keypoint": rcnn_loss_keypoint} + + gt_keypoints = [t["keypoints"] for t in targets] + rcnn_loss_keypoint = keypointrcnn_loss( + keypoint_logits, keypoint_proposals, gt_keypoints, pos_matched_idxs + ) + loss_keypoint = {"loss_keypoint": rcnn_loss_keypoint} else: if keypoint_logits is None or keypoint_proposals is None: raise ValueError( "both keypoint_logits and keypoint_proposals should not be None when not in training mode" ) - else: - keypoints_probs, kp_scores = keypointrcnn_inference(keypoint_logits, keypoint_proposals) - for keypoint_prob, kps, r in zip(keypoints_probs, kp_scores, result): - r["keypoints"] = keypoint_prob - r["keypoints_scores"] = kps + + keypoints_probs, kp_scores = keypointrcnn_inference(keypoint_logits, keypoint_proposals) + for keypoint_prob, kps, r in zip(keypoints_probs, kp_scores, result): + r["keypoints"] = keypoint_prob + r["keypoints_scores"] = kps losses.update(loss_keypoint) return result, losses diff --git a/torchvision/models/detection/ssd.py b/torchvision/models/detection/ssd.py index 2e51fcfb547..087f14f0f17 100644 --- a/torchvision/models/detection/ssd.py +++ b/torchvision/models/detection/ssd.py @@ -365,21 +365,21 @@ def forward( if self.training: if targets is None: raise ValueError("targets should not be None when in training mode") - else: - matched_idxs = [] - for anchors_per_image, targets_per_image in zip(anchors, targets): - if targets_per_image["boxes"].numel() == 0: - matched_idxs.append( - torch.full( - (anchors_per_image.size(0),), -1, dtype=torch.int64, device=anchors_per_image.device - ) + + matched_idxs = [] + for anchors_per_image, targets_per_image in zip(anchors, targets): + if targets_per_image["boxes"].numel() == 0: + matched_idxs.append( + torch.full( + (anchors_per_image.size(0),), -1, dtype=torch.int64, device=anchors_per_image.device ) - continue + ) + continue - match_quality_matrix = box_ops.box_iou(targets_per_image["boxes"], anchors_per_image) - matched_idxs.append(self.proposal_matcher(match_quality_matrix)) + match_quality_matrix = box_ops.box_iou(targets_per_image["boxes"], anchors_per_image) + matched_idxs.append(self.proposal_matcher(match_quality_matrix)) - losses = self.compute_loss(targets, head_outputs, anchors, matched_idxs) + losses = self.compute_loss(targets, head_outputs, anchors, matched_idxs) else: detections = self.postprocess_detections(head_outputs, anchors, images.image_sizes) detections = self.transform.postprocess(detections, images.image_sizes, original_image_sizes) From f41e1152d7cb9f508a207fc84b109bb09d69e602 Mon Sep 17 00:00:00 2001 From: Joao Gomes Date: Tue, 15 Mar 2022 13:51:28 +0000 Subject: [PATCH 47/49] apply ufmt --- torchvision/models/detection/generalized_rcnn.py | 4 +--- torchvision/models/detection/ssd.py | 4 +--- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/torchvision/models/detection/generalized_rcnn.py b/torchvision/models/detection/generalized_rcnn.py index 02719d66041..dba8e5b8148 100644 --- a/torchvision/models/detection/generalized_rcnn.py +++ b/torchvision/models/detection/generalized_rcnn.py @@ -65,9 +65,7 @@ def forward(self, images, targets=None): boxes = target["boxes"] if isinstance(boxes, torch.Tensor): if len(boxes.shape) != 2 or boxes.shape[-1] != 4: - raise ValueError( - f"Expected target boxes to be a tensor of shape [N, 4], got {boxes.shape}." - ) + raise ValueError(f"Expected target boxes to be a tensor of shape [N, 4], got {boxes.shape}.") else: raise TypeError(f"Expected target boxes to be of type Tensor, got {type(boxes)}.") diff --git a/torchvision/models/detection/ssd.py b/torchvision/models/detection/ssd.py index 087f14f0f17..995562e32cd 100644 --- a/torchvision/models/detection/ssd.py +++ b/torchvision/models/detection/ssd.py @@ -370,9 +370,7 @@ def forward( for anchors_per_image, targets_per_image in zip(anchors, targets): if targets_per_image["boxes"].numel() == 0: matched_idxs.append( - torch.full( - (anchors_per_image.size(0),), -1, dtype=torch.int64, device=anchors_per_image.device - ) + torch.full((anchors_per_image.size(0),), -1, dtype=torch.int64, device=anchors_per_image.device) ) continue From ee21d2ed534dadf507b30b64200e0c524205a014 Mon Sep 17 00:00:00 2001 From: Joao Gomes Date: Tue, 15 Mar 2022 13:58:34 +0000 Subject: [PATCH 48/49] last pr comment --- torchvision/models/feature_extraction.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/torchvision/models/feature_extraction.py b/torchvision/models/feature_extraction.py index 5fb3318bf20..17a4a2511c5 100644 --- a/torchvision/models/feature_extraction.py +++ b/torchvision/models/feature_extraction.py @@ -502,6 +502,8 @@ def to_strdict(n) -> Dict[str, str]: for n in reversed(graph_module.graph.nodes): if n.op == "output": orig_output_nodes.append(n) + if not orig_output_nodes: + raise RuntimeError("No output nodes found in graph_module.graph.nodes") for n in orig_output_nodes: graph_module.graph.erase_node(n) From d0002388ea74ebbadacb9ea3a2354655a7458408 Mon Sep 17 00:00:00 2001 From: Joao Gomes Date: Tue, 15 Mar 2022 16:35:48 +0000 Subject: [PATCH 49/49] replace RuntimeErrors --- torchvision/models/detection/anchor_utils.py | 4 ++-- torchvision/models/detection/roi_heads.py | 4 ++-- torchvision/models/detection/ssd.py | 2 +- torchvision/models/detection/ssdlite.py | 2 +- torchvision/models/feature_extraction.py | 6 +++--- torchvision/prototype/models/detection/ssdlite.py | 2 +- 6 files changed, 10 insertions(+), 10 deletions(-) diff --git a/torchvision/models/detection/anchor_utils.py b/torchvision/models/detection/anchor_utils.py index 9b956ca7d76..3248fc2e1aa 100644 --- a/torchvision/models/detection/anchor_utils.py +++ b/torchvision/models/detection/anchor_utils.py @@ -86,7 +86,7 @@ def grid_anchors(self, grid_sizes: List[List[int]], strides: List[List[Tensor]]) cell_anchors = self.cell_anchors if cell_anchors is None: - raise RuntimeError("cell_anchors should not be None") + ValueError("cell_anchors should not be None") if not (len(grid_sizes) == len(strides) == len(cell_anchors)): raise ValueError( @@ -165,7 +165,7 @@ def __init__( ): super().__init__() if steps is not None and len(aspect_ratios) != len(steps): - raise RuntimeError("aspect_ratios and steps should have the same length") + raise ValueError("aspect_ratios and steps should have the same length") self.aspect_ratios = aspect_ratios self.steps = steps self.clip = clip diff --git a/torchvision/models/detection/roi_heads.py b/torchvision/models/detection/roi_heads.py index 74c6a694223..9f2ef20d17c 100644 --- a/torchvision/models/detection/roi_heads.py +++ b/torchvision/models/detection/roi_heads.py @@ -767,9 +767,9 @@ def forward( losses = {} if self.training: if labels is None: - raise RuntimeError("labels cannot be None") + raise ValueError("labels cannot be None") if regression_targets is None: - raise RuntimeError("regression_targets cannot be None") + raise ValueError("regression_targets cannot be None") loss_classifier, loss_box_reg = fastrcnn_loss(class_logits, box_regression, labels, regression_targets) losses = {"loss_classifier": loss_classifier, "loss_box_reg": loss_box_reg} else: diff --git a/torchvision/models/detection/ssd.py b/torchvision/models/detection/ssd.py index 995562e32cd..bd7f1b2863f 100644 --- a/torchvision/models/detection/ssd.py +++ b/torchvision/models/detection/ssd.py @@ -197,7 +197,7 @@ def __init__( out_channels = det_utils.retrieve_out_channels(backbone, size) if len(out_channels) != len(anchor_generator.aspect_ratios): - raise RuntimeError( + raise ValueError( f"The length of the output channels from the backbone ({len(out_channels)}) do not match the length of the anchor generator aspect ratios ({len(anchor_generator.aspect_ratios)})" ) diff --git a/torchvision/models/detection/ssdlite.py b/torchvision/models/detection/ssdlite.py index 10cd0c1cb8a..1c59814f8d4 100644 --- a/torchvision/models/detection/ssdlite.py +++ b/torchvision/models/detection/ssdlite.py @@ -248,7 +248,7 @@ def ssdlite320_mobilenet_v3_large( out_channels = det_utils.retrieve_out_channels(backbone, size) num_anchors = anchor_generator.num_anchors_per_location() if len(out_channels) != len(anchor_generator.aspect_ratios): - raise RuntimeError( + raise ValueError( f"The length of the output channels from the backbone {len(out_channels)} do not match the length of the anchor generator aspect ratios {len(anchor_generator.aspect_ratios)}" ) diff --git a/torchvision/models/feature_extraction.py b/torchvision/models/feature_extraction.py index 17a4a2511c5..a6c26913093 100644 --- a/torchvision/models/feature_extraction.py +++ b/torchvision/models/feature_extraction.py @@ -292,7 +292,7 @@ def __init__( # serialize a GraphModule without retaining the Graph, and needs to use the correct Tracer # to re-create the Graph during deserialization. if self.eval_graph._tracer_cls != self.train_graph._tracer_cls: - raise RuntimeError( + raise TypeError( f"Train mode and eval mode should use the same tracer class. Instead got {self.eval_graph._tracer_cls} for eval vs {self.train_graph._tracer_cls} for train" ) self._tracer_cls = None @@ -481,7 +481,7 @@ def to_strdict(n) -> Dict[str, str]: available_nodes = list(tracer.node_to_qualname.values()) # FIXME We don't know if we should expect this to happen if len(set(available_nodes)) != len(available_nodes): - raise RuntimeError( + raise ValueError( "There are duplicate nodes! Please raise an issue https://github.com/pytorch/vision/issues" ) # Check that all outputs in return_nodes are present in the model @@ -503,7 +503,7 @@ def to_strdict(n) -> Dict[str, str]: if n.op == "output": orig_output_nodes.append(n) if not orig_output_nodes: - raise RuntimeError("No output nodes found in graph_module.graph.nodes") + raise ValueError("No output nodes found in graph_module.graph.nodes") for n in orig_output_nodes: graph_module.graph.erase_node(n) diff --git a/torchvision/prototype/models/detection/ssdlite.py b/torchvision/prototype/models/detection/ssdlite.py index 45fe078568b..f69e860dff4 100644 --- a/torchvision/prototype/models/detection/ssdlite.py +++ b/torchvision/prototype/models/detection/ssdlite.py @@ -99,7 +99,7 @@ def ssdlite320_mobilenet_v3_large( out_channels = det_utils.retrieve_out_channels(backbone, size) num_anchors = anchor_generator.num_anchors_per_location() if len(out_channels) != len(anchor_generator.aspect_ratios): - raise RuntimeError( + raise ValueError( f"The length of the output channels from the backbone {len(out_channels)} do not match the length of the anchor generator aspect ratios {len(anchor_generator.aspect_ratios)}" )