Search code examples
deep-learningpytorchtransfer-learning

PyTorch AttributeError: 'UNet3D' object has no attribute 'size'


I am making an image segmentation transfer learning project using Pytorch. I am using the weights of this pre-trained model and class UNet3D. https://github.com/MrGiovanni/ModelsGenesis

When I run the following codes I get this error at the line which MSELoss is called: "AttributeError: 'DataParallel' object has no attribute 'size' ".

When I delete the first line I get a similar error: "AttributeError: 'UNet3D' object has no attribute 'size'

"

How can I convert DataParallel or UNet3D class to an object which MSELoss can use? I do not need DataParallel for now. I need to run the UNet3D() class for transfer learning.

model = nn.DataParallel(model, device_ids = [i for i in range(torch.cuda.device_count())])
criterion = nn.MSELoss()
optimizer = torch.optim.SGD(model.parameters(), conf.lr, momentum=0.9, weight_decay=0.0, nesterov=False)
scheduler = lr_scheduler.StepLR(optimizer, step_size=7, gamma=0.1)
initial_epoch=10
for epoch in range(initial_epoch, conf.nb_epoch):
    scheduler.step(epoch)
    model.train()
    for batch_ndx, (x,y) in enumerate(train_loader):
        x, y = x.float().to(device), y.float().to(device)
        pred = model
        loss = criterion(pred, y)
        optimizer.zero_grad()
        loss.backward()
        optimizer.step()
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
<ipython-input-46-20d1943b3498> in <module>
     25         x, y = x.float().to(device), y.float().to(device)
     26         pred = model
---> 27         loss = criterion(pred, y)
     28         optimizer.zero_grad()
     29         loss.backward()

/opt/anaconda3/lib/python3.7/site-packages/torch/nn/modules/module.py in __call__(self, *input, **kwargs)
    548             result = self._slow_forward(*input, **kwargs)
    549         else:
--> 550             result = self.forward(*input, **kwargs)
    551         for hook in self._forward_hooks.values():
    552             hook_result = hook(self, input, result)

/opt/anaconda3/lib/python3.7/site-packages/torch/nn/modules/loss.py in forward(self, input, target)
    430 
    431     def forward(self, input, target):
--> 432         return F.mse_loss(input, target, reduction=self.reduction)
    433 
    434 

/opt/anaconda3/lib/python3.7/site-packages/torch/nn/functional.py in mse_loss(input, target, size_average, reduce, reduction)
   2528                 mse_loss, tens_ops, input, target, size_average=size_average, reduce=reduce,
   2529                 reduction=reduction)
-> 2530     if not (target.size() == input.size()):
   2531         warnings.warn("Using a target size ({}) that is different to the input size ({}). "
   2532                       "This will likely lead to incorrect results due to broadcasting. "

/opt/anaconda3/lib/python3.7/site-packages/torch/nn/modules/module.py in __getattr__(self, name)
    592                 return modules[name]
    593         raise AttributeError("'{}' object has no attribute '{}'".format(
--> 594             type(self).__name__, name))
    595 
    596     def __setattr__(self, name, value):

AttributeError: 'UNet3D' object has no attribute 'size'


Solution

  • You have a typo on this line:

    pred = model
    

    should be

    pred = model(x)
    

    model is nn.Module object which describes the network. x, y, pred are (supposed to be) torch tensors.

    Aside from this particular case, I think it would be good to think about how to solve this type of problems in general.

    You saw an error (exception) on a certain line. Is the problem there, or earlier? Can you isolate the problem?

    For example, if you print out the arguments you're passing to criterion(pred, y) just before the call, do they look right? (they don't)

    What happens if you create a couple of tensors of the right shape just before the call and pass them instead? (works fine)

    What is the error really saying? "AttributeError: 'UNet3D' object has no attribute 'size'" - well, of course it's not supposed to have a size, but why is the code trying to access it's size? Actually, why is the code even able to access that object on that line? (since the model is not supposed to be passed to the criterion function - right?)

    Maybe useful further reading: https://ericlippert.com/2014/03/05/how-to-debug-small-programs/