Extraction of layer-> getting error

Hello Everyone,

Here is the model:

‘’’
class Net(nn.Module):
def init(self):
super().init()
self.conv1 = nn.Conv2d(in_channels=3, out_channels=6, kernel_size= 5)
self.pool = nn.MaxPool2d(kernel_size=2,stride= 2)
self.conv2 = nn.Conv2d(in_channels=6, out_channels=16, kernel_size= 5)
self.fc1 = nn.Linear(in_features=400, out_features=120)
self.fc2 = nn.Linear(in_features=120, out_features=84)
self.fc3 = nn.Linear(in_features=84, out_features=10)

def forward(self, x):
    con_1_output = self.pool(F.relu(self.conv1(x)))
    con_2_output = self.pool(F.relu(self.conv2(con_1_output))) #([4, 16, 5, 5])
    flatten_values = torch.flatten(con_2_output, 1) # flatten all dimensions except batch [batch_size, in_features] [4, 400]
    fc1_output = F.relu(self.fc1(flatten_values)) # output x.shape = [4, 120]
    fc2_output = F.relu(self.fc2(fc1_output))
    fc3_output = self.fc3(fc2_output)
    return fc3_output

‘’’
I am creating a new model to extract the feature vector of the FC1

new_model = nn.Sequential(*list(save_net.children())[:-2])
Output is:

‘’’
Sequential(
(0): Conv2d(3, 6, kernel_size=(5, 5), stride=(1, 1))
(1): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)
(2): Conv2d(6, 16, kernel_size=(5, 5), stride=(1, 1))
(3): Linear(in_features=400, out_features=120, bias=True)
)

‘’’
Problem: When I am passing the test image in the new model I am getting an error:
‘’’
RuntimeError: mat1 and mat2 shapes cannot be multiplied (640x10 and 400x120)
‘’’

The problem is the tensor dimension inside the forward pass (look at the comments)

  def forward(self, x):
    # x shape: [1, 3, 224, 224]
    x = self.pool(F.relu(self.conv1(x))) # output shape: [1, 6, 110, 110]
    x = self.pool(F.relu(self.conv2(x))) # output shape: [1, 16, 53, 53]
    x = torch.flatten(x, 1) # output shape: [1, 44944]
    x = F.relu(self.fc1(x))  
    ...

You get the error even if you make inference with a random tensor.

model = Net()
t = torch.randn(1, 3, 224, 224)

model(t)
RuntimeError                              Traceback (most recent call last)
<ipython-input-71-22d29d5af2a4> in <module>()
----> 1 net(t)

3 frames
/usr/local/lib/python3.7/dist-packages/torch/nn/modules/linear.py in forward(self, input)
    101 
    102     def forward(self, input: Tensor) -> Tensor:
--> 103         return F.linear(input, self.weight, self.bias)
    104 
    105     def extra_repr(self) -> str:

RuntimeError: mat1 and mat2 shapes cannot be multiplied (1x44944 and 400x120)

As you can see, the expected input size is (batch_size, 400), but you’re feeding the layer with a tensor of shape (batch_size, 44944).

You should definitely consider to use a AdaptiveAvgPool2d layer after the flatten operation.

My input size is t = torch.randn(1, 3, 32, 32) not torch.randn(1, 3, 224, 224)

The children method returns only nn.Module, so you skipping the functional flatten in the forward pass, which is needed to prepare the output for the linear layer.

A fast refactoring could be the following:

import torch
import torch.nn as nn
import torch.nn.functional as F

class Net(nn.Module):
  def __init__(self):
    super().__init__()
    self.layers = nn.Sequential(
        nn.Conv2d(in_channels=3, out_channels=6, kernel_size= 5),
        nn.MaxPool2d(kernel_size=2,stride= 2),
        nn.Conv2d(in_channels=6, out_channels=16, kernel_size= 5),
        nn.Flatten(start_dim=1),
        nn.Linear(16 * 10 * 10, 120),
        nn.Linear(120, 84),
        nn.Linear(84, 10)
    )

  def forward(self, x):
    return self.layers(x)

Note that I had to modify the in_features of the first linear layer to fit the right dimension.

model = Net()
x = torch.randn(1, 3, 32, 32)

print(model.layers[:-2](x).shape)

>>> torch.Size([1, 120])

I have used forward hooks to extract the features and for fc1 I am getting this output (1, 4, 84). I don’t think this is right output value of fc1 layer?