Importing Transparent images gives RuntimeError: The size of tensor a (4) must match the size of tensor b (3) at non-singleton dimension 0
I'm trying to learn AI.
I have GAN (generative adversarial network) code with images with ALPHA Channel(transparency).
All images have alpha channel.
To prove that I wrote small image_validator.py program like below
from PIL import Image
import glob


def main():
    image_list = []
    img_number = 0
    for filename in glob.glob('data/*/*.*'):
        try:
            im = Image.open(filename)
            # print(filename)
            if str(im.mode) != &quot;RGBA&quot;:
                print(&quot;alpha &quot; + str(im.mode))
                img_number = img_number+1
                print(str(img_number))
        except Exception as e:
            print(&quot;Error : &quot;+filename)


if __name__ == &quot;__main__&quot;:
    main()

Above program prints nothing which means all images have ALPHA Channel. To Test above program I added single image WITHOUT ALPHA Channel. So I can confirm all images have ALPHA CHANNEL.
my generator.py is like below
import torch.nn as nn
class G(nn.Module):
    feature_maps = 512
    kernel_size = 4
    stride = 2
    padding = 1
    bias = False

    def __init__(self, input_vector):
        super(G, self).__init__()
        self.main = nn.Sequential(
            nn.ConvTranspose2d(input_vector, self.feature_maps, self.kernel_size, 1, 0, bias=self.bias),
            nn.BatchNorm2d(self.feature_maps), nn.ReLU(True),
            nn.ConvTranspose2d(self.feature_maps, int(self.feature_maps // 2), self.kernel_size, self.stride, self.padding,
                               bias=self.bias),
            nn.BatchNorm2d(int(self.feature_maps // 2)), nn.ReLU(True),
            nn.ConvTranspose2d(int(self.feature_maps // 2), int((self.feature_maps // 2) // 2), self.kernel_size, self.stride,
                               self.padding,
                               bias=self.bias),
            nn.BatchNorm2d(int((self.feature_maps // 2) // 2)), nn.ReLU(True),
            nn.ConvTranspose2d((int((self.feature_maps // 2) // 2)), int(((self.feature_maps // 2) // 2) // 2), self.kernel_size,
                               self.stride, self.padding,
                               bias=self.bias),
            nn.BatchNorm2d(int((self.feature_maps // 2) // 2) // 2), nn.ReLU(True),
            nn.ConvTranspose2d(int(((self.feature_maps // 2) // 2) // 2), 4, self.kernel_size, self.stride, self.padding,
                               bias=self.bias),
            nn.Tanh()
        )

    def forward(self, input):
        output = self.main(input)
        return output

my discriminator.py is like below
    import torch.nn as nn
class D(nn.Module):
    feature_maps = 64
    kernel_size = 4
    stride = 2
    padding = 1
    bias = False
    inplace = True

    def __init__(self):
        super(D, self).__init__()
        self.main = nn.Sequential(
            nn.Conv2d(4, self.feature_maps, self.kernel_size, self.stride, self.padding, bias=self.bias),
            nn.LeakyReLU(0.2, inplace=self.inplace),
            nn.Conv2d(self.feature_maps, self.feature_maps * 2, self.kernel_size, self.stride, self.padding,
                      bias=self.bias),
            nn.BatchNorm2d(self.feature_maps * 2), nn.LeakyReLU(0.2, inplace=self.inplace),
            nn.Conv2d(self.feature_maps * 2, self.feature_maps * (2 * 2), self.kernel_size, self.stride, self.padding,
                      bias=self.bias),
            nn.BatchNorm2d(self.feature_maps * (2 * 2)), nn.LeakyReLU(0.2, inplace=self.inplace),
            nn.Conv2d(self.feature_maps * (2 * 2), self.feature_maps * (2 * 2 * 2), self.kernel_size, self.stride,
                      self.padding, bias=self.bias),
            nn.BatchNorm2d(self.feature_maps * (2 * 2 * 2)), nn.LeakyReLU(0.2, inplace=self.inplace),
            nn.Conv2d(self.feature_maps * (2 * 2 * 2), 1, self.kernel_size, 1, 0, bias=self.bias),
            nn.Sigmoid()
        )

    def forward(self, input):
        output = self.main(input)
        return output.view(-1)

my main program gan.py is like below
    # Importing the libraries
from __future__ import print_function
import torch.nn as nn
import torch.optim as optim
import torch.utils.data
import torchvision.datasets as dset
import torchvision.transforms as transforms
import torchvision.utils as vutils
from torch.autograd import Variable
from generator import G
from discriminator import D
import os
from PIL import Image

batchSize = 64  # We set the size of the batch.
imageSize = 64  # We set the size of the generated images (64x64).
input_vector = 100
nb_epochs = 500
# Creating the transformations
transform = transforms.Compose([transforms.Resize((imageSize, imageSize)), transforms.ToTensor(),
                                transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5,
                                                                       0.5)), ])  # We create a list of transformations (scaling, tensor conversion, normalization) to apply to the input images.


def pil_loader_rgba(path: str) -&gt; Image.Image:
    with open(path, 'rb') as f:
        img = Image.open(f)
        return img.convert('RGBA')


# Loading the dataset
dataset = dset.ImageFolder(root='./data', transform=transform, loader=pil_loader_rgba)
dataloader = torch.utils.data.DataLoader(dataset, batch_size=batchSize, shuffle=True,
                                         num_workers=2)  # We use dataLoader to get the images of the training set batch by batch.


# Defining the weights_init function that takes as input a neural network m and that will initialize all its weights.
def weights_init(m):
    classname = m.__class__.__name__
    if classname.find('Conv') != -1:
        m.weight.data.normal_(0.0, 0.02)
    elif classname.find('BatchNorm') != -1:
        m.weight.data.normal_(1.0, 0.02)
        m.bias.data.fill_(0)


def is_cuda_available():
    return torch.cuda.is_available()


def is_gpu_available():
    if is_cuda_available():
        if int(torch.cuda.device_count()) &gt; 0:
            return True
        return False
    return False


# Create results directory
def create_dir(name):
    if not os.path.exists(name):
        os.makedirs(name)


# Creating the generator
netG = G(input_vector)
netG.apply(weights_init)

# Creating the discriminator
netD = D()
netD.apply(weights_init)

if is_gpu_available():
    netG.cuda()
    netD.cuda()

# Training the DCGANs

criterion = nn.BCELoss()
optimizerD = optim.Adam(netD.parameters(), lr=0.0002, betas=(0.5, 0.999))
optimizerG = optim.Adam(netG.parameters(), lr=0.0002, betas=(0.5, 0.999))

generator_model = 'generator_model'
discriminator_model = 'discriminator_model'


def save_model(epoch, model, optimizer, error, filepath, noise=None):
    if os.path.exists(filepath):
        os.remove(filepath)
    torch.save({
        'epoch': epoch,
        'model_state_dict': model.state_dict(),
        'optimizer_state_dict': optimizer.state_dict(),
        'loss': error,
        'noise': noise
    }, filepath)


def load_checkpoint(filepath):
    if os.path.exists(filepath):
        return torch.load(filepath)
    return None


def main():
    print(&quot;Device name : &quot; + torch.cuda.get_device_name(0))
    for epoch in range(nb_epochs):

        for i, data in enumerate(dataloader, 0):
            checkpointG = load_checkpoint(generator_model)
            checkpointD = load_checkpoint(discriminator_model)
            if checkpointG:
                print(&quot;checkpointG&quot;)
                netG.load_state_dict(checkpointG['model_state_dict'])
                optimizerG.load_state_dict(checkpointG['optimizer_state_dict'])
            if checkpointD:
                netD.load_state_dict(checkpointD['model_state_dict'])
                optimizerD.load_state_dict(checkpointD['optimizer_state_dict'])

            # 1st Step: Updating the weights of the neural network of the discriminator

            netD.zero_grad()

            # Training the discriminator with a real image of the dataset
            real, _ = data
            if is_gpu_available():
                print(&quot;True&quot;)
                input = Variable(real.cuda()).cuda()
                target = Variable(torch.ones(input.size()[0]).cuda()).cuda()
            else:
                input = Variable(real)
                target = Variable(torch.ones(input.size()[0]))
            output = netD(input)
            errD_real = criterion(output, target)

            # Training the discriminator with a fake image generated by the generator
            if is_gpu_available():
                noise = Variable(torch.randn(input.size()[0], input_vector, 1, 1)).cuda()
                target = Variable(torch.zeros(input.size()[0])).cuda()
            else:
                noise = Variable(torch.randn(input.size()[0], input_vector, 1, 1))
                target = Variable(torch.zeros(input.size()[0]))
            fake = netG(noise)
            output = netD(fake.detach())
            errD_fake = criterion(output, target)

            # Backpropagating the total error
            errD = errD_real + errD_fake
            errD.backward()
            optimizerD.step()

            # 2nd Step: Updating the weights of the neural network of the generator
            netG.zero_grad()
            if is_gpu_available():
                target = Variable(torch.ones(input.size()[0])).cuda()
            else:
                target = Variable(torch.ones(input.size()[0]))
            output = netD(fake)
            errG = criterion(output, target)
            errG.backward()
            optimizerG.step()

            # 3rd Step: Printing the losses and saving the real images and the generated images of the minibatch every 100 steps

            print('[%d/%d][%d/%d] Loss_D: %.4f Loss_G: %.4f' % (
            epoch, nb_epochs, i, len(dataloader), errD.data, errG.data))
            save_model(epoch, netG, optimizerG, errG, generator_model, noise)
            save_model(epoch, netD, optimizerD, errD, discriminator_model, noise)

            if i % 100 == 0:
                create_dir('results')
                vutils.save_image(real, '%s/real_samples.png' % &quot;./results&quot;, normalize=True)
                fake = netG(noise)
                vutils.save_image(fake.data, '%s/fake_samples_epoch_%03d.png' % (&quot;./results&quot;, epoch), normalize=True)


if __name__ == &quot;__main__&quot;:
    main()

But when I run my program I'm getting this error
Traceback (most recent call last):
  File &quot;.\gans.py&quot;, line 178, in &lt;module&gt;
    main()
  File &quot;.\gans.py&quot;, line 109, in main
    for i, data in enumerate(dataloader, 0):
  File &quot;C:\Users\Akila\anaconda3\lib\site-packages\torch\utils\data\dataloader.py&quot;, line 521, in __next__
    data = self._next_data()
  File &quot;C:\Users\Akila\anaconda3\lib\site-packages\torch\utils\data\dataloader.py&quot;, line 1203, in _next_data
    return self._process_data(data)
  File &quot;C:\Users\Akila\anaconda3\lib\site-packages\torch\utils\data\dataloader.py&quot;, line 1229, in _process_data
    data.reraise()
  File &quot;C:\Users\Akila\anaconda3\lib\site-packages\torch\_utils.py&quot;, line 425, in reraise
    raise self.exc_type(msg)
RuntimeError: Caught RuntimeError in DataLoader worker process 0.
Original Traceback (most recent call last):
  File &quot;C:\Users\Akila\anaconda3\lib\site-packages\torch\utils\data\_utils\worker.py&quot;, line 287, in _worker_loop
    data = fetcher.fetch(index)
  File &quot;C:\Users\Akila\anaconda3\lib\site-packages\torch\utils\data\_utils\fetch.py&quot;, line 44, in fetch
    data = [self.dataset[idx] for idx in possibly_batched_index]
  File &quot;C:\Users\Akila\anaconda3\lib\site-packages\torch\utils\data\_utils\fetch.py&quot;, line 44, in &lt;listcomp&gt;
    data = [self.dataset[idx] for idx in possibly_batched_index]
  File &quot;C:\Users\Akila\anaconda3\lib\site-packages\torchvision\datasets\folder.py&quot;, line 234, in __getitem__
    sample = self.transform(sample)
  File &quot;C:\Users\Akila\anaconda3\lib\site-packages\torchvision\transforms\transforms.py&quot;, line 60, in __call__
    img = t(img)
  File &quot;C:\Users\Akila\anaconda3\lib\site-packages\torch\nn\modules\module.py&quot;, line 1051, in _call_impl
    return forward_call(*input, **kwargs)
  File &quot;C:\Users\Akila\anaconda3\lib\site-packages\torchvision\transforms\transforms.py&quot;, line 221, in forward
    return F.normalize(tensor, self.mean, self.std, self.inplace)
  File &quot;C:\Users\Akila\anaconda3\lib\site-packages\torchvision\transforms\functional.py&quot;, line 335, in normalize
    tensor.sub_(mean).div_(std)
RuntimeError: The size of tensor a (4) must match the size of tensor b (3) at non-singleton dimension 0

I did a debugging and I found the issue is with this line
for i, data in enumerate(dataloader, 0):

IF I change this line --&gt; return img.convert('RGBA')
TO this --&gt; return img.convert('RGB')
program works fine.
But I can guarantee all of images have alpha channel.
Because my image_validator.py program prints nothing
I even tried running my main program with SINGLE image which has alpha channel still gives same error.
What am I doing wrong ?
How can I preserve transparency of my Images ?
I do NOT want to lose my transparency.

Regarding the error message

RuntimeError: The size of tensor a (4) must match the size of tensor b (3) at non-singleton dimension 0

would lead to suggest that there's a problem with this call: sample = self.transform(sample)
Indeed, the issue is you are using a T.Normalize transform which only expects three channels (you specified a mean and std for three channels only, not four).
transform = transforms.Compose([
   transforms.Resize((imageSize, imageSize)), 
   transforms.ToTensor(),
   transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5,0.5))])

Instead, you should provide a four-element tuple for both arguments. For example (this is an example, this might run but won't necessarily make sense... see explanation below):
    transforms.Normalize((0.5, 0.5, 0.5, 0.5), (0.5, 0.5,0.5, 0.5))])


Other than that, I should ask: do you know why you are using .5 for both parameters of mean and std? If not, chances are you are not using it properly. Please read about it on this answer and its applications.
