The model consists of a Encoder CNN used to extract features and a decoder Rnn which generated the caption
This is the exact model:
https://github.com/yunjey/pytorch-tutorial/tree/master/tutorials/03-advanced/image_captioning
If you can let me know the process for calculating and visualising Integrated Grads and Grad Cam , it would be very helpful, As I wish to interpret this image captioning model using Captum.
Thanks
Hi @shaunak27, thank you for creating the issue. Note that GradCam is meaningful to apply on models from CNN family (on a convolutional layer).
W.r.t. IG, you can definitely apply on that model. As an output, you can take a token such as 'Giraffes' and attribute it to the pixels of the image. Have you tried something like that ?
@NarineK Thank you very much for your help. Sorry for replying late, I followed the tutorial related to VQA for calculating and visualizing Integrated Gradient with Captum for my Image Captioning Problem.
The model which I have used takes in an image as input and returns a list of indices like [2,14,1,6,8]
which are the indices of words(tokens) from my vocab. So when I used the ig.attribute function as:
```
attributions = ig.attribute(inputs=image_features,baselines=image_features * 0.0,
target = 3, n_steps=30)
When I run this function I get an error :
> element 0 of tensors does not require grad and does not have a grad_fn
The following is the model that I have used:
class Encodersub(nn.Module):
def __init__(self, embed_size):
"""Load the pretrained ResNet-152 and replace top fc layer."""
super(Encodersub, self).__init__()
resnet = models.resnet152(pretrained=True)
modules = list(resnet.children())[:-1] # delete the last fc layer.
self.resnet = nn.Sequential(*modules)
self.linear = nn.Linear(resnet.fc.in_features, embed_size)
self.bn = nn.BatchNorm1d(embed_size, momentum=0.01)
def forward(self, images):
"""Extract feature vectors from input images."""
features = self.resnet(images)
features = features.reshape(features.size(0), -1)
features = self.bn(self.linear(features))
return features
class Decodermain(nn.Module):
def __init__(self, embed_size, hidden_size, vocab_size, num_layers, max_seq_length=20):
"""Set the hyper-parameters and build the layers."""
super(Decodermain, self).__init__()
self.encoder = Encodersub(embed_size)
self.embed = nn.Embedding(vocab_size, embed_size)
self.lstm = nn.LSTM(embed_size, hidden_size, num_layers, batch_first=True)
self.linear = nn.Linear(hidden_size, vocab_size)
self.max_seg_length = max_seq_length
def forward(self, features, captions, lengths):
"""Decode image feature vectors and generates captions."""
features = self.encoder(features)
embeddings = self.embed(captions)
embeddings = torch.cat((features.unsqueeze(1), embeddings), 1)
packed = pack_padded_sequence(embeddings, lengths, batch_first=True)
hiddens, _ = self.lstm(packed)
outputs = self.linear(hiddens[0])
return outputs
def sample(self, features, states=None):
"""Generate captions for given image features using greedy search."""
sampled_ids = []
features = self.encoder(features)
inputs = features.unsqueeze(1)
for i in range(self.max_seg_length):
hiddens, states = self.lstm(inputs, states) # hiddens: (batch_size, 1, hidden_size)
outputs = self.linear(hiddens.squeeze(1)) # outputs: (batch_size, vocab_size)
_, predicted = outputs.max(1) # predicted: (batch_size)
sampled_ids.append(predicted)
inputs = self.embed(predicted) # inputs: (batch_size, embed_size)
inputs = inputs.unsqueeze(1) # inputs: (batch_size, 1, embed_size)
sampled_ids = torch.stack(sampled_ids, 1) # sampled_ids: (batch_size,max_seq_length)
return sampled_ids
``
Also I have used sample as my forward_func in Integrated Grad. as:
ig = IntegratedGradients(model.sample)`
where model = Decodermain()
I would be really grateful If you could help me here.
Thank you
@NarineK Any Issue in my Code that might result into this error?
@NarineK It would be great If you could help me with this one, as I am not sure which part of my code is responsible for this error. Thanks !
Hi @shaunak27 , I took a quick look at your code, the issue is that you cannot take gradients with respect to argmax indices. You would instead need to attribute with respect to the output probability of the token, rather than the token index. To do this, you should modify your model to also store the score of the top token, e.g.
score, predicted = outputs.max(1)
and return the stacked scores. You will then be able to attribute with respect to the corresponding score.
Hi @vivekmig , Thank you so much for advice, It worked perfectly after incorporating the change that use suggested. Really grateful for your help.
Great, I'm glad it worked!
Most helpful comment
Hi @shaunak27, thank you for creating the issue. Note that GradCam is meaningful to apply on models from CNN family (on a convolutional layer).
W.r.t. IG, you can definitely apply on that model. As an output, you can take a token such as 'Giraffes' and attribute it to the pixels of the image. Have you tried something like that ?