导入透明图像给出RuntimeError:张量a(4)的大小必须匹配张量b(3)在非单维0的大小 &



我正在尝试学习人工智能。我有GAN(生成对抗网络)代码与ALPHA通道(透明度)的图像。所有图像都有alpha通道。为了证明我编写了如下的小image_validator.py程序

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) != "RGBA":
print("alpha " + str(im.mode))
img_number = img_number+1
print(str(img_number))
except Exception as e:
print("Error : "+filename)

if __name__ == "__main__":
main()

上面的程序没有打印任何东西,这意味着所有的图像都有ALPHA通道。为了测试上面的程序,我添加了一个没有ALPHA通道的图像。所以我可以确认所有的图像都有ALPHA通道。

我的generator.py就像

下面
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

我的discriminator.py如下

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)

我的主程序gan.py如下图

# 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) -> 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()) > 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("Device name : " + 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("checkpointG")
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("True")
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' % "./results", normalize=True)
fake = netG(noise)
vutils.save_image(fake.data, '%s/fake_samples_epoch_%03d.png' % ("./results", epoch), normalize=True)

if __name__ == "__main__":
main()

但是当我运行程序时,我得到了这个错误

Traceback (most recent call last):
File ".gans.py", line 178, in <module>
main()
File ".gans.py", line 109, in main
for i, data in enumerate(dataloader, 0):
File "C:UsersAkilaanaconda3libsite-packagestorchutilsdatadataloader.py", line 521, in __next__
data = self._next_data()
File "C:UsersAkilaanaconda3libsite-packagestorchutilsdatadataloader.py", line 1203, in _next_data
return self._process_data(data)
File "C:UsersAkilaanaconda3libsite-packagestorchutilsdatadataloader.py", line 1229, in _process_data
data.reraise()
File "C:UsersAkilaanaconda3libsite-packagestorch_utils.py", line 425, in reraise
raise self.exc_type(msg)
RuntimeError: Caught RuntimeError in DataLoader worker process 0.
Original Traceback (most recent call last):
File "C:UsersAkilaanaconda3libsite-packagestorchutilsdata_utilsworker.py", line 287, in _worker_loop
data = fetcher.fetch(index)
File "C:UsersAkilaanaconda3libsite-packagestorchutilsdata_utilsfetch.py", line 44, in fetch
data = [self.dataset[idx] for idx in possibly_batched_index]
File "C:UsersAkilaanaconda3libsite-packagestorchutilsdata_utilsfetch.py", line 44, in <listcomp>
data = [self.dataset[idx] for idx in possibly_batched_index]
File "C:UsersAkilaanaconda3libsite-packagestorchvisiondatasetsfolder.py", line 234, in __getitem__
sample = self.transform(sample)
File "C:UsersAkilaanaconda3libsite-packagestorchvisiontransformstransforms.py", line 60, in __call__
img = t(img)
File "C:UsersAkilaanaconda3libsite-packagestorchnnmodulesmodule.py", line 1051, in _call_impl
return forward_call(*input, **kwargs)
File "C:UsersAkilaanaconda3libsite-packagestorchvisiontransformstransforms.py", line 221, in forward
return F.normalize(tensor, self.mean, self.std, self.inplace)
File "C:UsersAkilaanaconda3libsite-packagestorchvisiontransformsfunctional.py", 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

我做了一个调试,我发现问题是在这一行

for i, data in enumerate(dataloader, 0):

如果我改变这一行——>return img.convert('RGBA')到此为止——>return img.convert('RGB')

程序工作正常。但是我可以保证所有的图像都有alpha通道。因为我的image_validator.py程序没有打印任何东西

我甚至尝试运行我的主程序与单一图像有alpha通道仍然给出相同的错误。

我做错了什么?如何保持图像的透明度?我不想失去我的透明度。

关于错误信息

RuntimeError:张量a(4)的大小必须与张量b(3)在非单维0的大小相匹配

会提示这个调用有问题:sample = self.transform(sample)

实际上,问题是您正在使用仅期望三个通道的T.Normalize转换(您仅为三个通道指定了平均值和std,而不是四个通道)。

transform = transforms.Compose([
transforms.Resize((imageSize, imageSize)), 
transforms.ToTensor(),
transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5,0.5))])
相反,您应该为两个参数提供一个包含四个元素的元组。例如(这是一个例子,这可能运行,但不一定有意义…
transforms.Normalize((0.5, 0.5, 0.5, 0.5), (0.5, 0.5,0.5, 0.5))])

除此之外,我应该问:你知道为什么meanstd的参数都使用.5吗?如果不是,很可能你没有正确地使用它。请阅读这个答案及其应用。

最新更新