Unet implementation, how to fix this. I tried changing the padding,stride, and kernel size but it didn't works

username: Ayush_Aditya
cooked: <p>class DoubleConv(nn.Module):<br>
def <strong>init</strong>(self, in_channels, out_channels):<br>
super(DoubleConv, self).<strong>init</strong>()<br>
self.conv = nn.Sequential(<br>
nn.Conv2d(in_channels, out_channels, 3, 1, 1),<br>
nn.BatchNorm2d(out_channels),<br>
nn.ReLU(inplace=True),<br>
nn.Conv2d(out_channels, out_channels, 3, 1, 1),<br>
nn.BatchNorm2d(out_channels),<br>
nn.ReLU(inplace=True)<br>
)</p>
<pre><code>def forward(self, x):
    return self.conv(x)
</code></pre>
<p>class UNetAudio(nn.Module):<br>
def <strong>init</strong>(self, in_channels, out_channels):<br>
super(UNetAudio, self).<strong>init</strong>()<br>
self.in_channels = in_channels<br>
self.out_channels = out_channels</p>
<pre><code>    self.down1 = DoubleConv(in_channels, 64)
    self.down2 = DoubleConv(64, 128)
    self.down3 = DoubleConv(128, 256)
    self.down4 = DoubleConv(256, 512)

    self.up1 = nn.ConvTranspose2d(512, 256, 2, 2)
    self.up2 = nn.ConvTranspose2d(256, 128, 2, 2)
    self.up3 = nn.ConvTranspose2d(128, 64, 2,2)
    
    self.out = nn.Conv2d(64, out_channels, 1)

def forward(self, x):
    # Encoder
    x1 = self.down1(x)
    x2 = self.down2(nn.MaxPool2d(2)(x1))
    x3 = self.down3(nn.MaxPool2d(2)(x2))
    x4 = self.down4(nn.MaxPool2d(2)(x3))

    # Decoder
    x = self.up1(x4)
    print(x.shape)
    print(x2.shape)
    print(x3.shape)
    x = self.up2(torch.cat([x, x3], dim=1))
    x = self.up3(torch.cat([x, x2], dim=1))
    x = self.out(torch.cat([x, x1], dim=1))
    
    return x
</code></pre>
<h2><a name="torchsize32-256-32-26-torchsize32-256-32-27-1" class="anchor" href="#torchsize32-256-32-26-torchsize32-256-32-27-1"></a>torch.Size([32, 256, 32, 26])<br>
torch.Size([32, 256, 32, 27])</h2>
<p>RuntimeError                              Traceback (most recent call last)<br>
Cell In[28], line 1<br>
----&gt; 1 training(train_loader, test_loader, num_epochs, model, loss_function, optimiser, scheduler, “UNetAudio”)</p>
<p>Cell In[16], line 11, in training(train_loader, val_loader, epochs, model, criterion, optimizer, scheduler, model_name)<br>
9 batch_Y=Variable(batch_Y.to(device))<br>
10 optimizer.zero_grad()<br>
—&gt; 11 outputs = model(batch_X)<br>
12 loss = criterion(outputs.squeeze(), batch_Y)<br>
13 loss.backward()</p>
<p>File D:\anaconda\envs\Pytorch\lib\site-packages\torch\nn\modules\module.py:1518, in Module._wrapped_call_impl(self, *args, **kwargs)<br>
1516     return self._compiled_call_impl(*args, **kwargs)  # type: ignore[misc]<br>
1517 else:<br>
 → 1518     return self._call_impl(*args, **kwargs)</p>
<p>File D:\anaconda\envs\Pytorch\lib\site-packages\torch\nn\modules\module.py:1527, in Module._call_impl(self, *args, **kwargs)<br>
1522 # If we don’t have any hooks, we want to skip the rest of the logic in<br>
1523 # this function, and just call forward.<br>
1524 if not (self._backward_hooks or self._backward_pre_hooks or self._forward_hooks or self._forward_pre_hooks<br>
1525         or _global_backward_pre_hooks or _global_backward_hooks<br>
1526         or _global_forward_hooks or _global_forward_pre_hooks):<br>
 → 1527     return forward_call(*args, **kwargs)<br>
1529 try:<br>
1530     result = None</p>
<p>Cell In[26], line 45, in UNetAudio.forward(self, x)<br>
43 print(x2.shape)<br>
44 print(x3.shape)<br>
—&gt; 45 x = self.up2(torch.cat([x, x3], dim=1))<br>
46 x = self.up3(torch.cat([x, x2], dim=1))<br>
47 x = self.out(torch.cat([x, x1], dim=1))</p>
<p>RuntimeError: Sizes of tensors must match except in dimension 1. Expected size 26 but got size 27 for tensor number 1 in the list.</p>

username: KFrank
cooked: <p>Hi Ayush!</p>
<aside class="quote no-group quote-modified" data-username="Ayush_Aditya" data-post="1" data-topic="197006" 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/ayush_aditya/48/62888_2.png" class="avatar"> Ayush_Aditya:</div>
<blockquote>
<pre><code>    # Decoder
    x = self.up1(x4)
    print(x.shape)
    print(x2.shape)
    print(x3.shape)
    x = self.up2(torch.cat([x, x3], dim=1))
</code></pre>
<h2>torch.Size([32, 256, 32, 26])<br>
torch.Size([32, 256, 32, 27])</h2>
<p>RuntimeError                              Traceback (most recent call last)<br>
…<br>
Cell In[26], line 45, in UNetAudio.forward(self, x)<br>
43 print(x2.shape)<br>
44 print(x3.shape)<br>
—&gt; 45 x = self.up2(torch.cat([x, x3], dim=1))<br>
46 x = self.up3(torch.cat([x, x2], dim=1))<br>
47 x = self.out(torch.cat([x, x1], dim=1))</p>
<p>RuntimeError: Sizes of tensors must match except in dimension 1. Expected size 26 but got size 27 for tensor number 1 in the list.</p>
</blockquote>
</aside>
<p>The short story is that the classic U-Net architecture only accepts inputs<br>
of certain specific shapes (although these shapes can vary, and – given<br>
adequate memory – can be arbitrarily large).  Your input has an invalid<br>
shape.</p>
<p>I’m not going to sort through your specific model to determine its valid<br>
input shapes, but what is going on is that when you “descend” through<br>
the U, the convolutions nibble away at the edges of your image (typically<br>
reducing its extent by two – one pixel on each side) and then your<br>
downsampling (<code>MaxPool2d (2)</code>) shrinks your image by a factor of two.</p>
<p>If the image that is input to your <code>MaxPool2d (2)</code> has a dimension that<br>
is not a multiple of two, no error occurs, but what would have been a<br>
fractional output dimension is rounded down.</p>
<p>When you go back up the U, your upsampling (<code>ConvTranspose2d</code>)<br>
expands your image by a factor of two.  You then implement the “skip<br>
connection” by concatenating the matching image from when you<br>
descended the U.  If one of the downsamplings between the two ends<br>
of your skip connection rounded down, the shapes of your “matching”<br>
images won’t be the same and <code>torch.cat()</code> will fail with the error you<br>
see.</p>
<p>You have to track how the shape of your image changes as it moves<br>
through the layers of your U-Net, look for such mismatches, and use<br>
that analysis to determine what input shapes are valid.  Then only input<br>
images with valid shapes to your U-Net.  (If you have an input image with<br>
an invalid shape, my general recommendation would be to “reflection-pad”<br>
that image up to the next larger valid shape.)</p>
<p>Good luck.</p>
<p>K. Frank</p>

username: Ayush_Aditya
cooked: <p>thank you, but I was following a research paper and they suggested doing in this way that is why i tried but your explanation did help me understand my problem more clearly.</p>