How to do TransposeConv2D for smaller size?

vishalthengane: <p>Hello all,</p>
<p>I am working on a ProteinGAN implementation in PyTorch. The generator model has an input of <code>[batch_size, z_dim]</code> and the output is <code>[batch_size, 512, 21]</code>. The model structure is like this;</p>
<p><div class="lightbox-wrapper"><a class="lightbox" href="https://discuss.pytorch.org/uploads/default/original/3X/c/c/cc84a7af480d3b18cc0994e4d38ad16dc7415058.png" data-download-href="https://discuss.pytorch.org/uploads/default/cc84a7af480d3b18cc0994e4d38ad16dc7415058" title="Screenshot from 2022-01-17 19-29-35"><img src="https://discuss.pytorch.org/uploads/default/optimized/3X/c/c/cc84a7af480d3b18cc0994e4d38ad16dc7415058_2_420x499.png" alt="Screenshot from 2022-01-17 19-29-35" data-base62-sha1="tbfCc30KF3Hz8fCK9j7gmQ7S7ag" width="420" height="499" srcset="https://discuss.pytorch.org/uploads/default/optimized/3X/c/c/cc84a7af480d3b18cc0994e4d38ad16dc7415058_2_420x499.png, https://discuss.pytorch.org/uploads/default/original/3X/c/c/cc84a7af480d3b18cc0994e4d38ad16dc7415058.png 1.5x, https://discuss.pytorch.org/uploads/default/original/3X/c/c/cc84a7af480d3b18cc0994e4d38ad16dc7415058.png 2x" data-dominant-color="F6F3EC"><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">Screenshot from 2022-01-17 19-29-35</span><span class="informations">561×667 44.8 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><br>
<div class="lightbox-wrapper"><a class="lightbox" href="https://discuss.pytorch.org/uploads/default/original/3X/0/e/0eaecd8f28995440a49d950a8aa4177adc41256d.png" data-download-href="https://discuss.pytorch.org/uploads/default/0eaecd8f28995440a49d950a8aa4177adc41256d" title="Screenshot from 2022-01-17 19-23-48"><img src="https://discuss.pytorch.org/uploads/default/optimized/3X/0/e/0eaecd8f28995440a49d950a8aa4177adc41256d_2_690x435.png" alt="Screenshot from 2022-01-17 19-23-48" data-base62-sha1="25TchVI2VzwpDjMYOJhfJLRkyuh" width="690" height="435" srcset="https://discuss.pytorch.org/uploads/default/optimized/3X/0/e/0eaecd8f28995440a49d950a8aa4177adc41256d_2_690x435.png, https://discuss.pytorch.org/uploads/default/optimized/3X/0/e/0eaecd8f28995440a49d950a8aa4177adc41256d_2_1035x652.png 1.5x, https://discuss.pytorch.org/uploads/default/original/3X/0/e/0eaecd8f28995440a49d950a8aa4177adc41256d.png 2x" data-dominant-color="E9E9E9"><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">Screenshot from 2022-01-17 19-23-48</span><span class="informations">1214×767 118 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>Based on that I have implemented the following code, but i when I am running it  the following output size is coming. I tried passing stride=(2, 1) so the width size will not increase. But I am getting this error;</p>
<pre><code class="lang-auto">RuntimeError: output padding must be smaller than either stride or dilation, but got output_padding_height: 1 output_padding_width: 1 stride_height: 2 stride_width: 1 dilation_height: 1 dilation_width: 1
</code></pre>
<p>Output:</p>
<pre><code class="lang-auto">torch.Size([1, 512, 16, 16]) 
torch.Size([1, 256, 32, 32])
torch.Size([1, 128, 64, 64])
torch.Size([1, 64, 128, 128])
torch.Size([1, 32, 256, 256])
torch.Size([1, 16, 512, 512])
torch.Size([1, 21, 512, 512]) # it suppose to be [21, 512]
</code></pre>
<p>Code;</p>
<pre><code class="lang-auto">import torch
import torch.nn as nn
import torch.nn.functional as F


class ResidualBlock(nn.Module):
    def __init__(self, in_channels, out_channels, kernel_size=3, stride=2, sn_itrs=1) -&gt; None:
        super().__init__()
        self.deconv1 = nn.ConvTranspose2d(
            in_channels, 
            out_channels, 
            kernel_size, 
            stride=stride,
            output_padding=1,
            padding=1
        )
        self.deconv2 = nn.ConvTranspose2d(
            in_channels, 
            in_channels, 
            kernel_size, 
            stride=stride,
            output_padding=1,
            padding=1
        )
        self.conv = nn.Conv2d(
            in_channels,
            out_channels,
            kernel_size,
            stride=1,
            padding=1
        )

    def shortcut(self, x):
        return self.deconv1(x)

    def residual(self, x):
        x = self.deconv2(F.leaky_relu(x))
        x = self.conv(F.leaky_relu(x))
        return x

    def forward(self, x):
        out = self.shortcut(x) + self.residual(x)
        print(out.shape)
        return out


class Generator(nn.Module):
    def __init__(self, cfg) -&gt; None:
        super().__init__()
        self.height = cfg.HEIGHT
        self.width = cfg.WIDTH
        self.hidden_dim = cfg.GF_DIM * (2 ** (len(cfg.GENERATOR_LAYERS) - 1))

        self.linear = nn.Linear(cfg.Z_DIM, self.height * self.width * self.hidden_dim)
        self.residuals = nn.Sequential(
            *self.make_layers(cfg.GENERATOR_LAYERS)
        )
        self.batch_norm = nn.BatchNorm2d(num_features=self.hidden_dim // 64)
        self.conv = nn.Conv2d(self.hidden_dim // 64, cfg.VOCAB_SIZE, 3, padding=1)

    def make_layers(self, layer_config):
        layers = []
        in_channels = self.height * self.width * self.hidden_dim
        for x in layer_config:
            out_channels = in_channels // 2
            if x == "A":
                pass
            else:
                layers.append(ResidualBlock(in_channels, out_channels))
            in_channels = out_channels
        return layers

    def forward(self, x):
        x = self.linear(x)
        x = x.view((-1, self.hidden_dim, self.height, self.width))
        x = self.residuals(x)
        x = F.leaky_relu(self.batch_norm(x))
        x = torch.tanh(self.conv(x))
        return x

class cfg:
    def __init__(self):
        self.VOCAB_SIZE = 21
        self.GENERATOR_LAYERS = ["R", "R", "R", "R", "R", "R"] # I am no using attention at the moment
        self.HEIGHT = 8
        self.WIDTH =  8
        self.Z_DIM = 128
        self.GF_DIM = 32

if __name__ == "__main__":
    gen = Generator(cfg())
    print(gen(torch.rand(1, 128)).shape)
</code></pre>