Expected 4D input (got 3D input)

jeremy_eudaric: <p>Hello l am trying to do an  auto encoder with 2 inputs base on the Siamese method but l got this issue and l don’t know why. Could you help me ?</p>
<p>ValueError                                Traceback (most recent call last)<br>
Cell In[72], line 3<br>
1 epochs=10<br>
2 for epoch in range(1,epochs+1):<br>
----&gt; 3       training(epoch)</p>
<p>Cell In[71], line 40, in training(epochs)<br>
35 <span class="hashtag-raw">#Clear</span> the gradients<br>
37  optimizer.zero_grad()<br>
—&gt; 40  output1,ouptut2 = Model(img_pre,img_post)<br>
42  loss = criterion(output1,output2,data)<br>
44  loss.backward()</p>
<p>File ~/miniconda3/lib/python3.10/site-packages/torch/nn/modules/module.py:1501, in Module._call_impl(self, *args, **kwargs)<br>
1496 # If we don’t have any hooks, we want to skip the rest of the logic in<br>
1497 # this function, and just call forward.<br>
1498 if not (self._backward_hooks or self._backward_pre_hooks or self._forward_hooks or self._forward_pre_hooks<br>
1499         or _global_backward_pre_hooks or _global_backward_hooks<br>
1500         or _global_forward_hooks or _global_forward_pre_hooks):<br>
 → 1501     return forward_call(*args, **kwargs)<br>
1502 # Do not call functions when jit is used<br>
1503 full_backward_hooks, non_full_backward_hooks = [], []</p>
<p>File ~/codes/Auto_Encoder/Auto_encoder.py:106, in Auto_encoder.forward(self, x1, x2)<br>
104 def forward(self, x1,x2):<br>
 → 106     encoded = self.encoder(x1)<br>
107     decoded1 = self.decoder(encoded)<br>
110     encoded = self.encoder(x2)</p>
<p>File ~/miniconda3/lib/python3.10/site-packages/torch/nn/modules/module.py:1501, in Module._call_impl(self, *args, **kwargs)<br>
1496 # If we don’t have any hooks, we want to skip the rest of the logic in<br>
1497 # this function, and just call forward.<br>
1498 if not (self._backward_hooks or self._backward_pre_hooks or self._forward_hooks or self._forward_pre_hooks<br>
1499         or _global_backward_pre_hooks or _global_backward_hooks<br>
1500         or _global_forward_hooks or _global_forward_pre_hooks):<br>
 → 1501     return forward_call(*args, **kwargs)<br>
1502 # Do not call functions when jit is used<br>
1503 full_backward_hooks, non_full_backward_hooks = [], []</p>
<p>File ~/miniconda3/lib/python3.10/site-packages/torch/nn/modules/container.py:217, in Sequential.forward(self, input)<br>
215 def forward(self, input):<br>
216     for module in self:<br>
 → 217         input = module(input)<br>
218     return input</p>
<p>File ~/miniconda3/lib/python3.10/site-packages/torch/nn/modules/module.py:1501, in Module._call_impl(self, *args, **kwargs)<br>
1496 # If we don’t have any hooks, we want to skip the rest of the logic in<br>
1497 # this function, and just call forward.<br>
1498 if not (self._backward_hooks or self._backward_pre_hooks or self._forward_hooks or self._forward_pre_hooks<br>
1499         or _global_backward_pre_hooks or _global_backward_hooks<br>
1500         or _global_forward_hooks or _global_forward_pre_hooks):<br>
 → 1501     return forward_call(*args, **kwargs)<br>
1502 # Do not call functions when jit is used<br>
1503 full_backward_hooks, non_full_backward_hooks = [], []</p>
<p>File ~/miniconda3/lib/python3.10/site-packages/torch/nn/modules/batchnorm.py:138, in _BatchNorm.forward(self, input)<br>
137 def forward(self, input: Tensor) → Tensor:<br>
 → 138     self._check_input_dim(input)<br>
140     # exponential_average_factor is set to self.momentum<br>
141     # (when it is available) only so that it gets updated<br>
142     # in ONNX graph when this node is exported to ONNX.<br>
143     if self.momentum is None:</p>
<p>File ~/miniconda3/lib/python3.10/site-packages/torch/nn/modules/batchnorm.py:410, in BatchNorm2d._check_input_dim(self, input)<br>
408 def _check_input_dim(self, input):<br>
409     if input.dim() != 4:<br>
 → 410         raise ValueError(“expected 4D input (got {}D input)”.format(input.dim()))</p>
<p>ValueError: expected 4D input (got 3D input)</p>
<p>my code :</p>
<p>class Auto_encoder(nn.Module):</p>
<pre><code>def __init__(self, in_channels=3, out_channels=16, latent_dim=200, act_fn=nn.ReLU()):
    super(Auto_encoder,self).__init__()

    
    
    #Encoder
    
    self.encoder = nn.Sequential(
    nn.Conv2d(in_channels, out_channels, 3, padding=1), # (32, 32)
    act_fn,
    nn.BatchNorm2d(out_channels),
    nn.Conv2d(out_channels, out_channels, 3, padding=1), 
    act_fn,
    nn.BatchNorm2d(out_channels),
    nn.Conv2d(out_channels, 2*out_channels, 3, padding=1, stride=2), # (16, 16)
    act_fn,
    nn.BatchNorm2d(out_channels),
    nn.Conv2d(2*out_channels, 2*out_channels, 3, padding=1),
    nn.BatchNorm2d(out_channels),
    act_fn,
    nn.BatchNorm2d(out_channels),
    nn.Conv2d(2*out_channels, 4*out_channels, 3, padding=1, stride=2), # (8, 8)
    act_fn,
    nn.BatchNorm2d(out_channels),
    nn.Conv2d(4*out_channels, 4*out_channels, 3, padding=1),
    act_fn,
    nn.BatchNorm2d(out_channels),
    nn.Flatten(),
    nn.Linear(4*out_channels*8*8, latent_dim),
    act_fn
)



    #Decoder



    self.decoder  = nn.Sequential(
         
        nn.Linear(latent_dim, 4*out_channels*8*8),
        act_fn,
        nn.ConvTranspose2d(4*out_channels, 4*out_channels, 3, padding=1), # (8, 8)
        
        act_fn,
        
        nn.ConvTranspose2d(4*out_channels, 2*out_channels, 3, padding=1, 
                       stride=2, output_padding=1), # (16, 16)
        act_fn,
        
        nn.ConvTranspose2d(2*out_channels, 2*out_channels, 3, padding=1),
        act_fn,
        
        nn.ConvTranspose2d(2*out_channels, out_channels, 3, padding=1, 
                       stride=2, output_padding=1), # (32, 32)
        act_fn,
        
        nn.ConvTranspose2d(out_channels, out_channels, 3, padding=1),
        act_fn,
        
        nn.ConvTranspose2d(out_channels, in_channels, 3, padding=1)
)
    
    
    
def forward(self, x1,x2):
    
    encoded = self.encoder(x1)
    decoded1 = self.decoder(encoded)
    
    
    encoded = self.encoder(x2)
    decoded2 = self.decoder(encoded)
   
    return decoded1, decoded2
</code></pre>
<p>def training(epochs):</p>
<pre><code>    Model.train()              
    epoch_loss = 0.0
    running_loss_train=0.0

    #for label,data in dataloader_train:
    for data, _  in (dataloader_train): 
    
    
               img_pre, img_post = data
               img_pre.to(device=device)  # move to device, e.g. GPU
                

               img_post.to(device=device)
             
              #Clear the gradients
            
               optimizer.zero_grad()

            
               output1,ouptut2 = Model(img_pre,img_post)
           
               loss = criterion(output1,output2,data)

               loss.backward()
            
            # Update Weight
               optimizer.step()
            
           #Calculate prediction
               prediction_train=output.argmax(dim=1)

    
               running_loss_train =+ loss.item() 
      
        
               epoch_loss += running_loss_train / len(train_loader)
            
              #acc_train += (prediction_train == label).type(torch.float).sum().item()
              
               Tp = ((label == 1) &amp; (prediction_train == 1)).sum().item()
              
               fp = ((label == 0) &amp; (prediction_train == 1)).sum().item()
              
               Fn = ((label == 1) &amp; (prediction_train == 0)).sum().item()
                
            
            # calculate precision, recall, and F1-score
            
               Precision_train = Tp / (Tp + Fp)

             
               Recall_train = Tp / (Tp + Fn)
              
               F1_score_train = 2 * (Precision * Recall) / (Precision + Recall)
</code></pre>

ptrblck: <p>Your code is nor executable as a few <code>nn.BatchNorm2d</code> definitions are wrong.<br>
E.g. in:</p>
<pre><code class="lang-python">    nn.Conv2d(out_channels, 2*out_channels, 3, padding=1, stride=2), # (16, 16)
    act_fn,
    nn.BatchNorm2d(out_channels),
    nn.Conv2d(2*out_channels, 2*out_channels, 3, padding=1),
    nn.BatchNorm2d(out_channels),
    act_fn,
    nn.BatchNorm2d(out_channels),
    nn.Conv2d(2*out_channels, 4*out_channels, 3, padding=1, stride=2), # (8, 8)
    act_fn,
    nn.BatchNorm2d(out_channels),
    nn.Conv2d(4*out_channels, 4*out_channels, 3, padding=1),
    act_fn,
    nn.BatchNorm2d(out_channels),
</code></pre>
<p>all batchnorm layers will fail as their number of channels is wrong.<br>
After fixing it, I also changed the linear layer feature dimension since you didn’t provide any input shapes.<br>
The error is then raised in the <code>self.decoder</code> module as its input is 2-dimensional and unsqueezed for you in the fist <code>nn.ConvTranspose2d</code> layer making it 3-dimensional.<br>
Unsqueeze the missing spatial dimensions manually after the first linear layer in the <code>self.decoder</code> branch and it should work.</p>