After training a GAN for 40 epochs it still generates random noise as output. Can anyone pls tell me what’s wrong here coz i can’t see whats wrong.
I mean even if 40 epochs is not enough it should still be able to generate sth better than random noise don’t you think ?
import numpy as np
from tqdm import tqdm
import os, cv2, torch
import torch.nn as nn
from torchvision.utils import save_image
import random
import matplotlib.pyplot as plt
#Data preprocessing
data = []
def dataPreprocessor(raw_data_path, save_data_path):
for single_data in tqdm(os.listdir(raw_data_path)):
try:
img = os.path.join(raw_data_path, single_data)
img = cv2.imread(img)
img = cv2.resize(img, (64, 64))
img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
img = np.array(img)
data.append([img])
except Exception as e:
pass
np.random.shuffle(data)
np.save(save_data_path, data, allow_pickle=True)
device = torch.device('cuda' if torch.cuda.is_available() == True else 'cpu')
raw_data_path = 'raw_data/training_data'
train_path = 'processed_data/training_dataset/train_dataset.npy'
saved_model_path = 'saved_model/DCGAN_network.pth.tar'
#Hyper-parameters
in_channels_D = 1
out_channels_D = 1
in_noise_channels_G = 256
out_channels_G = in_channels_D
lr = 0.0002
EPOCHS = 40
fake_label = 0 #~0
real_label = 1 #~1
num_of_eval_data = 3
real_desc_loss = []
fake_desc_loss = []
Generator_loss = []
def save_model(model, path=saved_model_path):
print('Saving model.......')
torch.save(model, path)
print('AI model has been saved.....')
def trainData():
if not os.path.isfile(train_path):
print("Preprocessing Data....... ")
dataPreprocessor(raw_data_path=raw_data_path, save_data_path=train_path)
else:
pass
trainData()
from neuralNets import Descriminator, Generator
DescNet = Descriminator(in_channels_D, out_channels_D).to(device=device)
GenNet = Generator(in_noise_channels_G, out_channels_G).to(device=device)
import torch.optim as optim
optimizer_D = optim.Adam(DescNet.parameters(), lr=lr, betas=(0.5, 0.999))
optimizer_G = optim.Adam(GenNet.parameters(), lr=lr, betas=(0.5, 0.999))
lossFunc = nn.BCELoss()
def dataLoader(path):
data = np.load(path, allow_pickle=True)
X = np.array([i[0] for i in data])
X = X.reshape(len(X), 64, 64, -1)
X = X.transpose(0, 3, 1, 2)
X = torch.Tensor(X)
X = X/255
return X
def Save_training_instances(save_data, directory, path):
cv2.imwrite(f'{os.path.join(directory, path)}', save_data)
def trainProcess(epochs, BATCH_SIZE = 60):
if not os.path.isfile(saved_model_path):
epoch_tab = []
Gen_loss = np.array([])
D_real_loss = np.array([])
D_fake_loss = np.array([])
X = dataLoader(path=train_path)
for epoch in range(epochs):
epoch_tab.append(epochs)
for imgs in tqdm(range(0, len(X), BATCH_SIZE)):
X_batch = X[imgs:imgs+BATCH_SIZE].to(device=device)
noise = torch.randn(X_batch.shape[0], in_noise_channels_G, 1, 1).to(device=device)
real_target = torch.Tensor(X_batch.shape[0], 1).fill_(real_label).to(device=device)
fake_target = torch.Tensor(X_batch.shape[0], 1).fill_(fake_label).to(device=device)
#Train Descriminator
DescNet.zero_grad()
real_output = DescNet(X_batch)
real_loss = lossFunc(real_output, real_target*0.9)
r'the gradient of the output of the generator is detached,\
while training the Descriminator to prevent back_prop on it'
G_output = GenNet(noise)
fake_output = DescNet(G_output.detach())
fake_loss = lossFunc(fake_output, fake_target*0.1)
D_loss = real_loss + fake_loss
D_loss.backward()
optimizer_D.step()
#Train Generator
GenNet.zero_grad()
D_output = DescNet(G_output)
G_loss = lossFunc(D_output, real_target)
optimizer_G.step()
#append losses
D_real_loss = np.append(D_real_loss, real_loss.data)
D_fake_loss = np.append(D_fake_loss, fake_loss.data)
Gen_loss = np.append(Gen_loss, G_loss.data)
if epoch % 2 == 0:
save_image(G_output[:20], f'output/{epoch}.jpg', nrow=5, normalize=True)
real_desc_loss.append(np.mean(D_real_loss))
fake_desc_loss.append(np.mean(D_fake_loss))
Generator_loss.append(np.mean(Gen_loss))
print(f'epoch: {epoch+1}\t desc_real_loss:{np.mean(D_real_loss)}\t \
desc_fake_loss: {np.mean(D_fake_loss)}\t Gen_loss: {np.mean(Gen_loss)}')
D_real_loss = np.array([])
D_fake_loss = np.array([])
Gen_loss = np.array([])
model_state = {'Gen_model':GenNet.state_dict(), 'Gen_optimizer':optimizer_D.state_dict(),
'Desc_model':DescNet.state_dict(),'Desc_optimizer':optimizer_D.state_dict(),
'loss_func':lossFunc.state_dict()}
save_model(model_state)
else:
pass
def evalProcess(no_img):
fixed_input_noise = torch.randn(no_img, in_noise_channels_G, 1, 1).to(device=device)
with torch.no_grad():
model_data = torch.load(saved_model_path)
Gen_model = Generator(in_noise_channels_G, out_channels_G)
Gen_model.load_state_dict(model_data['Gen_model'])
Gen_model.eval().to(device=device)
for num, img in zip(range(no_img), fixed_input_noise):
img = img.to(device=device)
img = img.view(1, in_noise_channels_G, 1, 1)
output_img = Gen_model(img)
output_img = output_img.detach()
output_img = np.array(output_img*255)
output_img = output_img.transpose(0, 2, 3, 1)
#output_img = cv2.cvtColor(output_img, cv2.COLOR_GRAY2RGB)
cv2.imshow(f'data{num}', output_img[0])
cv2.waitKey(0)
trainProcess(EPOCHS)
evalProcess(num_of_eval_data)
Also here’s how my neural network looks like.
import torch
import torch.nn as nn
class Descriminator(nn.Module):
def __init__(self, in_channels, out_channels):
super(Descriminator, self).__init__()
self.in_channels = in_channels
self.out_channels = out_channels
self.layer1 = nn.Sequential(
nn.Conv2d(self.in_channels, 256,
kernel_size=4, stride=2, padding=1,
bias=False),
nn.LeakyReLU(0.2)
)
self.layer2 = nn.Sequential(
nn.Conv2d(256, 512,
kernel_size=4, stride=2, padding=1,
bias=False),
nn.BatchNorm2d(512),
nn.LeakyReLU(0.2)
)
self.layer3 = nn.Sequential(
nn.Conv2d(512, 1024,
kernel_size=4, stride=2, padding=1,
bias=False),
nn.BatchNorm2d(1024),
nn.LeakyReLU(0.2)
)
self.layer4 = nn.Sequential(
nn.Conv2d(1024, 2048,
kernel_size=4, stride=2, padding=1,
bias=False),
nn.BatchNorm2d(2048),
nn.LeakyReLU(0.2)
)
self.layer5 = nn.Sequential(
nn.Conv2d(2048, 4096,
kernel_size=4, stride=1, padding=0,
bias=False),
nn.BatchNorm2d(4096),
nn.LeakyReLU(0.2)
)
self._linear_shape = 4096*1*1
self.layer6 = nn.Sequential(
nn.Linear(self._linear_shape, self.out_channels),
nn.Sigmoid()
)
def convs_fwd(self, x):
output = self.layer1(x)
output = self.layer2(output)
output = self.layer3(output)
output = self.layer4(output)
output = self.layer5(output)
return output
def forward(self, input):
output = self.convs_fwd(input)
output = output.view(-1, self._linear_shape)
output = self.layer6(output)
return output
class Generator(nn.Module):
def __init__(self, noise_channels, out_channels):
super(Generator, self).__init__()
self.noise_channel = noise_channels
self.out_channels = out_channels
self.layer1 = nn.Sequential(
nn.ConvTranspose2d(noise_channels, 1024,
kernel_size=4, stride=1, padding=0,
bias=False),
nn.BatchNorm2d(1024),
nn.ReLU(True)
)
self.layer2 = nn.Sequential(
nn.ConvTranspose2d(1024, 512,
kernel_size=4, stride=2, padding=1,
bias=False),
nn.BatchNorm2d(512),
nn.ReLU(True)
)
self.layer3 = nn.Sequential(
nn.ConvTranspose2d(512, 256,
kernel_size=4, stride=2, padding=1,
bias=False),
nn.BatchNorm2d(256),
nn.ReLU(True)
)
self.layer4 = nn.Sequential(
nn.ConvTranspose2d(256, 128,
kernel_size=4, stride=2, padding=1,
bias=False),
nn.BatchNorm2d(128),
nn.ReLU(True)
)
self.layer5 = nn.Sequential(
nn.ConvTranspose2d(128, self.out_channels,
kernel_size=4, stride=2, padding=1,
bias=False),
nn.Tanh()
)
def forward(self, input):
output = self.layer1(input)
output = self.layer2(output)
output = self.layer3(output)
output = self.layer4(output)
output = self.layer5(output)
return output
Btw my dataset is .jpg format of the mnist handwritten digits quantized to a .npy file
Someone should pls help me out here