# Layer shape computation in convolutional neural net (pyTorch)

How can you know the expected input size (image input size (tensor size)), for example for this network (cf. pyTorch tutorial example ):

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

class Net(nn.Module):

def __init__(self):
super(Net, self).__init__()
# 1 input image channel, 6 output channels, 3x3 square convolution
# kernel
self.conv1 = nn.Conv2d(1, 6, 3)
self.conv2 = nn.Conv2d(6, 16, 3)
# an affine operation: y = Wx + b
self.fc1 = nn.Linear(16 * 6 * 6, 120)  # 6*6 from image dimension
self.fc2 = nn.Linear(120, 84)
self.fc3 = nn.Linear(84, 10)

def forward(self, x):
# Max pooling over a (2, 2) window
x = F.max_pool2d(F.relu(self.conv1(x)), (2, 2))
# If the size is a square you can only specify a single number
x = F.max_pool2d(F.relu(self.conv2(x)), 2)
x = x.view(-1, self.num_flat_features(x))
x = F.relu(self.fc1(x))
x = F.relu(self.fc2(x))
x = self.fc3(x)
return x

def num_flat_features(self, x):
size = x.size()[1:]  # all dimensions except the batch dimension
num_features = 1
for s in size:
num_features *= s
return num_features

net = Net()
print(net)


Since it is nowhere explicitely stated. Moreover the comment

self.fc1 = nn.Linear(16 * 6 * 6, 120)  # 6*6 from image dimension


is unclear. What does this shape: (16 * 6 * 6, 120) have to do with image size (e.g. 32x32 as claimed by the authors of the tutorial) ? I cannot find a way, by looking at the code, to know what input size is expected by the net?

Well, with conv layers in pyTorch, you don't need to specify the input size except the number of channels/depth. However, you need to specify it for fully connected layers. So, when defining the input dimension of the first linear layer, you have to know what is the size of the images you feed.

You can find information on the output size calculation of conv layers and pooling layers here and here or here

If you feed images of size 32x32, the outputs layer by layer of this model are :

• conv1 : $$6$$ feature maps of size $$\left \lfloor{\frac{32 + 2\times0 -1\times(3-1)-1}{1}+1}\right \rfloor = 30$$
• max_pool2d: $$6$$ feature maps of size $$\left \lfloor{\frac{30 + 2\times0 -1\times(2-1)-1}{2}+1}\right \rfloor = 15$$
• conv2 : $$16$$ feature maps of size $$\left \lfloor{\frac{15+ 2\times0 -1\times(3-1)-1}{1}+1}\right \rfloor = 13$$
• max_pool2d: $$16$$ feature maps of size $$\left \lfloor{\frac{13+ 2\times0 -1\times(2-1)-1}{2}+1}\right \rfloor = 6$$

Therefore, for the flattened size of the output before the first linear layer is $$16\times6\times6$$ :

 self.fc1 = nn.Linear(16 * 6 * 6, 120)


By doing all sizes calculations in reverse, you could have find that the input size must be $$32\times32$$.

• Quite clearly explained, thanks. You should suggest your explanationsto pyTorch, so they could add it to their tutorial. Commented Aug 30, 2019 at 13:24
• Please one more comment to clarify: for the first conv layer (conv1) we have the shape (1,6,3) meaning 6 kernels of size 3x3 and of 1 channel, the latter being 1 because we use grayscale 32x32 images in this example, right? And the formula you used for conv1 activation map size is: ((W-F+2P)/S)+1, where W(and H since we use square images) are images's width/height, F is kernel size (always square) P is padding (0 in our case i think?), stride S =1 in this case. So ((32-3+2*0)/1)+1=30 but i dont see why you have some other computations like (3-1)-1 ? Is it not the same formula you used? Commented Aug 30, 2019 at 13:45
• Exactly for the grayscale channel. For the formula, I use the one with dilated convolution (you can see towardsdatascience.com/… and ) so the formula is lightly different (see pyTorch links in the answer). However dilatation here is equal to 1 (equivalent to classic convolution operation) so you can use the classic formula and your calculation is therefore entirely correct :). Commented Aug 30, 2019 at 13:58
• oh, great, again you are a very good teacher man! Commented Aug 30, 2019 at 14:05