NotImplementedError - identation and typos checked

Hi everyone, I’ve been recently implementing and adapting a repository of a Faster R-CNN to train it on some own data and research a couple little questions. So I’ve adapted and added some functionalities in the code, and for this current error I can not help myself anymore - I keep running into the NotImplementedError that says that I haven’t implemented the forward-function, although I did and I watched out for typos and identation.

Here is the code of my model-class and the forward function

class Model(torch.nn.Module):
    def __init__(self, num_classes):
        super(Model, self).__init__()
        self.model = torchvision.models.detection.fasterrcnn_resnet50_fpn(pretrained=True)
        in_features = self.model.roi_heads.box_predictor.cls_score.in_features
        self.model.roi_heads.box_predictor = FastRCNNPredictor(in_features, num_classes)
        
        def forward(self, images, targets=None):
            # Perform the forward pass computation
            if self.training and targets is None:
                raise ValueError("In training mode, targets should be passed to the forward method.")
            
            if self.training:
                # Separate images and targets
                images = [image for image in images]
                targets = [{k: v for k, v in t.items()} for t in targets]
                
                # Calculate losses
                losses = self.model(images, targets)
                return losses
            
            outputs = self.model(images)
            return outputs

And here is the error:

Traceback (most recent call last):
  File "train.py", line 132, in <module>
    main()
  File "train.py", line 108, in main
    evaluate(model, data_loader_test, device=device)
  File "/solaris/anaconda3/envs/od-env/lib/python3.7/site-packages/torch/autograd/grad_mode.py", line 26, in decorate_context
    return func(*args, **kwargs)
  File "/solaris/faster_r-cnn/src/engine.py", line 167, in evaluate
    outputs = model(image, targets) # targets added because Forward Method implemented
  File "/solaris/anaconda3/envs/od-env/lib/python3.7/site-packages/torch/nn/modules/module.py", line 727, in _call_impl
    result = self.forward(*input, **kwargs)
  File "train.py", line 46, in forward
    losses = self.model(images, targets)
  File "/solaris/anaconda3/envs/od-env/lib/python3.7/site-packages/torch/nn/modules/module.py", line 727, in _call_impl
    result = self.forward(*input, **kwargs)
  File "/solaris/anaconda3/envs/od-env/lib/python3.7/site-packages/torch/nn/modules/module.py", line 175, in _forward_unimplemented
    raise NotImplementedError
NotImplementedError

Does anyone know what it is that I am missing here?

Thanks and best,
S.

check your indentation. Currently you define a “forward” function inside the init block. But you want to define a forward method belonging to your Model

class Model(torch.nn.Module):
    def __init__(self, num_classes):
[...]
        def forward(self, images, targets=None):
            # Perform the forward pass computation
            if self.training and targets is None:
                raise ValueError("In training mode, targets should be passed to the forward method.")
            
            if self.training:
                # Separate images and targets
                images = [image for image in images]
                targets = [{k: v for k, v in t.items()} for t in targets]
                
                # Calculate losses
                losses = self.model(images, targets)
                return losses
            
            outputs = self.model(images)
            return outputs

should be

class Model(torch.nn.Module):
    def __init__(self, num_classes):
[...]
    def forward(self, images, targets=None): #indented one level to the left
        # Perform the forward pass computation
        if self.training and targets is None:
            raise ValueError("In training mode, targets should be passed to the forward method.")
        
        if self.training:
            # Separate images and targets
            images = [image for image in images]
            targets = [{k: v for k, v in t.items()} for t in targets]
                
            # Calculate losses
            losses = self.model(images, targets)
            return losses
            
        outputs = self.model(images)
        return outputs

oh! Thank you!! :slight_smile:

I thought it must be the other way around. I get back to you as soon as I tried it!

Btw. Do you have a further information on why this error raises. I did got into the module.py file of the torch-library to fin out, what exactly is the problem.

Background of my question is, that I am just implementing the model from a public repo that is connected to a paper, because I want to see how it works and make it run for getting to know some pytorch-models. Therefor I assume that the programmers of this public repository made the code work without implementing the forward method, because the forward-method is not implemented.

Do you know if there MUST be a forward-method in the model-class, or are there scenarios possible where the code of a pytorch-model runs properly without having the forward-method.

Furthermore: When I change the code to implement a forward-method into the model-class, I still run into the notImplementedError:

class AppleDetectionModel(torch.nn.Module):
    def __init__(self, num_classes):
        super(AppleDetectionModel, self).__init__()
        self.model = torchvision.models.detection.maskrcnn_resnet50_fpn(pretrained=True)
        in_features = self.model.roi_heads.box_predictor.cls_score.in_features
        self.model.roi_heads.box_predictor = FastRCNNPredictor(in_features, num_classes)
        in_features_mask = self.model.roi_heads.mask_predictor.conv5_mask.in_channels
        hidden_layer = 256
        self.model.roi_heads.mask_predictor = MaskRCNNPredictor(in_features_mask, hidden_layer, num_classes)

    def forward(self, images, targets=None):
        if self.training and targets is not None:
            return self.model(images, targets)
        else:
            return self.model(images, targets)
python train_rcnn.py --data_path /MinneApple/dataset --model frcnn --epochs 50 --output-dir /MinneApple/output
frcnn
Namespace(batch_size=2, data_path='/MinneApple/dataset', dataset='AppleDataset', device='cuda', epochs=50, lr=0.02, lr_gamma=0.1, lr_step_size=8, lr_steps=[8, 11], model='frcnn', momentum=0.9, output_dir='/MinneApple/output', print_freq=20, resume='', weight_decay=0.0001, workers=4)
Loading data
Creating data loaders
Creating model
Start training
Traceback (most recent call last):
  File "train_rcnn.py", line 128, in <module>
    main(args)
  File "train_rcnn.py", line 82, in main
    train_one_epoch(model, optimizer, data_loader, device, epoch, args.print_freq)
  File "/MinneApple/utility/engine.py", line 29, in train_one_epoch
    loss_dict = model(images, targets)
  File "/project/anaconda3/envs/project/lib/python3.7/site-packages/torch/nn/modules/module.py", line 727, in _call_impl
    result = self.forward(*input, **kwargs)
  File "train_rcnn.py", line 30, in forward
    return self.model(images, targets)
  File "/project/anaconda3/envs/project/lib/python3.7/site-packages/torch/nn/modules/module.py", line 727, in _call_impl
    result = self.forward(*input, **kwargs)
  File "/project/anaconda3/envs/project/lib/python3.7/site-packages/torch/nn/modules/module.py", line 175, in _forward_unimplemented
    raise NotImplementedError
NotImplementedError

Best,
S.

to put it simple: you don’t need a forward call. Except:

  1. you want to define a custom backward function
  2. you use a library that expects the forward call to exist
  3. you want to use hooks. Pytorch needs to know that the layers belong to a module in order to notify you when interesting things like the forward or backward passes happen

The forward call is implicitly called by the __call__ method. This means that it is called when you use model(xyz). In your code you call

self.model(images, targets)

and the exception shows that this call is forwarded to model.forward, which does not exist. So it seems like your

FastRCNNPredictor(in_features, num_classes)

does not have a forward method either.Have you implemented this one as well? If so, add a forward call. If not, check out the documentation of this model and see how the authors want it to be called

EDIT:
I’ve checked out torchvision.models.detection.maskrcnn_resnet50_fpn

model = torchvision.models.detection.maskrcnn_resnet50_fpn(weights=MaskRCNN_ResNet50_FPN_Weights.DEFAULT)
model.eval()
x = [torch.rand(3, 300, 400), torch.rand(3, 500, 400)]
predictions = model(x)

In the documentation they are using it with the __call__ so you need to check your modifications like FastRCNNPredictor

Wow! Thank you! That is very precise - I will follow your steps and get back to you with my results.

EDIT: Why did you checked out torchvision.models.detection.maskrcnn_resnet50_fpn, and nottorchvision.models.detection.faster_rcnn_resnet50_fpn ?

you are right. Seems like I landed on the wrong page somehow. Luckily it doesn’t make a difference because torchvision.models.detection.fasterrcnn_resnet50_fpn also uses the call operator :grinning: