Captum Atrribute Error

Hi, I encountered an error while I am trying to run captum XAI API(such as GradCam and Saliency).

This is the error. I can’t resolve this issue by myself.

---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
Input In [81], in <cell line: 2>()
      1 saliency = Saliency(netD_i)
----> 2 grads = saliency.attribute(input3, target=label_y[0].item())

File ~/anaconda3/envs/mitre_gan/lib/python3.10/site-packages/captum/log/__init__.py:35, in log_usage.<locals>._log_usage.<locals>.wrapper(*args, **kwargs)
     33 @wraps(func)
     34 def wrapper(*args, **kwargs):
---> 35     return func(*args, **kwargs)

File ~/anaconda3/envs/mitre_gan/lib/python3.10/site-packages/captum/attr/_core/saliency.py:130, in Saliency.attribute(self, inputs, target, abs, additional_forward_args)
    126 gradient_mask = apply_gradient_requirements(inputs)
    128 # No need to format additional_forward_args here.
    129 # They are being formated in the `_run_forward` function in `common.py`
--> 130 gradients = self.gradient_func(
    131     self.forward_func, inputs, target, additional_forward_args
    132 )
    133 if abs:
    134     attributions = tuple(torch.abs(gradient) for gradient in gradients)

File ~/anaconda3/envs/mitre_gan/lib/python3.10/site-packages/captum/_utils/gradient.py:112, in compute_gradients(forward_fn, inputs, target_ind, additional_forward_args)
     94 r"""
     95 Computes gradients of the output with respect to inputs for an
     96 arbitrary forward function.
   (...)
    108                 arguments) if no additional arguments are required
    109 """
    110 with torch.autograd.set_grad_enabled(True):
    111     # runs forward pass
--> 112     outputs = _run_forward(forward_fn, inputs, target_ind, additional_forward_args)
    113     assert outputs[0].numel() == 1, (
    114         "Target not provided when necessary, cannot"
    115         " take gradient with respect to multiple outputs."
    116     )
    117     # torch.unbind(forward_out) is a list of scalar tensor tuples and
    118     # contains batch_size * #steps elements

File ~/anaconda3/envs/mitre_gan/lib/python3.10/site-packages/captum/_utils/common.py:461, in _run_forward(forward_func, inputs, target, additional_forward_args)
    454 additional_forward_args = _format_additional_forward_args(additional_forward_args)
    456 output = forward_func(
    457     *(*inputs, *additional_forward_args)
    458     if additional_forward_args is not None
    459     else inputs
    460 )
--> 461 return _select_targets(output, target)

File ~/anaconda3/envs/mitre_gan/lib/python3.10/site-packages/captum/_utils/common.py:468, in _select_targets(output, target)
    465 if target is None:
    466     return output
--> 468 num_examples = output.shape[0]
    469 dims = len(output.shape)
    470 device = output.device

AttributeError: 'tuple' object has no attribute 'shape'

This is the code that cause the error.

saliency = Saliency(netD_i)
grads = saliency.attribute(input3, target=label_y[0].item())

My model as an input of Captum API


class Discriminator(nn.Module):
    def __init__(self, num_class):
        super(Discriminator, self).__init__()


        self.main = nn.Sequential(
            # input is 1 x 110 x 408
            nn.Conv2d(1, ndf, (4,6), (2,3), bias=False),
            nn.LeakyReLU(0.2, inplace=True),
            # state size. (ndf) x 54 x 135

            nn.Conv2d(ndf, ndf * 2, (8,9), (2,3), bias=False),
            nn.InstanceNorm2d(ndf * 2, affine= True),
            nn.LeakyReLU(0.2, inplace=True),
            # state size. (ndf*2) x 24 x 43

            nn.Conv2d(ndf * 2, ndf * 4, (6,3), (2,2), bias=False),
            nn.InstanceNorm2d(ndf * 4, affine= True),
            nn.LeakyReLU(0.2, inplace=True),
            # state size. (ndf*4) x 10 x 21

            nn.Conv2d(ndf * 4, ndf * 8, (4,6), (2,3), bias=False),
            nn.InstanceNorm2d(ndf * 8, affine= True),
            nn.LeakyReLU(0.2, inplace=True),
            # state size. (ndf*8) x 4 x 6
        )

        self.critic_layer = nn.Sequential(nn.Conv2d(ndf * 8, 1, (4,6), 1, bias=False))
        
        # self.aux_layer = nn.Sequential(nn.Flatten(), nn.Linear(ndf * 8 * 4 * 6, num_class))
        self.aux_layer = nn.Linear(ndf * 8 * 4 * 6, num_class)
        

    def forward(self, input):
        # embedding = self.embed_layer(labels).view(labels.shape[0], 1, self.tech_h, self.tech_w)
        # input = torch.cat([input, embedding], dim= 1)
        input = self.main(input)
        critic = self.critic_layer(input)
        
        input2 = torch.flatten(input, 1)
        pred_label = self.aux_layer(input2)
        
        return critic, pred_label

# Create the Discriminator
netD = Discriminator(num_class)
netD.cuda()

I would really appreciate your help! Thx!

For whom will encounter this same problem, I decide to remain this post

I solved this by using self.training attribute at the last of my model class.

if self.training:
    return critic, pred_label
else:
    return pred_label

And if you see the some gather error, change the type into int64 like tensor.type(torch.int64)

Solved!!!