ValueError with mismatched target and input size

21 views Asked by At

I am new to machine learning and have been playing around with implementing DCGAN models as a requisite for the research I am doing. I have a somewhat basic model but everytime I run it, regardless what loss function I select as my criterion, I always get a similar message about input and output size being mismatched and I don't know what to do. The stacktrace is as follows:

Traceback (most recent call last): File "c:\PycharmProjects\ctgan\dcgan.py", line 148, in <module dcgan.train() File "c:\PycharmProjects\ctgan\dcgan.py", line 101, in train errD_real = criterion(output_real, label_real) # Calculate the loss with the reshaped >labels File "C:.conda\envs\DL_IDS\lib\site-packages\torch\nn\modules\module.py", line 1511, in >_wrapped_call_impl return self._call_impl(*args, **kwargs) File "C:.conda\envs\DL_IDS\lib\site-packages\torch\nn\modules\module.py", line 1520, in >_call_impl return forward_call(*args, **kwargs) File "C:.conda\envs\DL_IDS\lib\site-packages\torch\nn\modules\loss.py", line 725, in >forward return F.binary_cross_entropy_with_logits(input, target, File "C:.conda\envs\DL_IDS\lib\site-packages\torch\nn\functional.py", line 3197, in >binary_cross_entropy_with_logits raise ValueError(f"Target size ({target.size()}) must be the same as input size ({input.size()})") ValueError: Target size (torch.Size([64, 1])) must be the same as input size (torch.Size([2304]))

The full code for my DCGAN model is as follows:

import torch
from torchvision import datasets, transforms
from torch.utils.data import DataLoader

import torch.nn as nn
import torch.optim as optim
import torchvision.utils as vutils


class DCGAN:
    def __init__(self, dataset, nz=100, ngf=79, ndf=79, nc=3):
        self.nz = nz
        self.ngf = ngf
        self.ndf = ndf
        self.nc = nc
        self.dataset = dataset

        # Initialize the networks
        self.netG = self.Generator(nz, ngf, nc)
        self.netD = self.Discriminator(nc, ndf)

        # Define the loss function and optimizers
        self.criterion = nn.BCEWithLogitsLoss()
        self.optimizerG = optim.SGD(self.netG.parameters(), lr=0.0002, momentum=0.9)
        self.optimizerD = optim.SGD(self.netD.parameters(), lr=0.0002, momentum=0.9)

    class Generator(nn.Module):
        def __init__(self, nz, ngf, nc):
            super(DCGAN.Generator, self).__init__()
            self.main = nn.Sequential(
                nn.ConvTranspose2d(nz, ngf * 4, 4, 1, 0, bias=False),
                nn.BatchNorm2d(ngf * 4),
                nn.ReLU(True),
                nn.ConvTranspose2d(ngf * 4, ngf * 2, 4, 2, 1, bias=False),
                nn.BatchNorm2d(ngf * 2),
                nn.ReLU(True),
                nn.ConvTranspose2d(ngf * 2, ngf, 4, 2, 1, bias=False),
                nn.BatchNorm2d(ngf),
                nn.ReLU(True),
                nn.ConvTranspose2d(ngf, nc, 4, 2, 1, bias=False),
                nn.Tanh()
            )

        def forward(self, x):
            return self.main(x)

    class Discriminator(nn.Module):
        def __init__(self, nc, ndf):
            super(DCGAN.Discriminator, self).__init__()
            self.main = nn.Sequential(
                nn.Conv2d(nc, ndf, 4, 2, 1, bias=False),
                nn.LeakyReLU(0.2, inplace=True),
                nn.Conv2d(ndf, ndf * 2, 4, 2, 1, bias=False),
                nn.BatchNorm2d(ndf * 2),
                nn.LeakyReLU(0.2, inplace=True),
                nn.Conv2d(ndf * 2, ndf * 4, 4, 2, 1, bias=False),
                nn.BatchNorm2d(ndf * 4),
                nn.LeakyReLU(0.2, inplace=True),
                nn.Conv2d(ndf * 4, 1, 4, 1, 0, bias=False),
                nn.Sigmoid()
            )

        def forward(self, x):
            print("input shape :", x.shape)
            if x.dim() == 3:
                # Add a batch dimension
                x = x.unsqueeze(0)

            x = self.main(x)
            return x.view(-1, 1)

    def train(self, num_epochs=10):
        # Data loading and preprocessing
        # Remove unused variable
        # transform = transforms.Compose([
        #     transforms.Resize((81, 393)),
        #     transforms.ToTensor(),
        #     transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5)),
        # ])

        # dataset = self.dataset
        # dataloader = DataLoader(dataset, batch_size=64, shuffle=True, num_workers=2)

        device = torch.device("cuda" if torch.cuda.is_available() else "cpu")

        # Sigmoid Cross Entropy Loss
        criterion = nn.BCEWithLogitsLoss()

        for epoch in range(num_epochs):
            for i, data in enumerate(dataloader, 0):
                # Update Discriminator
                self.netD.zero_grad()
                real_data = data[0].to(device)
                batch_size = real_data.size(0)

                # Create real labels (1s)
                label_real = torch.full((batch_size, 1), 1.0, device=device)  # Adjusted to match the dimensions

                output_real = self.netD(real_data).view(-1)
                label_real = label_real.view(-1, 1)  # Reshape label_real to match the shape of output_real
                errD_real = criterion(output_real, label_real)  # Calculate the loss with the reshaped labels
                errD_real.backward()

                noise = torch.randn(batch_size, self.nz, 1, 1, device=device)
                fake_data = self.netG(noise)

                # Create fake labels (0s)
                label_fake = torch.full((batch_size, 1), 0.0, device=device)  # Adjusted to match the dimensions

                output_fake = self.netD(fake_data.detach()).view(-1)
                errD_fake = criterion(output_fake, label_fake)
                errD_fake.backward()
                self.optimizerD.step()

                # Update Generator
                self.netG.zero_grad()
                label_real.fill_(1.0)  # Adjusted to use float labels
                output = self.netD(fake_data).view(-1)
                errG = criterion(output, label_real)
                errG.backward()
                self.optimizerG.step()

                if i % 100 == 0:
                    print('[%d/%d][%d/%d] Loss_D: %.4f Loss_G: %.4f'
                          % (epoch, num_epochs, i, len(dataloader),
                             errD_real.item() + errD_fake.item(), errG.item()))

            # Save generated images for every epoch
            fake = self.netG(torch.randn(64, self.nz, 1, 1, device=device))
            vutils.save_image(fake.detach(), f'fake_samples_epoch_{epoch + 1}.png', normalize=True)

        # Save the generator model
        torch.save(self.netG.state_dict(), 'dcgan_generator_weights.pth')


if __name__ == '__main__':

    # Example usage:
    # my_dataset = datasets.CIFAR10  # Set your dataset class dynamically
    transform = transforms.Compose([
        transforms.Resize(79),
        transforms.ToTensor(),
        transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5)),
    ])
    my_dataset = datasets.CIFAR10(root='./data', train=True, download=True, transform=transform)
    dataloader = DataLoader(my_dataset, batch_size=64, shuffle=True, num_workers=2)
    dcgan = DCGAN(dataset=dataloader)
    dcgan.train()
    pass

I have tried to expand, resize, reshape my data in all sorts of manner I could find online but none of it seems to yield any meaningful outcome. How to resolve this?

0

There are 0 answers