PyTorch > nn.Conv2d:computation of number of features output from nn.Conv2d

mohassan99: <p>I have x = nn.linear() following x=conv2d()</p>
<p>I understand in_features of linear() must be calculated from x. by calculating channels * height * width of x.</p>
<p>I know from, the documentation for conv2d, this stuff I dont get:</p>
<p><div class="lightbox-wrapper"><a class="lightbox" href="https://discuss.pytorch.org/uploads/default/original/3X/f/2/f2a28e5dfc760b515766beae26f9da573ce80760.png" data-download-href="https://discuss.pytorch.org/uploads/default/f2a28e5dfc760b515766beae26f9da573ce80760" title="image"><img src="https://discuss.pytorch.org/uploads/default/original/3X/f/2/f2a28e5dfc760b515766beae26f9da573ce80760.png" alt="image" data-base62-sha1="yCrP0AjjLBOCSjA2LDShiL6M4q4" width="690" height="246" data-dominant-color="F6F6F7"><div class="meta"><svg class="fa d-icon d-icon-far-image svg-icon" aria-hidden="true"><use href="#far-image"></use></svg><span class="filename">image</span><span class="informations">701×250 17 KB</span><svg class="fa d-icon d-icon-discourse-expand svg-icon" aria-hidden="true"><use href="#discourse-expand"></use></svg></div></a></div></p>
<p>I dont follow <a href="https://stackoverflow.com/questions/66121934/pytorch-nn-conv2d-output-comptation" rel="noopener nofollow ugc">this post on</a> nn.Conv2d output comptation), but it says you can get dimensions of x with x.shape.</p>
<p>I still dont understand how to apply those equations from the documentation of nn.conv.</p>
<p>I know:</p>
<ol>
<li>The input features are the pixel size (i.e.: h*w) of the image * channels and</li>
<li>pixel size (H*W) of your image after applying Conv2d comes from the above equations, but I dont understand it. Are we just defining notation in the input: and output: parts?</li>
</ol>
<p>Then it gives formulas for H_out and W_out, the height and width of the image output from conv2d based on H_in and W_in, the height and width of image input to conv2D, respectively. I don’t understand how to apply those equations.</p>
<ol>
<li>how do I get H_in and W_in?   Would those be x[2] and x[3] based on the assumptions that what comes after input: and ouput: are the dimensions of x. I.e.: N and the number of channels are the first two dimensions.</li>
</ol>
<p>Assuming:</p>
<ul>
<li>we are using x as it is after the line just before linear() and</li>
<li>input and output above show conv2D’s input and output orders of dimensions and the notation for the equations.</li>
</ul>
<ol start="2">
<li>Are padding, dilation, and kernel_size taken from the parameters values of the preceding conv2D call?  If the preceding call is:<br>
<code>self.conv2 = nn.Conv2d(6, 16, 5) </code><br>
This means:   <code>self.conv2 = nn.Conv2d(in_channels = 6, out_channels = 16, kernel_size = 5)</code> kernel size is 5, what is kernel_size[0] and where to I get padding and dilation?</li>
</ol>
<p>Then, say we have a call to nn.Linear afterward. It’s in_features parameter would be C * H_{out} * W_{out}, where:<br>
C = the out_channels parameter used in the prior conv2D call?</p>
<p>The current sad state of the code:</p>
<pre><code class="lang-auto">class Net(nn.Module):
    def __init__(self):
        super().__init__()
        # Conv2d(in_channels, out_channels, kernel_size, stride=1, padding=0, dilation=1, groups=1, bias=True, padding_mode='zeros', device=None, dtype=None)
        self.conv1 = nn.Conv2d(in_channels = 1, out_channels = 6, kernel_size = 5)
        
        self.conv2 = nn.Conv2d(in_channels = 6, out_channels = 16, kernel_size = 5)
       
        self.pool = nn.MaxPool2d(2, 2)
# To decide the number of input features your function can take, you first need to figure out what is the output pixel value of your final conv2d. 
# Let's say your final conv2d function returns a 3x3 pixel image with output channels as 50, in such case the input features to your linear function should be 3x3x50 
# and you can have any number of output features.
        
        #calculate H &amp; W of self.conv2 output from 
        #I GOT STUCK HERE. I WENT TO TUESDAY OFFICE HOURS 5 MIN LATE AND NO ONE WAS THERE
        #I DIDN'T GET AN ANSWER TO MY POST #1032 ABOUT POST #815
#         print(self.conv2.shape)
#       It seems self.conv2 has no shape attribute.
#         H_in = 
#         H = 
#         W =
        #Linear(in_features, out_features, bias=True, device=None, dtype=None)
        #self.fc1 = nn.Linear(16 * 5 * 5, 120)
        self.fc1 = nn.Linear(16 * H * W, 120)
        self.fc2 = nn.Linear(120, 84)
        self.fc3 = nn.Linear(84, 10)

    def forward(self, x):
        x = self.pool(F.relu(self.conv1(x)))
        x = self.pool(F.relu(self.conv2(x)))
        x = torch.flatten(x, 1) # flatten all dimensions except batch
        x = F.relu(self.fc1(x)) #relu is an activation function
        x = F.relu(self.fc2(x))
        x = self.fc3(x)
        return x
net = Net()
</code></pre>

ptrblck: <aside class="quote no-group" data-username="mohassan99" data-post="1" data-topic="150750">
<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/mohassan99/48/49201_2.png" class="avatar"> mohassan99:</div>
<blockquote>
<p>how do I get H_in and W_in? Would those be x[2] and x[3] based on the assumptions that what comes after input: and ouput: are the dimensions of x. I.e.: N and the number of channels are the first two dimensions.</p>
</blockquote>
</aside>
<p>Yes, the spatial dimensions (height and width) defined in dim2 and dim3, respectively for the expected 4-dimensional input in the shape <code>[batch_size, channels, height, width]</code>.</p>
<aside class="quote no-group" data-username="mohassan99" data-post="1" data-topic="150750">
<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/mohassan99/48/49201_2.png" class="avatar"> mohassan99:</div>
<blockquote>
<p>Are padding, dilation, and kernel_size taken from the parameters values of the preceding conv2D call?</p>
</blockquote>
</aside>
<p>Yes</p>
<aside class="quote no-group" data-username="mohassan99" data-post="1" data-topic="150750">
<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/mohassan99/48/49201_2.png" class="avatar"> mohassan99:</div>
<blockquote>
<p>If the preceding call is:<br>
<code>self.conv2 = nn.Conv2d(6, 16, 5) </code><br>
This means: <code>self.conv2 = nn.Conv2d(in_channels = 6, out_channels = 16, kernel_size = 5)</code> kernel size is 5, what is kernel_size[0]</p>
</blockquote>
</aside>
<p>If you specify the <code>kernel_size</code> with a single <code>int</code>, the height and width of the kernel will be set to this value. <code>kernel_size[0]</code> and also <code>kernel_size[1]</code> will have a value of 5. The <a href="https://pytorch.org/docs/stable/generated/torch.nn.Conv2d.html">docs</a> also explain this behavior.</p>
<aside class="quote no-group" data-username="mohassan99" data-post="1" data-topic="150750">
<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/mohassan99/48/49201_2.png" class="avatar"> mohassan99:</div>
<blockquote>
<p>and where to I get padding and dilation?</p>
</blockquote>
</aside>
<p>If you don’t specify these values explicitly, the default values will be used also as given in the docs.</p>
<aside class="quote no-group" data-username="mohassan99" data-post="1" data-topic="150750">
<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/mohassan99/48/49201_2.png" class="avatar"> mohassan99:</div>
<blockquote>
<p>Then, say we have a call to nn.Linear afterward. It’s in_features parameter would be C * H_{out} * W_{out}, where:<br>
C = the out_channels parameter used in the prior conv2D call?</p>
</blockquote>
</aside>
<p>Yes, that’s correct.</p>

mohassan99: <p>Thank you!</p>
<p>In<br>
<code>def __init__(self):</code> I have …</p>
<pre><code class="lang-auto">        self.conv2 = nn.Conv2d(in_channels = 6, out_channels = 16, kernel_size = 5)
        self.pool = nn.MaxPool2d(2, 2)
        self.fc1 = nn.Linear(16 * 5 * 5, 120)
</code></pre>
<p>This last line above is nn.Linear(16 * h * w, 120) and I need h &amp; w?<br>
, but self.conv2.shape doesn’t exist so self.conv2[2] doesn’t give me the height of an image.<br>
If I add<br>
<code>print(self.conv2.shape)</code> I get:<br>
<code>'Conv2d' object has no attribute 'shape'</code></p>

Matias_Vasquez: <p>For your parameters (since you are not giving values for padding, stride and dilation the default are used) the equation would look like this</p>
<p><img src="https://discuss.pytorch.org/uploads/default/original/3X/f/e/fee553cce9e14c5152cfc1cf58a2406557513ffb.png" alt="image" data-base62-sha1="AmUBLfqk3MLZs4cBCb2LnBCkdmj" width="578" height="330"></p>
<p>If you want to use this approach instead of solving the equation</p>
<aside class="quote no-group" data-username="mohassan99" data-post="3" data-topic="150750">
<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/mohassan99/48/49201_2.png" class="avatar"> mohassan99:</div>
<blockquote>
<p><code>print(self.conv2.shape)</code> I get:<br>
<code>'Conv2d' object has no attribute 'shape'</code></p>
</blockquote>
</aside>
<p>Then you need to pass something through the <code>conv</code> to see what is happening.</p>
<pre data-code-wrap="python"><code class="lang-python"># Example
conv2 = torch.nn.Conv2d(in_channels = 6, out_channels = 16, kernel_size = 5)
img = torch.rand(1, 6, 50, 50)

print(conv2(img).shape)

# Output:
# torch.Size([1, 16, 46, 46])
</code></pre>
<p>Which is the same result that we got from the formula.</p>

ptrblck: <p>As <a class="mention" href="/u/matias_vasquez">@Matias_Vasquez</a> described you could either calculate the activation shape manually or pass an input to the model to print the actual shape.<br>
E.g. in your model you would most likely have a few conv, pool, etc. layers before the first linear layer is used.<br>
If you don’t want to calculate the <code>in_features</code>, set this argument to any random value (e.g. <code>1</code>), pass the input tensor to the model, and print the activation shape before passing it to the linear layer:</p>
<pre><code class="lang-python">x = self.conv(x)
x = x.view(x.size(0), -1)
print(x.shape)
x = self.fc(x) # will raise a shape mismatch here
</code></pre>
<p>Then use the printed shape of dim1 to set the <code>in_features</code>.<br>
Alternatively, you could also use the lazy layers e.g. via <code>nn.LazyLinear</code> to let this layer calculate the <code>in_features</code> for you.</p>

mohassan99: <p>I was trying to print the shape of conv2 object to see how I can get H_in.</p>
<aside class="quote no-group" data-username="Matias_Vasquez" data-post="18" data-topic="150750">
<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/matias_vasquez/48/47847_2.png" class="avatar"> Matias_Vasquez:</div>
<blockquote>
<p><code>print(x.shape)</code></p>
</blockquote>
</aside>
<p>Are you saying I should literally copy/paste that somewhere in my existing code? In the construction of the net class? I’m not sure how or where to incorporate this into my existing code.</p>

ptrblck: <p>This isn’t possible as the conv layer can work on a variable input shape as long as the spatial shape of the input is large enough for the current conv setup.<br>
The output shape thus depends on the input shape <em>and</em> the conv setup. The conv layer alone will not define the output shape.</p>

mohassan99: <aside class="quote no-group" data-username="mohassan99" data-post="1" data-topic="150750">
<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/mohassan99/48/49201_2.png" class="avatar"> mohassan99:</div>
<blockquote>
<p><code>self.fc1 = nn.Linear(16 * 5 * 5, 120)</code></p>
</blockquote>
</aside>
<p>Sorry guys I’m so lost. I dont really understand this stuff and was coasting despite that by asking questions and getting the coding. Nothing about NN made sense to me.</p>
<p>In the code in my question, this line gives me a matrix multiplication error:<br>
self.fc1 = nn.Linear(16 * 5 * 5, 120).<br>
I’m told the first parameter is wrong, but can be calculated.<br>
The calculation include h_in, which I dont know how to get.<br>
What’s the easy way to get an in_features that will run?</p>

mohassan99: <aside class="quote no-group" data-username="ptrblck" data-post="5" data-topic="150750">
<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/ptrblck/48/1823_2.png" class="avatar"> ptrblck:</div>
<blockquote>
<p><code>nn.LazyLinear</code></p>
</blockquote>
</aside>
<p>Like this?<br>
<code>self.fc1 = nn.Linear(nn.LazyLinear, 120)</code></p>
<p><code>module 'torch.nn' has no attribute 'LazyLinear'</code></p>

ptrblck: <aside class="quote no-group" data-username="mohassan99" data-post="8" data-topic="150750">
<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/mohassan99/48/49201_2.png" class="avatar"> mohassan99:</div>
<blockquote>
<p>I’m told the first parameter is wrong, but can be calculated.<br>
The calculation include h_in, which I dont know how to get.<br>
What’s the easy way to get an in_features that will run?</p>
</blockquote>
</aside>
<p>See my previous post with a code snippet which shows how to print the activation shape.</p>
<aside class="quote no-group" data-username="mohassan99" data-post="9" data-topic="150750">
<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/mohassan99/48/49201_2.png" class="avatar"> mohassan99:</div>
<blockquote>
<p>Like this?<br>
<code>self.fc1 = nn.Linear(nn.LazyLinear, 120)</code></p>
</blockquote>
</aside>
<p>No, <a href="https://pytorch.org/docs/stable/generated/torch.nn.LazyLinear.html#torch.nn.LazyLinear"><code>nn.LazyLinear</code></a> is a layer, not an argument of `nn.Linear.</p>
<pre data-code-wrap="python"><code class="lang-python">self.fc1 = nn.LazyLinear(120)
</code></pre>
<p>should work.</p>

mohassan99: <aside class="quote no-group" data-username="ptrblck" data-post="10" data-topic="150750">
<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/ptrblck/48/1823_2.png" class="avatar"> ptrblck:</div>
<blockquote>
<p><code>self.fc1 = nn.LazyLinear(120)</code></p>
</blockquote>
</aside>
<p><code>self.fc1 = nn.LazyLinear(120)</code><br>
<code>module 'torch.nn' has no attribute 'LazyLinear'</code></p>

ptrblck: <p>You might need to update your PyTorch version to be able to use this layer, as your version seems to be too old.</p>

mohassan99: <aside class="quote no-group" data-username="ptrblck" data-post="5" data-topic="150750">
<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/ptrblck/48/1823_2.png" class="avatar"> ptrblck:</div>
<blockquote>
<pre><code class="lang-auto">x = self.conv(x)
x = x.view(x.size(0), -1)
print(x.shape)
x = self.fc(x) # will raise a shape mismatch here
</code></pre>
</blockquote>
</aside>
<p>This code is all going inside</p>
<p><code>class Net(nn.Module):</code><br>
with a</p>
<pre><code class="lang-auto">def __init__(self):
        super().__init__()
</code></pre>
<p>part and a<br>
<code>def forward(self, x):</code><br>
part.</p>
<p>I had this in the constructor(?), <code>def __init__(self):</code> part:</p>
<pre><code class="lang-auto">self.conv2 = nn.Conv2d(in_channels = 6, out_channels = 16, kernel_size = 5)
self.pool = nn.MaxPool2d(2, 2)
self.fc1 = nn.Linear(16 * 5 * 5, 120)
</code></pre>
<p>You are suggesting I modify</p>
<pre><code class="lang-auto">x = self.conv(x)
x = x.view(x.size(0), -1)
print(x.shape)
x = self.fc(x) # will raise a shape mismatch here
</code></pre>
<p>to work in this context.</p>
<p>It almost looks like your syntax is different. How does the code in the model/class definition correspond to your code?  The class has</p>
<p>self.someName = someFunction(someParameters)<br>
self.someName1 = someFunction1(someParameters1)</p>
<p>Your code looks like<br>
x = self.someName(x)<br>
x = self.someName1(x)</p>
<p>I dont know how to translate between them.</p>
<p>I’m just trying to adapt the code in<br>
<a href="https://pytorch.org/tutorials/beginner/blitz/cifar10_tutorial.html#define-a-convolutional-neural-network" class="onebox" target="_blank" rel="noopener nofollow ugc">https://pytorch.org/tutorials/beginner/blitz/cifar10_tutorial.html#define-a-convolutional-neural-network</a><br>
to work with MNIST input which is just one channel greyscale instead of 3 like CIFAR10.</p>

ptrblck: <p>My code should be used in the <code>forward</code> method, not the <code>__init__</code>.<br>
As you can see in the tutorial, the <code>__ini__</code> initializes the modules, while the <code>forward</code> uses them.</p>

mohassan99: <aside class="quote no-group" data-username="ptrblck" data-post="12" data-topic="150750" data-full="true">
<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/ptrblck/48/1823_2.png" class="avatar"> ptrblck:</div>
<blockquote>
<p>You might need to update your PyTorch version to be able to use this layer, as your version seems to be too old.</p>
</blockquote>
</aside>
<p>I dont know how or if that’s possible or allowed:<br>
I have these imports:</p>
<pre><code class="lang-auto">%matplotlib inline

import torch
import torchvision
import torchvision.transforms as transforms

import matplotlib.pyplot as plt
import numpy as np

import torch.nn as nn
import torch.nn.functional as F
import torch.optim as optim
import random
import numpy as np

import os
</code></pre>
<p>I have the constructor:</p>
<pre><code class="lang-auto">    def __init__(self):
        super().__init__()
        self.conv1 = nn.Conv2d(1, 6, 5)
        self.pool = nn.MaxPool2d(2, 2)
        self.conv2 = nn.Conv2d(6, 16, 5)
        self.fc1 = nn.Linear(16 * 5 * 5, 120)
        self.fc2 = nn.Linear(120, 84)
        self.fc3 = nn.Linear(84, 10)
</code></pre>
<p>I’m getting a matrix multiplication error because<br>
self.fc1 = nn.Linear(16 * 5 * 5, 120) has the wrong number of input features.<br>
How do I find the number of input features using these H_out, H_in equations or otherwise work around the error? Dont I need to replace “16 * 5 * 5” with something?</p>
<p>The full model definitions is:</p>
<pre><code class="lang-auto">class Net(nn.Module):
    def __init__(self):
        super().__init__()
        self.conv1 = nn.Conv2d(3, 6, 5)
        self.pool = nn.MaxPool2d(2, 2)
        self.conv2 = nn.Conv2d(6, 16, 5)
        self.fc1 = nn.Linear(16 * 5 * 5, 120)
        self.fc2 = nn.Linear(120, 84)
        self.fc3 = nn.Linear(84, 10)

    def forward(self, x):
        x = self.pool(F.relu(self.conv1(x)))
        x = self.pool(F.relu(self.conv2(x)))
        x = torch.flatten(x, 1) # flatten all dimensions except batch
        x = F.relu(self.fc1(x)) #relu is an activation function
        x = F.relu(self.fc2(x))
        x = self.fc3(x)
        return x
    
net = Net()
</code></pre>
<p>In this context, could I and how would I apply your suggestion to:</p>
<aside class="quote no-group" data-username="ptrblck" data-post="5" data-topic="150750">
<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/ptrblck/48/1823_2.png" class="avatar"> ptrblck:</div>
<blockquote>
<p>pass an input to the model to print the actual shape.<br>
E.g. in your model you would most likely have a few conv, pool, etc. layers before the first linear layer is used.<br>
If you don’t want to calculate the <code>in_features</code>, set this argument to any random value (e.g. <code>1</code>), pass the input tensor to the model, and print the activation shape before passing it to the linear layer:</p>
<pre><code class="lang-auto">x = self.conv(x)
x = x.view(x.size(0), -1)
print(x.shape)
x = self.fc(x) # will raise a shape mismatch here
</code></pre>
<p>Then use the printed shape of dim1 to set the <code>in_features</code>.<br>
Alternatively, you could also use the lazy layers e.g. via <code>nn.LazyLinear</code> to let this layer calculate the <code>in_features</code> for you.</p>
</blockquote>
</aside>

mohassan99: <p>I dont see how you get the result from the equations. You are still missing H_in. How do I get that when I have:</p>
<pre><code class="lang-auto">class Net(nn.Module):
    def __init__(self):
        super().__init__()
        #self.conv1 = nn.Conv2d(3, 6, 5)
        self.conv1 = nn.Conv2d(1, 6, 5)
        self.pool = nn.MaxPool2d(2, 2)
        self.conv2 = nn.Conv2d(6, 16, 5)
        self.fc1 = nn.Linear(16 * 5 * 5, 120)
        self.fc2 = nn.Linear(120, 84)
        self.fc3 = nn.Linear(84, 10)

    def forward(self, x):
        x = self.pool(F.relu(self.conv1(x)))
        x = self.pool(F.relu(self.conv2(x)))
        x = torch.flatten(x, 1) # flatten all dimensions except batch
        x = F.relu(self.fc1(x)) #relu is an activation function
        x = F.relu(self.fc2(x))
        x = self.fc3(x)
        return x
    
net = Net()
</code></pre>
<p>As you know, I am seeing a shape mismatch error in the first linear layer, a matrix multiplication error of (a x b) @ (c x d), but b != c.</p>
<p>I don’t see where or how to get height_in and width_in for the functions to calculate the <code>in_features</code> manually.</p>
<p>My environment or something does not recognize LazyLinears when I replace<br>
<code>self.fc1 = nn.Linear(16 * 5 * 5, 120)</code><br>
with<br>
<code>self.fc1 = nn.LazyLinears(120)</code>.</p>

Matias_Vasquez: <p>You can print the shape of <code>x</code> right before you feed it to your first linear layer.</p>
<pre><code class="lang-python">print(x.shape)
</code></pre>

Matias_Vasquez: <p>As <a class="mention" href="/u/ptrblck">@ptrblck</a> said, the forward method uses your layers when you pass something through your network.</p>
<p>For debugging purposes you can add a print statement in this forward method so that you get an idea of what is happening before your get your error.</p>
<aside class="quote no-group quote-modified" data-username="mohassan99" data-post="17" data-topic="150750">
<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/mohassan99/48/49201_2.png" class="avatar"> mohassan99:</div>
<blockquote>
<pre><code class="lang-auto">class Net(nn.Module):
    def __init__(self):
        super().__init__()
        #self.conv1 = nn.Conv2d(3, 6, 5)
        self.conv1 = nn.Conv2d(1, 6, 5)
        self.pool = nn.MaxPool2d(2, 2)
        self.conv2 = nn.Conv2d(6, 16, 5)
        self.fc1 = nn.Linear(16 * 5 * 5, 120)
        self.fc2 = nn.Linear(120, 84)
        self.fc3 = nn.Linear(84, 10)

    def forward(self, x):
        print("Input shape = ", x.shape)
        x = self.pool(F.relu(self.conv1(x)))
        print("Shape after conv1 = ", x.shape)
        x = self.pool(F.relu(self.conv2(x)))
        print("Shape after conv2 = ", x.shape)
        x = torch.flatten(x, 1) # flatten all dimensions except batch
        print("Shape after flatten = ", x.shape)
        x = F.relu(self.fc1(x)) #relu is an activation function
        print("Shape after fc1 = ", x.shape)
        x = F.relu(self.fc2(x))
        print("This is not even my final shape = ", x.shape)
        x = self.fc3(x)
        print("Final shape = ", x.shape)
        return x
    
net = Net()
</code></pre>
</blockquote>
</aside>
<p>So the <code>H_in</code> would refer to the height of the input shape for each layer. This means that <code>H_out</code> from conv1 would be the same as <code>H_in</code> for conv2.</p>
<p>Also, the shapes are in the format <code>BxCxHxW</code> = <code>Batch x Channel x Height x Width</code>.</p>