RuntimeError: Given transposed=1, weight of size [192, 64, 4, 4], expected input[8, 252, 258, 258] to have 192 channels, but got 252 channels instead

bash: <p>Hello please i need help with this error</p>
<pre><code class="lang-auto">RuntimeError: Given transposed=1, weight of size [192, 64, 4, 4], expected input[8, 252, 258, 258] to have 192 channels, but got 252 channels instead
</code></pre>
<p>the error is at the def forward of the generator</p>
<pre><code class="lang-auto">x = nn.functional.relu(self.deconv1(x), inplace=True)
</code></pre>
<p>here is the full code</p>
<pre><code class="lang-auto">import torch
import torch.nn as nn
import torch.nn.functional as F

# Depthwise dilated convolutional layer
class DepthwiseDilatedConv(nn.Module):
    def __init__(self, in_channels, latent_dim, out_channels, dilation_factor):
        super(DepthwiseDilatedConv, self).__init__()
        self.depthwise_conv = nn.Conv2d(in_channels + latent_dim, in_channels + latent_dim,
                                       kernel_size=3, padding=dilation_factor, dilation=dilation_factor, groups=in_channels + latent_dim)
        self.batch_norm1 = nn.BatchNorm2d(in_channels + latent_dim, momentum=0.78)
        self.pointwise_conv = nn.Conv2d(in_channels + latent_dim, out_channels, kernel_size=1)
        self.batch_norm2 = nn.BatchNorm2d(out_channels, momentum=0.78)

    def forward(self, x, latent_noise):
        latent_noise = latent_noise.expand(-1, -1, x.size(2), x.size(3))
        x = torch.cat([x, latent_noise], dim=1)
        x = self.depthwise_conv(x)
        x = self.batch_norm1(x)
        x = F.relu(x, inplace=True)
        x = self.pointwise_conv(x)
        x = self.batch_norm2(x)
        return x

class FeatureReuseResidualBlock(nn.Module):
    def __init__(self, in_channels, out_channels):
        super(FeatureReuseResidualBlock, self).__init__()
        self.conv1 = nn.Conv2d(in_channels, out_channels, kernel_size=1, padding=1)
        self.batch_norm1 = nn.BatchNorm2d(out_channels, momentum=0.78)
        self.conv2 = nn.Conv2d(out_channels, out_channels, kernel_size=3, padding=1)
        self.batch_norm2 = nn.BatchNorm2d(out_channels, momentum=0.78)
        self.conv3 = nn.Conv2d(out_channels, out_channels, kernel_size=3, padding=1)
        self.batch_norm3 = nn.BatchNorm2d(out_channels, momentum=0.78)
        self.conv4 = nn.Conv2d(out_channels, in_channels, kernel_size=3, padding=1)
        self.batch_norm4 = nn.BatchNorm2d(in_channels, momentum=0.78)

    def forward(self, x):
        residual1 = x
        x = self.conv1(x)
        x = self.batch_norm1(x)
        residual2 = x
        x = self.conv2(x)
        x = self.batch_norm2(x)
        x = F.relu(x, inplace=True)
        x = self.conv3(x)
        x = self.batch_norm3(x)
        x = F.relu(x, inplace=True)
        x = self.conv4(x)
        x = self.batch_norm4(x)
        x = torch.cat((x, residual2), dim=1)
        residual1 = F.pad(residual1, (0, x.shape[3] - residual1.shape[3], 0, x.shape[2] - residual1.shape[2], 0, x.shape[1] - residual1.shape[1]))
        x += residual1
        x = F.relu(x, inplace=True)
        print("FeatureReuseResidualBlock x - Output Shape:", x.shape)

        return x

# InceptionV3 with Factorization// 2
class InceptionV3Factorized(nn.Module):
    def __init__(self, in_channels, out_channels):
        super(InceptionV3Factorized, self).__init__()
        self.conv1x1 = nn.Conv2d(128, out_channels, kernel_size=1)  # Adjust the output channels here

        self.conv3x3_reduce = nn.Conv2d(128, out_channels // 3, kernel_size=1)
        self.conv3x3_1 = nn.Conv2d(out_channels // 3, out_channels // 3, kernel_size=(1, 3), padding=(0, 1))
        self.conv3x3_2 = nn.Conv2d(out_channels // 3, out_channels // 3, kernel_size=(3, 1), padding=(1, 0))

        self.conv5x5_reduce = nn.Conv2d(128, out_channels // 6, kernel_size=1)
        self.conv5x5_1 = nn.Conv2d(out_channels // 6, out_channels // 6, kernel_size=(1, 5), padding=(0, 2))
        self.conv5x5_2 = nn.Conv2d(out_channels // 6, out_channels // 6, kernel_size=(5, 1), padding=(2, 0))

        self.pool_proj = nn.Conv2d(128, out_channels // 3, kernel_size=1)

    def forward(self, x):
        print("InceptionV3Factorized x - Output Shape:", x.shape)
        x1 = nn.functional.relu(self.conv1x1(x), inplace=True)
        print("InceptionV3Factorized x1 - Output Shape:", x1.shape)
        x2 = nn.functional.relu(self.conv3x3_reduce(x), inplace=True)
        x2_1 = nn.functional.relu(self.conv3x3_1(x2), inplace=True)
        x2_2 = nn.functional.relu(self.conv3x3_2(x2), inplace=True)
        print("InceptionV3Factorized x2 - Output Shape:", x2.shape)
        x3 = nn.functional.relu(self.conv5x5_reduce(x), inplace=True)
        x3_1 = nn.functional.relu(self.conv5x5_1(x3), inplace=True)
        x3_2 = nn.functional.relu(self.conv5x5_2(x3), inplace=True)
        print("InceptionV3Factorized x3 - Output Shape:", x3.shape)
        x4 = nn.functional.relu(F.max_pool2d(x, kernel_size=3, stride=1, padding=1))
        x4 = nn.functional.relu(self.pool_proj(x4), inplace=True)
        print("InceptionV3Factorized x4 - Output Shape:", x4.shape)

        # Adjust the concatenation to have the desired shape
        x1 = F.pad(x1, (0, x4.shape[3] - x1.shape[3], 0, x4.shape[2] - x1.shape[2], 0, x4.shape[1] - x1.shape[1]))
        x2_1 = F.pad(x2_1, (0, x4.shape[3] - x2_1.shape[3], 0, x4.shape[2] - x2_1.shape[2], 0, x4.shape[1] - x2_1.shape[1]))
        x2_2 = F.pad(x2_2, (0, x4.shape[3] - x2_2.shape[3], 0, x4.shape[2] - x2_2.shape[2], 0, x4.shape[1] - x2_2.shape[1]))
        x3_1 = F.pad(x3_1, (0, x4.shape[3] - x3_1.shape[3], 0, x4.shape[2] - x3_1.shape[2], 0, x4.shape[1] - x3_1.shape[1]))
        x3_2 = F.pad(x3_2, (0, x4.shape[3] - x3_2.shape[3], 0, x4.shape[2] - x3_2.shape[2], 0, x4.shape[1] - x3_2.shape[1]))

        output = torch.cat([x1, x2_1, x2_2, x3_1, x3_2, x4], dim=1)
        print("InceptionV3Factorized - Output Shape:", output.shape)
        return output


# GAN Generator Architecture
class Generator(nn.Module):
    def __init__(self, image_channels, latent_dim, channels=64, inception_out_channels=128):
        super(Generator, self).__init__()

        self.depthwise_dilated_conv = DepthwiseDilatedConv(image_channels, latent_dim, channels, dilation_factor=2)
        self.feature_reuse_residual_block = FeatureReuseResidualBlock(channels, channels)
        self.inception_block = InceptionV3Factorized(channels, inception_out_channels)

        # Adjust the input channels for deconv1
        deconv1_input_channels = inception_out_channels + channels
        self.deconv1 = nn.ConvTranspose2d(deconv1_input_channels, channels, kernel_size=4, stride=2, padding=1)
        self.deconv2 = nn.ConvTranspose2d(channels, 64, kernel_size=4, stride=2, padding=1)
        self.final_conv = nn.Conv2d(64, image_channels, kernel_size=3, stride=1, padding=1)
        self.tanh = nn.Tanh()

    def forward(self, images, latent_noise):
        x = self.depthwise_dilated_conv(images, latent_noise)
        print("generator depthwise_dilated_conv- Output Shape:", x.shape)
        x = self.feature_reuse_residual_block(x)
        print("generator feature_reuse_residual_block - Output Shape:", x.shape)
        x = self.inception_block(x)
        print("generator inception_block - Output Shape:", x.shape)

        # Verify the number of channels in the deconv1 input
        channels=64
        deconv1_input_channels = x.shape[1] + channels
        print(f"Expected deconv1 input channels: {deconv1_input_channels}")

        # Debugging: print the shapes before deconv1
        print(f"Before deconv1 - x.shape: {x.shape}")
        # Adjust the number of channels in the deconv1 layer
        x = nn.functional.relu(self.deconv1(x), inplace=True)
        x = nn.functional.relu(self.deconv2(x), inplace=True)
        x = self.tanh(self.final_conv(x))
        print("Generator - Final Output Shape:", x.shape)
        return x

# Testing the model with random noise and images
torch.manual_seed(42)

# Instantiate the generator
image_channels = 1  # Grayscale images
latent_dim = 100
generator = Generator(image_channels, latent_dim, channels=64, inception_out_channels=128)

# Generate random noise and images
random_noise = torch.randn(8, latent_dim, 1, 1)
random_images = torch.randn(8, image_channels, 256, 256)

# Forward pass through the generator
generated_image = generator(random_images, random_noise)

# Print the shape of the generated image
print("Generated Image Shape:", generated_image.shape)
</code></pre>

ptrblck: <p>You should double check your padding approach as you are changing the channels, while I would guess you want to manipulate the spatial size.<br>
Shapes before applying <code>F.pad</code>:</p>
<pre data-code-wrap="python"><code class="lang-python">print(x1.shape, x2_1.shape, x2_2.shape, x3_1.shape, x3_2.shape, x4.shape)
# torch.Size([8, 128, 258, 258]) torch.Size([8, 42, 258, 258]) torch.Size([8, 42, 258, 258]) torch.Size([8, 
21, 258, 258]) torch.Size([8, 21, 258, 258]) torch.Size([8, 42, 258, 258])
</code></pre>
<p>After:</p>
<pre data-code-wrap="python"><code class="lang-python">print(x1.shape, x2_1.shape, x2_2.shape, x3_1.shape, x3_2.shape, x4.shape)
# torch.Size([8, 42, 258, 258]) torch.Size([8, 42, 258, 258]) torch.Size([8, 42, 258, 258]) torch.Size([8, 42, 258, 258]) torch.Size([8, 42, 258, 258]) torch.Size([8, 42, 258, 258])
</code></pre>
<p>If this is desired, change <code>deconv1_input_channels = 6 * (inception_out_channels // 3)</code> and it should work.</p>

bash: <p>Hi thanks please can you clarify more i really did not understand what you mean.</p>

ptrblck: <p>Could you clarify which parts of the message weren’t understood so I can provide more details?</p>

bash: <p>Please this “You should double check your padding approach as you are changing the channels, while I would guess you want to manipulate the spatial size.<br>
Shapes before applying <code>F.pad</code>”</p>

bash: <p>Or please help me with the correct version of the code if possible.</p>