Convolution autoencoder target size that is different to the input size

username: MaxJohnson
cooked: <p>I am trying to modify the code below for the mnist dataset but it shows an error<br>
"<br>
ValueError: Using a target size (torch.Size([20, 1, 28, 28])) that is different to the input size (torch.Size([20, 20, 1, 1])) is deprecated. Please ensure they have the same size.<br>
"</p>
<pre><code class="lang-auto">import torch.nn as nn
import torch.nn.functional as F

# define the NN architecture
class ConvAutoencoder(nn.Module):
    def __init__(self):
        super(ConvAutoencoder, self).__init__()
        ## encoder layers ##
        # conv layer (depth from 3 --&gt; 16), 3x3 kernels
        self.conv1 = nn.Conv2d(1,20, 28, padding=1)  
        # conv layer (depth from 16 --&gt; 4), 3x3 kernels
        self.conv2 = nn.Conv2d(20, 20, 1, padding=1)
        # pooling layer to reduce x-y dims by two; kernel and stride of 2
        self.pool = nn.MaxPool2d(2, 2)
        
        ## decoder layers ##
        ## a kernel of 2 and a stride of 2 will increase the spatial dims by 2
        self.t_conv1 = nn.ConvTranspose2d(20, 20, 1, stride=2)
        self.t_conv2 = nn.ConvTranspose2d(20, 20,1, stride=2)

    def forward(self, x):
        ## encode ##
        # add hidden layers with relu activation function
        # and maxpooling after
        x = F.relu(self.conv1(x))
        x = self.pool(x)
        # add second hidden layer
        x = F.relu(self.conv2(x))
        x = self.pool(x)  # compressed representation
        
        ## decode ##
        # add transpose conv layers, with relu activation function
        x = F.relu(self.t_conv1(x))
        # output layer (with sigmoid for scaling from 0 to 1)
        x = F.sigmoid(self.t_conv2(x))
                
        return x

# initialize the NN
model = ConvAutoencoder()
print(model)
# specify loss function
criterion = nn.BCELoss()

# specify loss function
optimizer = torch.optim.Adam(model.parameters(), lr=0.001)
# number of epochs to train the model
n_epochs = 100

for epoch in range(1, n_epochs+1):
    # monitor training loss
    train_loss = 0.0
    
    ###################
    # train the model #
    ###################
    for data in train_loader:
        # _ stands in for labels, here
        # no need to flatten images
        images, _ = data
        # clear the gradients of all optimized variables
        optimizer.zero_grad()
        # forward pass: compute predicted outputs by passing inputs to the model
        outputs = model(images)
        # calculate the loss
        loss = criterion(outputs, images)
        # backward pass: compute gradient of the loss with respect to model parameters
        loss.backward()
        # perform a single optimization step (parameter update)
        optimizer.step()
        # update running training loss
        train_loss += loss.item()*images.size(0)
            
    # print avg training statistics 
    train_loss = train_loss/len(train_loader)
    print('Epoch: {} \tTraining Loss: {:.6f}'.format(
        epoch, 
        train_loss
        ))
</code></pre>

username: ptrblck
cooked: <p>The output of your model contains 20 channels and a single pixel, which doesn’t fit the input dimension of the <code>MNIST</code>-like input data.<br>
If you want to reconstruct the input, you would have to use <code>1</code> output channel in the last transposed convolution and would need to increase the spatial size by using a <code>kernel_size</code> in the <code>nn.ConvTranspose2d</code> layers, which is larger than <code>1</code>.</p>