Get the activations of the second to last layer

smu226: <p>Hello! I have this piece of code:</p>
<pre><code class="lang-auto">class View(nn.Module):
    def __init__(self, size):
        super(View, self).__init__()
        self.size = size

    def forward(self, tensor):
        return tensor.view(self.size)

class Encoder(nn.Module):
    def __init__(self):
        super().__init__()
        
        N = 32
        
        self.encoder = nn.Sequential(
            nn.Conv2d(3, N, 4, 2, 1),          
            nn.ReLU(True),
            nn.Conv2d(N, N, 4, 2, 1),          
            nn.ReLU(True),
            nn.Conv2d(N, 2*N, 4, 2, 1),          
            nn.ReLU(True),
            nn.Conv2d(2*N, 2*N, 4, 2, 1),         
            nn.ReLU(True),
            nn.Conv2d(2*N, 8*N, 4, 1),          
            nn.ReLU(True),
            View((-1, 8*N*1*1)),                
            nn.Linear(8*N, 2),            
        )
            
    def forward(self, x):
        z = self.encoder(x)
        return z
</code></pre>
<p>I take 64x64 images and return 2 numbers. I trained it to do what I need and it works well, but I would like now (for some other reason) to get the activations before the output i.e. the result of that flattening layer. So I would need the values of the 8*N dimensional vector, before the last matrix multiplication. How can I do this? Thank you!</p>

spanev: <p>Hi <a class="mention" href="/u/smu226">@smu226</a>,</p>
<p>You should be able to do it with <a href="https://pytorch.org/docs/stable/nn.html#torch.nn.Module.register_forward_hook" rel="nofollow noopener">hooks</a>:</p>
<pre><code class="lang-auto">global view_output
def hook_fn(module, input, output):
    global view_output
    view_output = output
net = Encoder()
hook = net.encoder[-2].register_forward_hook(hook_fn)
# call hook.remove() to remove
</code></pre>
<p>so after each forward pass you will find View’s output in <code>view_output</code>.</p>
<p>Hope that helps!</p>

smu226: <p>Thank you so much for this, it looks like what I need. But how do I actually use it. I tried:</p>
<pre><code class="lang-auto">net(x)
print(view_output)
</code></pre>
<p>but I still get None.</p>

spanev: <p>Oops, please look at my edit, it should work better <img src="https://discuss.pytorch.org/images/emoji/apple/slightly_smiling_face.png?v=12" title=":slightly_smiling_face:" class="emoji" alt=":slightly_smiling_face:" loading="lazy" width="20" height="20"></p>
<aside class="quote no-group" data-username="spanev" data-post="2" data-topic="55629">
<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/spanev/48/14892_2.png" class="avatar"> spanev:</div>
<blockquote>
<p>global view_output def hook_fn(module, input, output): global view_output</p>
</blockquote>
</aside>

DoubtWang: <p>u get the 8*N dimensional vector successfully ?<br>
Does u complete it by using the hook.remove() ?</p>

spanev: <p>I just ran the code with batch size of 1 and N=32:</p>
<pre><code class="lang-auto">&gt;&gt;&gt; view_output.shape
torch.Size([1, 256])
</code></pre>
<p>so it looks good.</p>
<p><code>hook.remove()</code> is in case you don’t want to use the hook run anymore.</p>

Aryan_Asadian: <p>Hi. I tried your solution. It seems that it works for a net with single module, i.e., a model with a single Sequential block. How can we register a hook for children of a module in a mutli-module net, e.g., ResNet?</p>

spanev: <p>Hi <a class="mention" href="/u/aryan_asadian">@Aryan_Asadian</a>,</p>
<p>Let’s assume that you have <code>models.resnet50</code> from <code>torchvision</code>.</p>
<pre><code class="lang-auto">my_resnet = models.resnet50(pretrained=True)
</code></pre>
<p>If you want to register the hook on the first on the conv2 of the very first bottleneck block you will write:</p>
<pre><code class="lang-auto">my_resnet.layer1[0].conv2.register_forward_hook(hook_fn)
</code></pre>
<p>As you can see, modules are called by name/id and Sequential blocks element by index.<br>
To find what are the names of the submodules you can print the model.</p>
<p>I hope that I understood correctly what you mean by muti-model net.</p>

Aryan_Asadian: <p>That’s right. But if we define a new sequential module with the OrderDict, this method is not working, i.e. the sub-layers in our newly defined sequential are not accessible neither by their indices nor by their defined OrderDict keys.</p>