0

This is my GAN model code:

import torch
import torch.nn as nn
import torch.optim as optim
import torchvision.datasets as dset
import torchvision.transforms as transforms
from torchvision.utils import save_image
from torch.utils.data import DataLoader

# Define hyperparameters
batch_size = 1 # I am putting it as 1 bcoz I want to save the images 1 by 1 
image_size = 256 
num_epochs = 200
noise_dim = 50
lr = 0.0002
beta1 = 0.5

import torch
from torch.utils.data import Dataset, DataLoader
from torchvision import transforms
from PIL import Image
import glob
import os
import matplotlib.pyplot as plt
import numpy as np
import torchvision.utils as vutils

# Define a custom dataset for your SMT resistor x-ray images
class MyDataset(Dataset):
    def __init__(self, path):
        self.transforms = transforms.Compose([
            transforms.Resize((image_size,image_size)),  # resize to 64x64
            transforms.Grayscale(),  # convert to grayscale
            transforms.ToTensor(),  # convert to PyTorch tensor
            transforms.Normalize((0.5,), (0.5,))  # normalize to range [-1, 1]
        ])
        self.img_paths = sorted(glob.glob(os.path.join(path, '*.jpg')))  # get list of image paths

    def __getitem__(self, index):
        img_path = self.img_paths[index]
        img = Image.open(img_path)
        img = self.transforms(img)
        return img

    def __len__(self):
        return len(self.img_paths)

# Set the path to your dataset
data_path = path_images

# Initialize the custom dataset
dataset = MyDataset(data_path)

# Initialize the dataloader
dataloader = DataLoader(dataset, batch_size=batch_size, shuffle=False)

# Define the generator model
class Generator(nn.Module):
    def __init__(self):
        super(Generator, self).__init__()
        self.fc1 = nn.Linear(noise_dim, 128)
        self.fc2 = nn.Linear(128, 256)
        self.fc3 = nn.Linear(256, 512)
        self.fc4 = nn.Linear(512, image_size*image_size)

    def forward(self, x):
        x = x.view(x.size(0), -1)
        x = nn.functional.leaky_relu(self.fc1(x), 0.2)
        x = nn.functional.leaky_relu(self.fc2(x), 0.2)
        x = nn.functional.leaky_relu(self.fc3(x), 0.2)
        x = nn.functional.tanh(self.fc4(x))
        x = x.view(x.size(0), 1, image_size, image_size)
        return x

# Define the discriminator model
class Discriminator(nn.Module):
    def __init__(self):
        super(Discriminator, self).__init__()
        self.conv1 = nn.Conv2d(1, 64, 4, 2, 1)
        self.conv2 = nn.Conv2d(64, 128, 4, 2, 1)
        self.conv3 = nn.Conv2d(128, 256, 4, 2, 1)
        self.conv4 = nn.Conv2d(256, 512, 4, 2, 1)
        self.fc = nn.Linear(image_size//16*image_size//16*512, 1)

    def forward(self, x):
        x = nn.functional.leaky_relu(self.conv1(x), 0.2)
        x = nn.functional.leaky_relu(self.conv2(x), 0.2)
        x = nn.functional.leaky_relu(self.conv3(x), 0.2)
        x = nn.functional.leaky_relu(self.conv4(x), 0.2)
        x = x.view(-1, image_size//16*image_size//16*512)
        x = nn.functional.sigmoid(self.fc(x))
        return x

# Initialize networks
G = Generator().cuda()
D = Discriminator().cuda()

# Set the loss function and optimizer
criterion = nn.BCELoss()
optimizer_G = optim.Adam(G.parameters(), lr=lr, betas=(beta1, 0.999))
optimizer_D = optim.Adam(D.parameters(), lr=lr, betas=(beta1, 0.999))

print(G)
print(D)

# Create a directory to save the generated images
os.makedirs('generated_images', exist_ok=True)

# Start the training loop
for epoch in range(num_epochs):
    for i, images in enumerate(dataloader):
        # Initialize the noise vector
        noise = torch.randn(images.size(0), noise_dim, 1, 1).cuda()

        # Train the discriminator with real images
        D.zero_grad()
        real_images = images.cuda()
        real_labels = torch.ones((images.size(0), 1)).cuda()
        real_outputs = D(real_images)
        d_loss_real = criterion(real_outputs, real_labels.view(-1, 1))
        d_loss_real.backward()

        # Train the discriminator with fake images
        fake_images = G(noise).detach()
        fake_labels = torch.zeros((images.size(0), 1)).cuda()
        fake_outputs = D(fake_images)
        d_loss_fake = criterion(fake_outputs, fake_labels)
        d_loss_fake.backward()

        # Update the discriminator parameters
        d_loss = (d_loss_real + d_loss_fake) / 2
        optimizer_D.step()

        # Train the generator
        G.zero_grad()
        noise = torch.randn(images.size(0), noise_dim, 1, 1).cuda()
        fake_images = G(noise)
        fake_labels = torch.ones((images.size(0), 1)).cuda()
        fake_outputs = D(fake_images)
        g_loss = criterion(fake_outputs, fake_labels.view(-1, 1))
        g_loss.backward()
        optimizer_G.step()

        print(
                "[Epoch %d/%d] [Batch %d/%d] [D loss: %f] [G loss: %f]"
                % (epoch, num_epochs, i, len(dataloader), d_loss.item(), g_loss.item())
            )
     
        device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
        fixed_noise = torch.randn(batch_size, noise_dim, 1, 1).to(device)

        # Generate and save the images
        generated_images = G(fixed_noise)
        for j, img in enumerate(generated_images): # j = num of fake images
            save_image(img, f'generated_images/image_{epoch}_{i}_{j}.png')
                

The generated_images is only able to save the first image from my dataset. I don't know which part is playing the role to save all the generated images from the original images. For example, I have 5 images in my dataset. When comes to the training loop, the generated_images should be showing all the 5 fake images, but it only shows the fake image for the first original image. Please help me to look into the code. Thanks in advance!

My sample dataset Obviousely it only work for my 1st image

Candy
  • 21
  • 3

1 Answers1

0

to fix this, try move fixed_noise tensor creation outside of your training loop and create a separate loop for saving the generated images:

device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
fixed_noise = torch.randn(len(dataset), noise_dim, 1, 1).to(device)

# Start training loop
for epoch in range(num_epochs):
    for i, images in enumerate(dataloader):
        # .......(your existing training code) ...

        print(
                "[Epoch %d/%d] [Batch %d/%d] [D loss: %f] [G loss: %f]"
                % (epoch, num_epochs, i, len(dataloader), d_loss.item(), g_loss.item())
            )

    # Generate and save images 
    generated_images = G(fixed_noise)
    for j, img in enumerate(generated_images): # j = num of fake images
        save_image(img, f'generated_images/image_{epoch}_{j}.png')
  • Hi sir. It still remains unchanged. The generated image is only available for the first image of my dataset. Others are not able to be saved...and i realized that the j does not increases... – Candy Apr 24 '23 at 06:37
  • batch_size=1 and the shuffle = False. This causes the DataLoader to always return the first image in the dataset for each batch, and hence, only the first image is being processed and saved. Try to fix this set shuffle = True in the DataLoader. – Mr. RobotMaster Apr 24 '23 at 08:59
  • to save the images 1 by 1: save_image(img, f'generated_images/image_{epoch}_{j}.png', nrow=1) – Mr. RobotMaster Apr 24 '23 at 09:03
  • actually i want to train the images in sequence so i set the shuffle = False. however i have tried ur suggestion but it is still the same...it is only able to save the first training image, seems like other images failed to save, but the 'i' increases mean they actually have been trained successfully. – Candy Apr 24 '23 at 16:51