Skip to content

Replace assert with ValueError in AnchorGenerator #2947

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
oke-aditya opened this issue Nov 2, 2020 · 2 comments · Fixed by #2960
Closed

Replace assert with ValueError in AnchorGenerator #2947

oke-aditya opened this issue Nov 2, 2020 · 2 comments · Fixed by #2960

Comments

@oke-aditya
Copy link
Contributor

oke-aditya commented Nov 2, 2020

🐛 Bug

I think with the Retina Net PR, there was an update to anchor utils.
My old code still works fine on torchvision 0.7 and pytorch 1.6. But on upgrading to 0.8 it doesn't.
I am not sure if this was BC Breaking change.

To Reproduce

Steps to reproduce the behavior:

  1. Following is the code block to create FRCNN
import torchvision
import torchvision.transforms as T
from torchvision.models.detection.rpn import AnchorGenerator
from torchvision.models.detection import FasterRCNN

device = torch.device('cuda') if torch.cuda.is_available() else torch.device('cpu')

def create_model(num_classes, min_size=300, max_size=500, backbone="mobile_net"):

    model = torchvision.models.detection.fasterrcnn_resnet50_fpn(pretrained=True)
    in_features = model.roi_heads.box_predictor.cls_score.in_features

    ft_mean = [0.485, 0.456, 0.406]
    ft_std = [0.229, 0.224, 0.225]

    mobile_net = torchvision.models.mobilenet_v2(pretrained=True)

    ft_backbone = mobile_net.features
    ft_backbone.out_channels = 1280

    ft_model = FasterRCNN(backbone=ft_backbone,
                        num_classes=num_classes, 
                        image_mean=ft_mean, 
                        image_std=ft_std,)
  1. When I do These three function sequeantially

def load_model():
    detector = model.create_model(num_classes=config.NUM_CLASSES)
    detector.load_state_dict(torch.load(config.MODEL_SAVE_PATH, map_location=device))
    detector.eval()
    detector.to(device)
    return detector


def load_image_tensor(image_path, device):
    image_tensor = T.ToTensor() (Image.open(image_path))
    input_images = [image_tensor.to(device)]
    return input_images


def get_prediction(detector, images):
    with torch.no_grad():
        prediction = detector(images)
        return prediction

I get an assertion error from this line

Expected behavior

It should work fine, I think an upgrade to torchvision should not break Anchor utils for FRCNN.

Environment

  • PyTorch / torchvision Version (e.g., 1.0 / 0.4.0): PT -> 1.7 TV-> 0.8.1
  • OS (e.g., Linux): Windows
  • How you installed PyTorch / torchvision (conda, pip, source): conda
  • Build command you used (if compiling from source):
  • Python version: 3.7
  • CUDA/cuDNN version: NA
  • GPU models and configuration: NA

Additional context

  1. Maybe something has changed and I'm not aware of
  2. Can we remove these assertions and raise ValueError with suitable messages ? I cannot debug at all with assert errors.
  3. Slightly associated with [RFC] How to handle BC breaking changes on Model weights or hyper-parameters #2955
@fmassa
Copy link
Member

fmassa commented Nov 3, 2020

Hi,

Thanks for opening this issue.

I believe the code snippet that you included is not supposed to work, and it only worked before by accident (although potentially leading to worse results)

Indeed, you need to pass a custom AnchorGenerator that will only return one feature map, as your backbone is only returning one feature map.

The assert was added in #2722 as the without the assert users were using it incorrectly, which could lead to worse results.

The expected way to construct the model with mobilenet so that it works is illustrated in the documentation

>>> backbone = torchvision.models.mobilenet_v2(pretrained=True).features
>>> # FasterRCNN needs to know the number of
>>> # output channels in a backbone. For mobilenet_v2, it's 1280
>>> # so we need to add it here
>>> backbone.out_channels = 1280
>>>
>>> # let's make the RPN generate 5 x 3 anchors per spatial
>>> # location, with 5 different sizes and 3 different aspect
>>> # ratios. We have a Tuple[Tuple[int]] because each feature
>>> # map could potentially have different sizes and
>>> # aspect ratios
>>> anchor_generator = AnchorGenerator(sizes=((32, 64, 128, 256, 512),),
>>> aspect_ratios=((0.5, 1.0, 2.0),))
>>>
>>> # let's define what are the feature maps that we will
>>> # use to perform the region of interest cropping, as well as
>>> # the size of the crop after rescaling.
>>> # if your backbone returns a Tensor, featmap_names is expected to
>>> # be ['0']. More generally, the backbone should return an
>>> # OrderedDict[Tensor], and in featmap_names you can choose which
>>> # feature maps to use.
>>> roi_pooler = torchvision.ops.MultiScaleRoIAlign(featmap_names=['0'],
>>> output_size=7,
>>> sampling_ratio=2)
>>>
>>> # put the pieces together inside a FasterRCNN model
>>> model = FasterRCNN(backbone,
>>> num_classes=2,
>>> rpn_anchor_generator=anchor_generator,
>>> box_roi_pool=roi_pooler)
>>> model.eval()
>>> x = [torch.rand(3, 300, 400), torch.rand(3, 500, 400)]
>>> predictions = model(x)

We would be glad to accept a PR removing the assert and adding a ValueError message instead. Could you send a PR with it?

@fmassa fmassa changed the title RPN Anchor error in torchvision 0.8.1 Replace assert with ValueError in AnchorGenerator Nov 3, 2020
@oke-aditya
Copy link
Contributor Author

Hi, Thank you for answering this.
Yes definitely. I will send PR removing assert.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants