Gradients of model output layer and intermediate layer wrt inputs

username: kvenkatesh5
cooked: <p>I’m trying to visualize model layer outputs using the <a href="https://github.com/PAIR-code/saliency" rel="noopener nofollow ugc">saliency core package</a> package on a simple conv net. This requires me to compute the gradients of the model output layer and intermediate convolutional layer output w.r.t the input. I’ve attempted to do this in the last code block, but I run into the error <code>RuntimeError: grad can be implicitly created only for scalar outputs</code>. How do I retrieve these gradients and what is this error telling me?</p>
<pre><code class="lang-auto">import torch
import torch.nn as nn
import torchvision
from torchvision import datasets, transforms
from torch.utils.data import DataLoader
import numpy as np
from tqdm.notebook import tqdm
device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
from google.colab import drive
drive.mount('/content/drive')
root = '/content/drive/MyDrive/Work/ExplainMNIST'
import os
# !pip install saliency
import saliency.core as saliency

# Hyperparameters
batch_size = 32
num_classes = 10

data_dir = os.path.join(root, "data")
mnist_train = torchvision.datasets.MNIST(data_dir, train=True, transform=transforms.Compose([
    transforms.ToTensor(),
    transforms.Normalize((0.1307,), (0.3081))
]), download=True)
mnist_test = torchvision.datasets.MNIST(data_dir, train=False, transform=transforms.Compose([
    transforms.ToTensor(),
    transforms.Normalize((0.1307,), (0.3081))
]), download=True)
train_loader = DataLoader(mnist_train, batch_size=batch_size, shuffle=True)
test_loader = DataLoader(mnist_test, batch_size=batch_size, shuffle=True)
checkpoint_dir = os.path.join(root, 'checkpoints')
if not os.path.exists(checkpoint_dir):
    os.makedirs(checkpoint_dir)

images_, labels_ = next(iter(train_loader))
images_ = images_.to(device)
labels_ = labels_.to(device)

class ConvNet(nn.Module):
    def __init__(self, in_channels, num_classes):
        super(ConvNet, self).__init__()
        self.conv1 = nn.Conv2d(in_channels=in_channels, out_channels=10, kernel_size=3)
        self.pool1 = nn.MaxPool2d(3)
        self.conv2 = nn.Conv2d(in_channels=10, out_channels=10, kernel_size=3)
        self.activation = nn.ReLU()
        self.fc = nn.Linear(360, num_classes)
    def forward(self, x):
        x = self.conv1(x)
        x = self.pool1(x)
        x = self.activation(x)
        x = self.conv2(x)
        x = self.activation(x)
        conv = x
        x = self.fc(x.reshape(x.shape[0], -1))
        return {'output': x, 'conv': conv}

model = ConvNet(1, num_classes)
model = model.to(device)
model.eval()

#HELP! here is my attempt
with torch.set_grad_enabled(True):
    output, conv = model(images_).values()
    output_class = output[:, 0]
# Here is how i tried to do it
    grads = torch.autograd.grad(output, images_)
    grads2 = torch.autograd.grad(conv, images_)
</code></pre>

username: mhnazeri
cooked: <p>Hi<br>
You can use hooks to access intermediate activations. Here is a snippet borrowed from this forum:</p>
<pre><code class="lang-python">class MyModel(nn.Module):
    def __init__(self):
        super(MyModel, self).__init__()
        self.cl1 = nn.Linear(25, 60)
        self.cl2 = nn.Linear(60, 16)
        self.fc1 = nn.Linear(16, 120)
        self.fc2 = nn.Linear(120, 84)
        self.fc3 = nn.Linear(84, 10)
        
    def forward(self, x):
        x = F.relu(self.cl1(x))
        x = F.relu(self.cl2(x))
        x = F.relu(self.fc1(x))
        x = F.relu(self.fc2(x))
        x = F.log_softmax(self.fc3(x), dim=1)
        return x


activation = {}
def get_activation(name):
    def hook(model, input, output):
        activation[name] = output.detach()
    return hook


model = MyModel()
model.fc2.register_forward_hook(get_activation('fc2'))
x = torch.randn(1, 25)
output = model(x)
print(activation['fc2'])
</code></pre>

username: kvenkatesh5
cooked: <p>thank you so much, <a class="mention" href="/u/mhnazeri">@mhnazeri</a> <img src="https://discuss.pytorch.org/images/emoji/apple/slight_smile.png?v=9" title=":slight_smile:" class="emoji" alt=":slight_smile:"></p>