How to select a specific layer in VGG network

Surpuissant: <p>Hi everyone,</p>
<p>I am implementing a CNN to differentiate two types of images and I would like to use the grad-cam library <a href="https://github.com/jacobgil/pytorch-grad-cam" class="inline-onebox" rel="noopener nofollow ugc">GitHub - jacobgil/pytorch-grad-cam: Advanced AI Explainability for computer vision. Support for CNNs, Vision Transformers, Classification, Object detection, Segmentation, Image similarity and more.</a> to explain the predictions of the network.<br>
The network I used is a pre-trained VGG followed by two fully connected layers.<br>
I need to tell the grad-cam function the target layer, but I can’t figure out the right way to do it.</p>
<p>On the website they suggest this syntax target_layer = model.features[-1] . But as I used nn.sequential, it doesn’t work.</p>
<p>Do you know how to do it in this case?</p>
<p>I attach my code below.</p>
<p>Thanks a lot for your help.</p>
<blockquote>
<p>import matplotlib.pyplot as plt<br>
from torchvision import datasets, transforms<br>
from torch.utils.data import DataLoader<br>
import torch.nn as nn<br>
import torch.nn.functional as F<br>
import torch.optim as optim<br>
import torch<br>
import pandas as pd<br>
import cv2<br>
from torchvision import models<br>
import numpy as np<br>
from torch.autograd import Variable<br>
from PIL import Image<br>
from PIL import ImageFile<br>
ImageFile.LOAD_TRUNCATED_IMAGES = True</p>
</blockquote>
<blockquote>
<p>vgg16 = models.vgg16(pretrained=True)<br>
mod = nn.Sequential(*list(vgg16.children())[:-1])</p>
</blockquote>
<blockquote>
<p>class Net(nn.Module):<br>
def <strong>init</strong>(self):<br>
super(Net,self).<strong>init</strong>()<br>
<span class="hashtag-raw">#img</span> = images<br>
self.fc1=nn.Linear(512<em>7</em>7,32)<br>
self.fc2=nn.Linear(32,2)</p>
</blockquote>
<pre><code>def forward(self,x):     
    x = x.view(x.size(0), 512*7*7)
    x = F.relu(self.fc1(x))
    x = self.fc2(x)
    return  x
</code></pre>
<blockquote>
<p>model=nn.Sequential(mod,Net())</p>
</blockquote>
<blockquote>
<p>model_parameters = filter(lambda p: p.requires_grad, model.parameters())<br>
params = sum([np.prod(p.size()) for p in model_parameters])<br>
print(params)</p>
</blockquote>
<blockquote>
<p>from pytorch_grad_cam import GradCAM, HiResCAM, ScoreCAM, GradCAMPlusPlus, AblationCAM, XGradCAM, EigenCAM, FullGrad<br>
from pytorch_grad_cam.utils.model_targets import ClassifierOutputTarget<br>
from pytorch_grad_cam.utils.image import show_cam_on_image</p>
</blockquote>
<blockquote>
<p>target_layers = list(model.children())[0][:-1] <span class="hashtag-raw">#this</span> is not good…</p>
</blockquote>
<blockquote>
<p>cam = HiResCAM(model=model, target_layers=target_layers, use_cuda= False)<br>
grayscale_cam = cam(input_tensor=input_tensor.unsqueeze(0))<br>
grayscale_cam = grayscale_cam[0, :]<br>
visualization = show_cam_on_image(test_image, grayscale_cam)<br>
imgplot = plt.imshow(visualization)<br>
plt.show()</p>
</blockquote>

Surpuissant: <p>Any ideas please ? <img src="https://discuss.pytorch.org/images/emoji/apple/pray.png?v=12" title=":pray:" class="emoji" alt=":pray:" loading="lazy" width="20" height="20"></p>

ambujpawar: <p>Quick but hacky answer for your case, select target layer as:<br>
<code>model[0][0][-1]</code></p>
<p>Alternate answer:<br>
This way of initializing the model is not good. Have a look over here regarding how to add extra layers to your model:</p><aside class="quote quote-modified" data-post="2" data-topic="88397">
  <div class="title">
    <div class="quote-controls"></div>
    <img loading="lazy" alt="" width="24" height="24" src="https://discuss.pytorch.org/user_avatar/discuss.pytorch.org/nikronic/48/71873_2.png" class="avatar">
    <a href="https://discuss.pytorch.org/t/load-only-a-part-of-the-network-with-pretrained-weights/88397/2">Load only a part of the network with pretrained weights</a> 
  </div>
  <blockquote>
    Hi, 
For this, there are different approaches but personally, I would create a class on top of previously defined model which you have weights for. Then add any other layers as another sequential to the new defined model. Something like this: 
pretrained = torchvision.models.alexnet(pretrained=True)
class MyAlexNet(nn.Module):
    def __init__(self, my_pretrained_model):
        super(MyAlexNet, self).__init__()
        self.pretrained = my_pretrained_model
        self.my_new_layers = nn.Sequen…
  </blockquote>
</aside>

<p>Regarding gradcam, you need to define your target layer. For that, you can check what is the target layer for Vgg:</p>
<pre><code class="lang-auto">vgg.features[-1]
MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)
</code></pre>
<p>So, in your new model, it should refer to this layer as well. For getting that layer just try to print your custom model and try to find the layer</p>

Surpuissant: <p>Thank you very much for your useful answer</p>